优化老化测试 3297/1 3297/head 3309/target/1
authorxue <2144439972@qq.com>
Fri, 20 Mar 2026 03:06:05 +0000 (11:06 +0800)
committerxue <2144439972@qq.com>
Fri, 20 Mar 2026 03:06:05 +0000 (11:06 +0800)
code/sdk/application/wearable/ln/nativeapp/nativeui/thunderbird/include/ThunderBirdModel.h
code/sdk/application/wearable/ln/nativeapp/nativeui/thunderbird/src/ThunderBirdModel.cpp
code/sdk/zhihui/leiniao/ln_api_cpp/ln_audio_simple.cpp
code/sdk/zhihui/leiniao/ln_api_cpp/ln_audio_simple.h

index 85791cb..380f7a6 100644 (file)
@@ -50,6 +50,9 @@ namespace OHOS
         // 常亮屏刷新定时器(用于压测模式,每50分钟刷新一次,避免1小时超时)
         void StartAlwaysOnRefreshTimer();
         void StopAlwaysOnRefreshTimer();
+        /** 压测音频循环定时器(每1.5秒播放一次 FactoryMode.mp3) */
+        void StartStressAudioLoopTimer();
+        void StopStressAudioLoopTimer();
 
         /** 息屏时间档位:0=30秒(默认) 1=5分钟 2=10分钟 3=30分钟 4=常亮(不息屏);KV 仅存 screen_timeout_sec */
         static constexpr int SCREEN_KEEPON_LEVEL_30S = 0;
@@ -481,7 +484,8 @@ namespace OHOS
         void* m_storyModeTimeoutTimer;        // 故事模式超时定时器(1分钟无文本切换则退出)
         void* m_storyAudioPlaybackTimeoutTimer;  // 故事模式音频播放超时定时器(5秒内无音频播放则退出)
         void* m_factoryResetTimer;              // 恢复出厂设置定时器
-        
+        void* m_stressAudioLoopTimer;            // 压测音频循环定时器(每1.5秒播放一次)
+
         // 对话模式相关标志
         bool m_dialogueModeFinished = false; // 对话模式是否已finished(收到finished=true)
 
@@ -496,6 +500,10 @@ namespace OHOS
         bool m_videoThreadRecoveryInProgress = false; // 视频线程恢复进行中标志
         int m_videoThreadRecoveryAttempts = 0;        // 视频线程恢复尝试次数(最多3次)
 
+        // AT^LN_STRESS_TEST_DIALOGUE 压测模式相关
+        bool m_stressTestDialogueActive = false;  // 是否处于压测对话模式
+        time_t m_stressTestStartTime = 0;         // 压测开始时间戳
+
     };
 }
 
index 0b8ec3c..04a4bfb 100644 (file)
@@ -27,6 +27,7 @@
  #include <sys/time.h>
  #include <service/graphic_service.h>
 #include "custom_utils.h"
+#include "custom_utilscpp.h"
 #include "bluetooth/Ln_Bluetooth_apiC.h"
 #include <algorithm>
 #include <ctime>
@@ -48,6 +49,7 @@
 #include "ln_api.h"
 #include <unistd.h>
 #include <sys/stat.h>
+#include <cstdio>
 #include "vibrator_service.h"
 #include "ai_media.h"
 #include "ConfigModelC.h"
