OpenHarmony设备使用统计深度实战:从数据埋点到信息采集的全链路方案

在 OpenHarmony 中,Device Usage Statistics(设备使用模块)主要负责 采集、统计和记录系统中各种软硬件资源的使用情况,为系统优化、应用管理、电量/性能分析、用户行为分析等提供数据支持。

即统计APP使用量、客流量、用户记录等。

1. 系统架构与核心组件

功能 说明
资源使用监控 实时统计 CPU、内存、存储、网络、传感器等硬件资源的使用量和占用时长。
应用行为记录 记录应用启动次数、运行时长、前后台切换、崩溃信息等。
用户行为分析 统计用户解锁频率、应用偏好、设备使用时段等,用于智能推荐或系统调优。
电量与性能追踪 关联资源使用与电量消耗,识别高耗电模块,辅助功耗优化。
数据上报与查询接口 向系统服务或上层应用提供查询接口,支持数据可视化或云端同步。

1.1 整体架构源码结构

文件路径:
foundation/resourceschedule/device_usage_statistics/


foundation/resourceschedule/device_usage_statistics/
├── services/common/include/           # 服务层头文件
│   ├── bundle_active_service.h        # 主服务类 
│   ├── bundle_active_core.h          # 核心业务逻辑
│   └── bundle_active_usage_database.h # 数据库操作
├── services/common/src/              # 服务层实现
│   ├── bundle_active_service.cpp     # 服务实现 
│   ├── bundle_active_core.cpp        # 核心业务实现
│   └── bundle_active_usage_database.cpp
├── interfaces/innerkits/include/     # 对内接口
│   ├── bundle_active_client.h        # 客户端接口 
│   ├── bundle_active_event.h         # 事件定义 
│   ├── bundle_active_package_stats.h # 统计信息定义 
│   └── bundle_active_module_record.h # 模块记录定义
├── sa_profile/1907.json              # SA配置文件 
└── test/                             # 测试目录

1.2 核心类关系

2. 核心数据结构

2.1 事件数据结构

文件:
foundation/resourceschedule/device_usage_statistics/interfaces/innerkits/include/bundle_active_event.h


namespace OHOS {
namespace DeviceUsageStats {
class BundleActiveEvent : public Parcelable {
public:
    // 事件类型定义
    static const int32_t ABILITY_FOREGROUND = 2;      // 应用进入前台
    static const int32_t ABILITY_BACKGROUND = 3;      // 应用进入后台
    static const int32_t ABILITY_STOP = 4;           // 应用销毁
    static const int32_t LONG_TIME_TASK_STARTTED = 5; // 长时任务开始
    static const int32_t LONG_TIME_TASK_ENDED = 6;    // 长时任务结束
    static const int32_t SYSTEM_INTERACTIVE = 7;      // 系统交互
    static const int32_t USER_INTERACTIVE = 8;        // 用户交互
    static const int32_t END_OF_THE_DAY = 9;        // 日结束
    static const int32_t SHUTDOWN = 10;               // 关机
    static const int32_t STARTUP = 11;                // 启动
    static const int32_t FLUSH = 12;                  // 数据刷新
    static const int32_t SCREEN_INTERACTIVE = 13;     // 屏幕交互
    static const int32_t SCREEN_NON_INTERACTIVE = 14; // 屏幕无交互
    static const int32_t FORM_IS_CLICKED = 15;        // 卡片点击
    static const int32_t FORM_IS_REMOVED = 16;        // 卡片移除
    static const int32_t KEYGUARD_SHOWN = 17;         // 锁屏显示
    static const int32_t KEYGUARD_HIDDEN = 18;       // 锁屏隐藏
    static const int32_t NOTIFICATION_SEEN = 19;      // 通知查看
    static const int32_t SYSTEM_LOCK = 20;           // 系统锁定
    static const int32_t SYSTEM_UNLOCK = 21;          // 系统解锁
    static const int32_t SYSTEM_SLEEP = 22;          // 系统休眠
    static const int32_t SYSTEM_WAKEUP = 23;         // 系统唤醒

