跨设备FA启动速度测试工具设计与实现 原创

进修的泡芙
发布于 2025-6-17 20:35
浏览
0收藏

跨设备FA启动速度测试工具设计与实现

一、项目概述

基于HarmonyOS分布式能力构建的跨设备FA(Feature Ability)启动速度测试工具,可测量同一FA在不同设备上的启动耗时,并分析性能差异。借鉴《鸿蒙跨端U同步》中的设备协同机制,实现多设备测试任务的同步执行与结果收集。

二、架构设计

±--------------------+
测试控制端
(Test Controller)

±---------±---------+
±---------v----------+ ±--------------------+

分布式任务调度 <—> 被测设备集群
(Task Scheduler) (Device Cluster)

±---------±---------+ ±--------------------+
±---------v----------+

数据分析可视化
(Data Analytics)

±--------------------+

三、核心代码实现
测试控制端实现

// 测试控制端Ability
public class TestControllerAbility extends Ability {
private static final String TAG = “TestController”;
private DistributedScheduler scheduler;
private List<DeviceInfo> testDevices = new ArrayList<>();
private Map<String, TestResult> results = new ConcurrentHashMap<>();

@Override
public void onStart(Intent intent) {
    super.onStart(intent);
    setUIContent(ResourceTable.Layout_controller_layout);
    
    // 初始化分布式调度器
    scheduler = DistributedScheduler.getInstance(this);
    
    // 获取可用设备列表
    discoverDevices();
    
    // 设置测试按钮点击事件
    findComponentById(ResourceTable.Id_start_test).setClickedListener(component -> {
        startTestOnAllDevices();
    });

// 发现周边设备

private void discoverDevices() {
    DeviceManager deviceManager = DeviceManager.getInstance(this);
    deviceManager.discoverDevices(new DeviceDiscoveryCallback() {
        @Override
        public void onDeviceFound(DeviceInfo device) {
            if (device.getDeviceType() != DeviceType.PHONE) return;
            
            getUITaskDispatcher().asyncDispatch(() -> {
                testDevices.add(device);
                updateDeviceListUI();
            });

@Override

        public void onDiscoveryFailed(int errorCode) {
            HiLog.error(TAG, "Device discovery failed: " + errorCode);

});

// 在所有设备上启动测试

private void startTestOnAllDevices() {
    String testAbility = "com.example.testfa.MainAbility";
    String bundleName = "com.example.testfa";
    
    for (DeviceInfo device : testDevices) {
        TestTask task = new TestTask();
        task.setTargetAbility(testAbility);
        task.setBundleName(bundleName);
        task.setDeviceId(device.getDeviceId());
        
        scheduler.executeTask(device.getDeviceId(), task, new TestCallback());

}

// 测试任务类
public static class TestTask extends DistributedScheduler.BaseTask {
    private String targetAbility;
    private String bundleName;
    
    // Getters & Setters
    public String getTargetAbility() { return targetAbility; }
    public void setTargetAbility(String targetAbility) { this.targetAbility = targetAbility; }
    public String getBundleName() { return bundleName; }
    public void setBundleName(String bundleName) { this.bundleName = bundleName; }

// 测试回调

private class TestCallback implements DistributedScheduler.TaskCallback {
    @Override
    public void onSuccess(String deviceId, DistributedScheduler.BaseTask task) {
        TestResult result = (TestResult) task;
        results.put(deviceId, result);
        
        getUITaskDispatcher().asyncDispatch(() -> {
            updateResultsUI();
        });

@Override

    public void onFailure(String deviceId, int errorCode) {
        HiLog.error(TAG, "Test failed on device " + deviceId + ", error: " + errorCode);

}

// 更新UI显示测试结果
private void updateResultsUI() {
    // 实现结果可视化展示

}

测试执行端实现

// 测试执行端Ability
public class TestExecutorAbility extends Ability {
private static final String TAG = “TestExecutor”;
private DistributedScheduler scheduler;

@Override
public void onStart(Intent intent) {
    super.onStart(intent);
    
    // 注册测试任务处理器
    scheduler = DistributedScheduler.getInstance(this);
    scheduler.registerTaskHandler(TestControllerAbility.TestTask.class, new TestHandler());

// 测试任务处理器

private class TestHandler implements DistributedScheduler.TaskHandler {
    @Override
    public DistributedScheduler.BaseTask onExecute(String deviceId, DistributedScheduler.BaseTask task) {
        TestControllerAbility.TestTask testTask = (TestControllerAbility.TestTask) task;
        
        // 记录开始时间
        long startTime = System.currentTimeMillis();
        
        // 启动目标FA
        Intent intent = new Intent();
        Operation operation = new Intent.OperationBuilder()
            .withDeviceId("")
            .withBundleName(testTask.getBundleName())
            .withAbilityName(testTask.getTargetAbility())
            .build();
        intent.setOperation(operation);
        
        startAbility(intent);
        
        // 记录结束时间
        long endTime = System.currentTimeMillis();
        long duration = endTime - startTime;
        
        // 返回测试结果
        TestResult result = new TestResult();
        result.setDuration(duration);
        result.setDeviceId(deviceId);
        result.setSuccess(true);
        
        return result;

}

// 测试结果类
public static class TestResult extends DistributedScheduler.BaseTask {
    private long duration;
    private boolean success;
    
    // Getters & Setters
    public long getDuration() { return duration; }
    public void setDuration(long duration) { this.duration = duration; }
    public boolean isSuccess() { return success; }
    public void setSuccess(boolean success) { this.success = success; }

}

分布式任务调度服务

// 分布式任务调度服务
public class DistributedScheduler {
private static final String SCHEDULER_CHANNEL = “test_scheduler”;
private static DistributedScheduler instance;
private DistributedDataManager dataManager;
private Map<Class<?>, TaskHandler> handlers = new ConcurrentHashMap<>();

private DistributedScheduler(Context context) {
    this.dataManager = DistributedDataManagerFactory.getInstance()
        .createDistributedDataManager(context);

public static synchronized DistributedScheduler getInstance(Context context) {

    if (instance == null) {
        instance = new DistributedScheduler(context);

return instance;

// 注册任务处理器

public <T extends BaseTask> void registerTaskHandler(Class<T> taskClass, TaskHandler handler) {
    handlers.put(taskClass, handler);
    
    // 监听任务请求
    dataManager.registerDataChangeListener(SCHEDULER_CHANNEL, new DataChangeListener() {
        @Override
        public void onDataChanged(String deviceId, String key, String value) {
            try {
                JSONObject json = new JSONObject(value);
                String taskType = json.getString("taskType");
                
                Class<?> type = Class.forName(taskType);
                TaskHandler handler = handlers.get(type);
                if (handler != null) {
                    BaseTask task = (BaseTask) GsonUtils.fromJson(value, type);
                    BaseTask result = handler.onExecute(deviceId, task);
                    
                    // 返回结果
                    dataManager.putString(SCHEDULER_CHANNEL + "_result", 
                        GsonUtils.toJson(result));

} catch (Exception e) {

                HiLog.error(TAG, "Task handling error: " + e.getMessage());

}

    });

// 执行远程任务

public void executeTask(String deviceId, BaseTask task, TaskCallback callback) {
    try {
        JSONObject json = new JSONObject(GsonUtils.toJson(task));
        json.put("taskType", task.getClass().getName());
        
        dataManager.putString(SCHEDULER_CHANNEL, json.toString());
        
        // 监听结果
        dataManager.registerDataChangeListener(SCHEDULER_CHANNEL + "_result", 
            new DataChangeListener() {
                @Override
                public void onDataChanged(String senderId, String key, String value) {
                    BaseTask result = GsonUtils.fromJson(value, task.getClass());
                    callback.onSuccess(senderId, result);
                    dataManager.unregisterDataChangeListener(this);

});

catch (JSONException e) {

        callback.onFailure(deviceId, -1);

}

// 基础任务类
public static abstract class BaseTask {
    // 可添加公共字段

// 任务处理器接口

public interface TaskHandler {
    BaseTask onExecute(String deviceId, BaseTask task);

// 任务回调接口

public interface TaskCallback {
    void onSuccess(String deviceId, BaseTask task);
    void onFailure(String deviceId, int errorCode);

}

测试结果可视化

// 测试结果展示AbilitySlice
public class ResultAnalysisSlice extends AbilitySlice {
private Map<String, TestExecutorAbility.TestResult> results;
private BarChartView chartView;

@Override
public void onStart(Intent intent) {
    super.onStart(intent);
    setUIContent(ResourceTable.Layout_result_layout);
    
    // 获取测试结果
    results = intent.getSerializableParam("results");
    
    // 初始化图表
    chartView = (BarChartView) findComponentById(ResourceTable.Id_result_chart);
    displayResults();

private void displayResults() {

    List<BarChartView.BarData> bars = new ArrayList<>();
    
    for (Map.Entry<String, TestExecutorAbility.TestResult> entry : results.entrySet()) {
        String deviceName = DeviceInfo.getDeviceName(entry.getKey());
        long duration = entry.getValue().getDuration();
        
        BarChartView.BarData bar = new BarChartView.BarData();
        bar.setLabel(deviceName);
        bar.setValue(duration);
        bar.setColor(getDeviceColor(entry.getKey()));
        
        bars.add(bar);

chartView.setData(bars);

    chartView.setYAxisLabel("启动时间(ms)");
    chartView.startAnimation();

private int getDeviceColor(String deviceId) {

    // 为不同设备分配不同颜色
    int hash = deviceId.hashCode();
    return Color.rgb(
        (hash & 0xFF0000) >> 16,
        (hash & 0x00FF00) >> 8,
        hash & 0x0000FF
    );

}

四、XML布局示例

<!-- 控制器布局 controller_layout.xml -->
<DirectionalLayout
xmlns:ohos=“http://schemas.huawei.com/res/ohos
ohos:width=“match_parent”
ohos:height=“match_parent”
ohos:orientation=“vertical”
ohos:padding=“24vp”>

<Text
    ohos:id="$+id/title"
    ohos:width="match_parent"
    ohos:height="wrap_content"
    ohos:text="跨设备FA启动测试"
    ohos:text_size="32fp"
    ohos:margin_bottom="24vp"/>
    
<ScrollView
    ohos:width="match_parent"
    ohos:height="0vp"
    ohos:weight="1">
    
    <ListContainer
        ohos:id="$+id/device_list"
        ohos:width="match_parent"
        ohos:height="match_content"/>
</ScrollView>

<Button
    ohos:id="$+id/start_test"
    ohos:width="match_parent"
    ohos:height="60vp"
    ohos:text="开始测试"
    ohos:margin_top="24vp"/>

</DirectionalLayout>

<!-- 结果布局 result_layout.xml -->
<DirectionalLayout
xmlns:ohos=“http://schemas.huawei.com/res/ohos
ohos:width=“match_parent”
ohos:height=“match_parent”
ohos:orientation=“vertical”
ohos:padding=“24vp”>

<Text
    ohos:width="match_parent"
    ohos:height="wrap_content"
    ohos:text="测试结果对比"
    ohos:text_size="28fp"
    ohos:margin_bottom="24vp"/>
    
<com.example.testtool.BarChartView
    ohos:id="$+id/result_chart"
    ohos:width="match_parent"
    ohos:height="0vp"
    ohos:weight="1"/>
    
<TableLayout
    ohos:id="$+id/result_table"
    ohos:width="match_parent"
    ohos:height="300vp"
    ohos:margin_top="24vp"/>

</DirectionalLayout>

五、技术创新点
分布式测试:利用HarmonyOS分布式能力实现多设备并行测试

精确计时:测量从启动请求到Ability完全加载的精确时间

自动同步:借鉴游戏同步机制实现测试任务自动分发

可视化分析:直观展示不同设备的性能差异

灵活扩展:支持测试任意FA的启动性能

六、总结

本跨设备FA启动速度测试工具实现了以下核心价值:
性能评估:量化不同设备的FA启动性能差异

自动化测试:一键触发多设备并行测试

数据可视化:直观展示测试结果

问题定位:帮助发现性能瓶颈设备

标准化流程:建立统一的FA性能测试方法

系统借鉴了《鸿蒙跨端U同步》中的任务分发与结果收集机制,将游戏场景的同步技术应用于性能测试领域。未来可增加更多测试维度(内存占用、CPU使用率等),并与CI/CD流程集成实现自动化性能回归测试。HarmonyOS5

©著作权归作者所有,如需转载,请注明出处,否则将追究法律责任
收藏
回复
举报
回复
    相关推荐