@@ -112,6 +114,55 @@ extern "C" {
 
      static bool g_isRecording = false;//是否正在录音
 
+    /**************************产测相关************************************/
+    /* AT^LN_STRESS_TEST_DIALOGUE 压测线程:产测期间定期内存拷贝,拉高 CPU 使用率(仅拷贝,不写文件) */
+    static osMessageQueueId_t g_stress_save_queue = nullptr;
+    static volatile bool g_stress_save_created = false;
+    static volatile bool g_stress_test_active_for_save = false;  /* 产测进行中,线程定期做拷贝 */
+    static const char *g_stress_audio_file = "/user/res/music/FactoryMode.mp3";
+    #define STRESS_COPY_BUF_SIZE 4096
+    #define STRESS_COPY_LOOPS 64     /* 每轮拷贝 64 次,共 256KB,拉高 CPU */
+    static uint8_t g_stress_copy_src[STRESS_COPY_BUF_SIZE];
+    static uint8_t g_stress_copy_dst[STRESS_COPY_BUF_SIZE];
+
+    /* 压测音频循环定时器回调:每1.5秒执行一次,投递到图形线程播放 */
+    static void StressAudioLoopTimerCallback(uint8_t data)
+    {
+        GraphicService::GetInstance()->PostGraphicEvent([]() {
+            ln_audio_simple_stop();
+            LOS_Msleep(100);
+            (void)ln_audio_simple_play_loop(g_stress_audio_file, false);
+        });
+    }
+
+    static void stress_test_do_copy_only(void)
+    {
+        /* 仅内存拷贝:拉高 CPU 使用率,不写文件 */
+        for (int i = 0; i < STRESS_COPY_LOOPS; i++) {
+            memcpy(g_stress_copy_dst, g_stress_copy_src, STRESS_COPY_BUF_SIZE);
+        }
+    }
+
+    static void stress_test_save_task(void *arg)
+    {
+        uint32_t msg = 0;
+        uint32_t copy_count = 0;
+        WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "stress_test_save: task started (periodic memcpy only, no file)");
+        for (;;) {
+            uint32_t timeout_ms = g_stress_test_active_for_save ? 1000 : osWaitForever;  /* 产测中每 1 秒唤醒 */
+            osStatus_t st = osMessageQueueGet(g_stress_save_queue, &msg, nullptr, timeout_ms);
+            if (st == osOK) continue;  /* 收到消息则忽略(仅用于唤醒),不写文件 */
+            if (st != osOK && g_stress_test_active_for_save) {
+                /* 超时且产测进行中:重复内存拷贝,拉高 CPU */
+                stress_test_do_copy_only();
+                copy_count++;
+                if (copy_count % 10 == 1) {  /* 每 10 秒打印一次,便于确认在运行 */
+                    WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "stress_test_save: memcpy running, count=%u", copy_count);
+                }
+            }
+        }
+    }
+     /**************************产测相关************************************/
     ThunderBirdModel::ThunderBirdModel() : m_nextReminderId(1), m_otaStatus(0),
                                            m_timeDisplayTimer(nullptr), m_statusTimer(nullptr),
                                            m_currentStatus(DeviceStatus::IDLE), 