    // 数据成员
    std::string bundleName_;           // 应用包名
    std::string continuousTaskAbilityName_; // 长时任务能力名
    std::string abilityName_;          // 能力名
    std::string abilityId_;           // 能力ID
    std::string moduleName_;          // 模块名
    std::string formName_;            // 卡片名
    int32_t formDimension_;           // 卡片维度
    int64_t formId_;                 // 卡片ID
    int64_t timeStamp_;              // 时间戳
    int32_t eventId_;                // 事件ID
    int32_t uid_;                    // 用户ID
};
}  // namespace DeviceUsageStats
}  // namespace OHOS

2.2 包统计信息结构

文件:
foundation/resourceschedule/device_usage_statistics/interfaces/innerkits/include/bundle_active_package_stats.h


namespace OHOS {
namespace DeviceUsageStats {
class BundleActivePackageStats : public Parcelable {
public:
    std::string bundleName_;           // 应用包名
    int64_t beginTimeStamp_;         // 统计开始时间
    int64_t endTimeStamp_;           // 统计结束时间
    int64_t lastTimeUsed_;           // 最后使用时间
    int64_t totalInFrontTime_;       // 前台总时间
    int64_t lastContiniousTaskUsed_; // 最后长时任务使用时间
    int64_t totalContiniousTaskUsedTime_; // 长时任务总使用时间
    int32_t startCount_;             // 启动次数
    int32_t bundleStartedCount_;     // 应用启动次数
    int32_t lastEvent_;              // 最后事件
    int32_t userId_;                 // 用户ID
    int32_t uid_;                    // UID
    int32_t appIndex_;               // 应用索引
    
    // 能力事件映射
    std::map<std::string, int32_t> abilities_;      // key: abilityId, value: 最后事件
    std::map<std::string, int32_t> longTimeTasks_;   // key: 长时任务名, value: 最后事件
};
}  // namespace DeviceUsageStats
}  // namespace OHOS

2.3 模块使用记录结构

文件:
foundation/resourceschedule/device_usage_statistics/interfaces/innerkits/include/bundle_active_module_record.h


namespace OHOS {
namespace DeviceUsageStats {
class BundleActiveModuleRecord : public Parcelable {
public:
    std::string bundleName_;    // 应用包名
    std::string moduleName_;  // 模块名
    int64_t lastUsedTime_;    // 最后使用时间
    int64_t totalUsedTime_;   // 总使用时间
    int32_t launchCount_;     // 启动次数
    int32_t userId_;         // 用户ID
    std::string deviceId_;    // 设备ID
};
}  // namespace DeviceUsageStats
}  // namespace OHOS

3. 系统服务配置

3.1 SA配置

文件:
foundation/resourceschedule/device_usage_statistics/sa_profile/1907.json


{
    "process": "bgtaskmgr_service",
    "systemability": [
        {
            "name": 1907,
            "libpath": "libusagestatservice.z.so",
            "run-on-create": true,
            "depend_time_out": 60000,
            "distributed": false,
            "dump_level": 1
        }
    ]
}

3.2 服务启动流程

文件:
foundation/resourceschedule/device_usage_statistics/services/common/src/bundle_active_service.cpp


// 关键常量定义
static const int32_t DEVICE_USAGE_STATISTICS_SYS_ABILITY_ID = 1907;
static const std::string NEEDED_PERMISSION = "ohos.permission.BUNDLE_ACTIVE_INFO";

// 服务启动流程
void BundleActiveService::OnStart() {
    BUNDLE_ACTIVE_LOGI("OnStart() called");
    if (ready_) {
        BUNDLE_ACTIVE_LOGI("service is ready. nothing to do.");
        return;
    }
    std::shared_ptr<BundleActiveService> service = shared_from_this();
    ffrt::submit([service]() {
        service->InitNecessaryState();
    });
}

