#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>
#include "ln_api.h"
#include <unistd.h>
#include <sys/stat.h>
+#include <cstdio>
#include "vibrator_service.h"
#include "ai_media.h"
#include "ConfigModelC.h"
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),
m_lastCat1RestartTime(0),
m_storyModeTimeoutTimer(nullptr),
m_storyAudioPlaybackTimeoutTimer(nullptr),
+ m_stressAudioLoopTimer(nullptr),
m_networkConnectingReason(NetworkConnectingReason::NONE),
m_networkConnectingTimeoutCount(0)
{
// ---------------------- 仅当当前在提醒界面时启动 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();
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++;
{
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();
}
// 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();
}
}
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()
{
// 退出对话模式时恢复表情
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: 开始退出对话模式");