@@ -130,6 +181,7 @@ extern "C" {
                                           m_lastCat1RestartTime(0),
                                           m_storyModeTimeoutTimer(nullptr),
                                           m_storyAudioPlaybackTimeoutTimer(nullptr),
+                                          m_stressAudioLoopTimer(nullptr),
                                           m_networkConnectingReason(NetworkConnectingReason::NONE),
                                           m_networkConnectingTimeoutCount(0)
      {
@@ -358,6 +410,8 @@ extern "C" {
      // ---------------------- 仅当当前在提醒界面时启动 3 秒退出定时器(供 LN_HTTP_SERVICE_CMD_AUDIO_STOP 使用,避免哄睡结束误触) ----------------------
      void ThunderBirdModel::StartCountUpTimerForDialogueExitIfInSpeaking(void)
      {
+         /* 压测模式下不启动 3 秒退出定时器,避免 FactoryMode.mp3 播放完成后误退出 */
+         if (m_stressTestDialogueActive) return;
          ThunderBirdMainView *view = ThunderBirdMainView::GetInstance();
          if (view == nullptr) return;
          int16_t currentView = view->GetCurrentView();
@@ -1787,6 +1841,11 @@ extern "C" {
             WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "TimeDisplayCallback: %s", currentTime.c_str());
         }
         
+        /* 产测模式下每秒重新断言常亮屏,防止被其他逻辑覆盖 */
+        if (m_stressTestDialogueActive) {
+            ScreenAlwaysOnCtr(OPEN_SCREEN_ALWAYS_ON);
+        }
+        
         // 处理常亮屏刷新定时器(每5分钟刷新一次,避免1小时超时)
         if (m_alwaysOnRefreshActive) {
             m_alwaysOnRefreshTime++;
@@ -3441,11 +3500,37 @@ extern "C" {
     {
         WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "ThunderBirdModel::HandleJumpDialogueSpeaking");
         
+        m_stressTestDialogueActive = true;
+        m_stressTestStartTime = time(nullptr);
+        g_stress_test_active_for_save = true;
+        ln_audio_simple_set_suppress_stop_on_complete(true);  /* 产测模式下播放完成不触发 CMD_AUDIO_STOP */
+        
+        /* 首次进入时创建压测保存线程:独立线程做内存拷贝+写文件 */
+        if (!g_stress_save_created) {
+            g_stress_save_queue = osMessageQueueNew(4, sizeof(uint32_t), nullptr);
+            if (g_stress_save_queue) {
+                osThreadAttr_t attr = {0};
+                attr.name = "stress_save";
+                attr.stack_size = 1024;
+                attr.priority = osPriorityBelowNormal;
+                if (osThreadNew(stress_test_save_task, nullptr, &attr) != nullptr) {
+                    g_stress_save_created = true;
+                    WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "HandleJumpDialogueSpeaking: stress_test_save thread created");
+                } else {
+                    WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "HandleJumpDialogueSpeaking: stress_test_save thread create FAILED");
+                    osMessageQueueDelete(g_stress_save_queue);
+                    g_stress_save_queue = nullptr;
+                }
+            }
+        }
+        
         // 1. 停止其他音频服务,避免冲突
         ln_audio_simple_stop();
         // AI_ForceInterrupt();
         do_custom_cmd_service_check_msg(CUSTOM_CMD_MSG_AUDIO_DEINIT, NULL, 0);
         
+        LOS_Msleep(250);
+        
         // 2. 跳转到对话说话界面
         if (ThunderBirdMainView::GetInstance()) {
             int currentView = ThunderBirdMainView::GetInstance()->GetCurrentView();
@@ -3453,19 +3538,20 @@ extern "C" {
         }
         
         // 3. 设置常亮屏(在ChangeView之后设置,确保不会被视图切换逻辑覆盖)
+        uapi_setScreenDuration(30 * 60 * 1000);  /* 产测模式:30分钟息屏,避免被 KV 的短超时覆盖 */
         ScreenAlwaysOnCtr(OPEN_SCREEN_ALWAYS_ON);
         
         StartAlwaysOnRefreshTimer();
         
         const char *factory_mode_file = "/user/res/music/FactoryMode.mp3";
-        WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "ThunderBirdModel::HandleJumpDialogueSpeaking: Playing file: %s (will loop)", factory_mode_file);
+        WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "ThunderBirdModel::HandleJumpDialogueSpeaking: Playing file: %s (timer replay every 1.5s)", factory_mode_file);
         
-        // 使用 ln_audio_simple_play_loop 直接循环播放,无需线程
-        int ret = ln_audio_simple_play_loop(factory_mode_file, true);
+        int ret = ln_audio_simple_play_loop(factory_mode_file, false);
         if (ret != 0) {
             WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "ThunderBirdModel::HandleJumpDialogueSpeaking: Failed to play file: %s, ret=%d", factory_mode_file, ret);
         } else {
-            WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "ThunderBirdModel::HandleJumpDialogueSpeaking: Successfully started loop playback");
+            WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "ThunderBirdModel::HandleJumpDialogueSpeaking: started, timer will replay every 1.5s");
+            StartStressAudioLoopTimer();
         }
     }
     
@@ -3488,6 +3574,36 @@ extern "C" {
         m_alwaysOnRefreshTime = 0;
     }
 