void BundleActiveService::InitNecessaryState() {
    std::set<int32_t> serviceIdSets{
        APP_MGR_SERVICE_ID, 
        BUNDLE_MGR_SERVICE_SYS_ABILITY_ID, 
        POWER_MANAGER_SERVICE_ID, 
        COMMON_EVENT_SERVICE_ID,
        BACKGROUND_TASK_MANAGER_SERVICE_ID, 
        TIME_SERVICE_ID,
    };
    
    // 检查依赖服务
    for (const auto& serviceItem : serviceIdSets) {
        auto checkResult = systemAbilityManager->CheckSystemAbility(serviceItem);
        if (!checkResult) {
            // 延迟重试
            ffrt::submit([service]() {
                service->InitNecessaryState();
            }, ffrt::task_attr().delay(DELAY_TIME));
            return;
        }
    }
    
    InitService();
    ready_ = true;
    int32_t ret = Publish(DelayedSingleton<BundleActiveService>::GetInstance().get());
}

4. 核心接口

4.1 客户端接口

文件:
foundation/resourceschedule/device_usage_statistics/interfaces/innerkits/include/bundle_active_client.h


namespace OHOS {
namespace DeviceUsageStats {
class BundleActiveClient {
public:
    static BundleActiveClient& GetInstance();
    
    // 事件上报
    ErrCode ReportEvent(BundleActiveEvent event, const int32_t userId);
    
    // 查询接口
    ErrCode IsBundleIdle(bool& isBundleIdle, const std::string& bundleName, int32_t userId = -1);
    
    ErrCode QueryBundleStatsInfoByInterval(
        std::vector<BundleActivePackageStats>& bundleActivePackageStats,
        const int32_t intervalType, const int64_t beginTime, const int64_t endTime, int32_t userId = -1);
    
    ErrCode QueryBundleEvents(
        std::vector<BundleActiveEvent>& bundleActiveEvents, 
        const int64_t beginTime, const int64_t endTime, int32_t userId = -1);
    
    ErrCode QueryModuleUsageRecords(
        int32_t maxNum, std::vector<BundleActiveModuleRecord>& results, int32_t userId = -1);
    
    ErrCode SetAppGroup(std::string bundleName, const int32_t newGroup, int32_t userId = -1);
    
    // 设备事件统计
    ErrCode QueryDeviceEventStats(
        int64_t beginTime, int64_t endTime,
        std::vector<BundleActiveEventStats>& eventStats, int32_t userId = -1);
    
    ErrCode QueryNotificationEventStats(
        int64_t beginTime, int64_t endTime,
        std::vector<BundleActiveEventStats>& eventStats, int32_t userId = -1);
        
    // 回调注册
    ErrCode RegisterAppGroupCallBack(const sptr<IAppGroupCallback>& observer);
    ErrCode UnRegisterAppGroupCallBack(const sptr<IAppGroupCallback>& observer);
    
private:
    static const int32_t MAXNUM_UP_LIMIT = 1000; // 最大查询数量限制
};
}  // namespace DeviceUsageStats
}  // namespace OHOS

4.2 服务端接口实现

文件:
foundation/resourceschedule/device_usage_statistics/services/common/src/bundle_active_service.cpp


// 关键实现
ErrCode BundleActiveService::ReportEvent(const BundleActiveEvent& event, int32_t userId) {
    // 权限检查
    if (!CheckCallingPermission(NEEDED_PERMISSION)) {
        return ERR_BUNDLE_ACTIVE_PERMISSION_DENIED;
    }
    
    return bundleActiveCore_->ReportEvent(event, userId);
}

ErrCode BundleActiveService::QueryBundleStatsInfoByInterval(
    std::vector<BundleActivePackageStats>& packageStats,
    const int32_t intervalType, const int64_t beginTime, const int64_t endTime, int32_t userId) {
    
    if (!CheckCallingPermission(NEEDED_PERMISSION)) {
        return ERR_BUNDLE_ACTIVE_PERMISSION_DENIED;
    }
    
    return bundleActiveCore_->QueryBundleStatsInfoByInterval(
        packageStats, intervalType, beginTime, endTime, userId);
}

5. 数据库结构

5.1 数据库表结构