+    void ThunderBirdModel::StartStressAudioLoopTimer()
+    {
+        if (m_stressAudioLoopTimer != nullptr) {
+            StopStressAudioLoopTimer();
+        }
+        m_stressAudioLoopTimer = osTimerNew((osTimerFunc_t)StressAudioLoopTimerCallback, osTimerPeriodic, nullptr, nullptr);
+        if (m_stressAudioLoopTimer == nullptr) {
+            WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "StartStressAudioLoopTimer: Failed to create timer");
+            return;
+        }
+        osStatus_t ret = osTimerStart(m_stressAudioLoopTimer, 2000);  // 1500ms = 1.5秒
+        if (ret != osOK) {
+            WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "StartStressAudioLoopTimer: Failed to start, ret=%d", ret);
+            osTimerDelete(m_stressAudioLoopTimer);
+            m_stressAudioLoopTimer = nullptr;
+        } else {
+            WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "StartStressAudioLoopTimer: started, 1.5s interval");
+        }
+    }
+
+    void ThunderBirdModel::StopStressAudioLoopTimer()
+    {
+        if (m_stressAudioLoopTimer != nullptr) {
+            osTimerStop(m_stressAudioLoopTimer);
+            osTimerDelete(m_stressAudioLoopTimer);
+            m_stressAudioLoopTimer = nullptr;
+            WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "StopStressAudioLoopTimer: stopped");
+        }
+    }
+
     //测试BGM开始函数
     void ThunderBirdModel::StartDialogueBgm()
     {
@@ -4202,6 +4318,15 @@ extern "C" {
     // 退出对话模式时恢复表情
     void ThunderBirdModel::OnExitDialogueMode()
     {
+        // 停止BGM/压测音频,停止常亮屏定时器
+        StopStressAudioLoopTimer();
+        StopDialogueBgm();
+        StopAlwaysOnRefreshTimer();
+        if (m_stressTestDialogueActive) {
+            ln_audio_simple_set_suppress_stop_on_complete(false);  /* 恢复默认:播放完成发送 CMD_AUDIO_STOP */
+            g_stress_test_active_for_save = false;  /* 停止定期拷贝 */
+            m_stressTestDialogueActive = false;
+        }
         //切换跑马灯速度
         ThunderBirdDialogueView::GetInstance()->SwitchRollSpeed(75);
         WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "ThunderBirdModel::OnExitDialogueMode: 开始退出对话模式");
index 124bbb2..48955db 100644 (file)
@@ -45,6 +45,7 @@ typedef struct
 } ln_audio_simple_impl_t;
 
 static ln_audio_simple_impl_t g_simple = {0};
+static bool g_suppress_stop_on_complete = false;
 
 /* ============================== 播放器回调类 ============================== */
 
@@ -57,11 +58,15 @@ public:
     {
         if (impl_)
         {
+            impl_->is_playing = false;
+            if (g_suppress_stop_on_complete) {
+                /* 压测模式下不发送 CMD_AUDIO_STOP,由 StressAudioLoopTimer 负责重播 */
+                return;
+            }
             printf("[LN_AUDIO_SIMPLE] playback completed, sending cleanup message\n");
             // 通过消息队列发送清理命令,避免在回调中直接调用导致卡住
             // 发送消息到 ln_http_server_send_task 线程
             do_ln_http_server_send_data(LN_HTTP_SERVICE_CMD_AUDIO_STOP, NULL, 0);
-            impl_->is_playing = false;
         }
     }
 
@@ -399,6 +404,11 @@ bool ln_audio_simple_is_playing(void)
     return g_simple.is_playing;
 }
 
+void ln_audio_simple_set_suppress_stop_on_complete(bool suppress)
+{
+    g_suppress_stop_on_complete = suppress;
+}
+
 } // extern "C"
 
 
index 61f5783..fd05560 100644 (file)
@@ -51,6 +51,12 @@ int ln_audio_simple_stop(void);
  */
 bool ln_audio_simple_is_playing(void);
 
+/*
+ * 压测模式下:播放完成时不发送 LN_HTTP_SERVICE_CMD_AUDIO_STOP
+ * 参数:suppress - true 表示抑制,false 表示恢复默认行为
+ */
+void ln_audio_simple_set_suppress_stop_on_complete(bool suppress);
+
 #ifdef __cplusplus
 }
 #endif