文件:
foundation/resourceschedule/device_usage_statistics/services/common/include/bundle_active_usage_database.h

主要数据表:


events
: 事件记录表
packages
: 包统计信息表
modules
: 模块使用记录表
app_groups
: 应用分组表

5.2 数据存储策略

文件:
foundation/resourceschedule/device_usage_statistics/services/common/src/bundle_active_core.cpp


// 数据刷新策略
void BundleActiveCore::FlushData() {
    // 每隔30分钟刷新一次
    // 系统时间变更时刷新
    // 跨天时刷新
}

// 数据清理策略
void BundleActiveCore::CleanupOldData() {
    // 保留365天的数据
    // 定期清理过期数据
}

6. 设备使用上报事件

6.1 事件上报


#include "bundle_active_client.h"

void ReportAppEvent(const std::string& bundleName, int32_t eventId) {
    OHOS::DeviceUsageStats::BundleActiveEvent event(
        eventId, bundleName, getuid());
    event.timeStamp_ = std::chrono::duration_cast<std::chrono::milliseconds>(
        std::chrono::system_clock::now().time_since_epoch()).count();
    
    auto& client = OHOS::DeviceUsageStats::BundleActiveClient::GetInstance();
    client.ReportEvent(event, getuid());
}

ReportAppEvent("com.ohos.DeviceHapUsage", 
    OHOS::DeviceUsageStats::BundleActiveEvent::ABILITY_FOREGROUND);

6.2 查询使用统计


#include "bundle_active_client.h"

std::vector<OHOS::DeviceUsageStats::BundleActivePackageStats> 
QueryAppUsageStats(int64_t beginTime, int64_t endTime) {
    std::vector<OHOS::DeviceUsageStats::BundleActivePackageStats> stats;
    auto& client = OHOS::DeviceUsageStats::BundleActiveClient::GetInstance();
    
    // 查询日统计数据
    client.QueryBundleStatsInfoByInterval(
        stats, 0, beginTime, endTime, getuid());
    
    return stats;
}

6.3 查询事件记录


#include "bundle_active_client.h"

std::vector<OHOS::DeviceUsageStats::BundleActiveEvent> 
QueryAppEvents(const std::string& bundleName, 
               int64_t beginTime, int64_t endTime) {
    std::vector<OHOS::DeviceUsageStats::BundleActiveEvent> events;
    auto& client = OHOS::DeviceUsageStats::BundleActiveClient::GetInstance();
    
    client.QueryBundleEvents(events, beginTime, endTime, getuid());
    
    return events;
}

7. 系统能力ID和权限

7.1 系统能力ID

设备使用统计服务: 1907

7.2 所需权限

必需权限:
ohos.permission.BUNDLE_ACTIVE_INFO

7.3 依赖服务

APP_MGR_SERVICE_ID (1000)BUNDLE_MGR_SERVICE_SYS_ABILITY_ID (401)POWER_MANAGER_SERVICE_ID (3301)COMMON_EVENT_SERVICE_ID (2101)BACKGROUND_TASK_MANAGER_SERVICE_ID (2020)TIME_SERVICE_ID (2901)

8. 调试和验证

8.1 验证服务状态


# 检查服务是否运行
hdc shell "hidumper -ls 1907"

# 查看服务日志
hdc shell "hilog | grep BundleActive"

8.2 数据验证


// 验证数据是否正确存储
bool ValidateDatabase() {
    auto& client = OHOS::DeviceUsageStats::BundleActiveClient::GetInstance();
    
    // 查询最近的事件
    int64_t endTime = std::chrono::duration_cast<std::chrono::milliseconds>(
        std::chrono::system_clock::now().time_since_epoch()).count();
    int64_t beginTime = endTime - 24 * 60 * 60 * 1000; // 24小时前
    
    std::vector<OHOS::DeviceUsageStats::BundleActiveEvent> events;
    client.QueryBundleEvents(events, beginTime, endTime, getuid());
    
    return !events.empty();
}
© 版权声明
THE END
如果内容对您有所帮助,就支持一下吧!
点赞0 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容