重构手环软件架构:实现动态挂载前后台 App 框架,解耦拆分源文件,并引入统一日志宏 xtell.h

This commit is contained in:
Antigravity IDE
2026-07-17 09:08:53 +08:00
parent 8fdbb32f42
commit c0d1fe74f5
18 changed files with 1380 additions and 1155 deletions

View File

@@ -3,56 +3,75 @@
#include "config.h"
/* ====== 应用程序管理器 (AppManager) 核心接口 ====== */
// 动态挂载的 WristbandApp 控制块定义
typedef struct WristbandApp {
u8 app_id; // 应用唯一识别 ID
char *app_name; // 应用名称
void (*OnStart)(void); // 启动生命周期,进入前台时调用
void (*onRun)(void); // 轮询生命周期,主循环每次被调度
void (*onClose)(void); // 关闭生命周期,退出前台/后台时清理资源
EventResult (*onEvent)(SystemEvent *evt); // 事件处理生命周期,接收按键事件
} WristbandApp;
/**
* @brief 初始化应用程序管理器
* @details 负责将应用管理器的系统注册表清零,随后逐一注册系统支持的五个前台应用:
* ClockApp (待机时钟), MenuApp (主菜单), PairApp (传感器对码),
* AlarmApp (传感器警报), SOSApp (主动求救呼叫)。最后默认加载并启动 ClockApp。
* @brief 初始化应用管理器
* @details 将前台活跃槽位与后台的三个槽位全部清空为 NULL。
*/
void AppManager_Init(void);
/**
* @brief 启动指定的应用程序
* @param app_id 待启动应用的目标 ID (如 APP_ID_MENU, APP_ID_PAIR)
* @details 会执行完整的切应用生命周期流转:
* 1. 检查目标是否合法且包含有效的 OnStart 启动回调。
* 2. 对当前正在活跃运行的前台应用调用其 onClose(),以关闭该应用的屏幕内容、马达振动或射频特定模式
* 3. 将活跃应用指针指向新应用,将其 is_active 和 is_running 标志位置 1
* 4. 调用新应用的 OnStart() 初始化回调以绘制新页面
* @brief 动态将一个应用切换至前台活跃运行
* @param app 目标应用的结构体指针
* @return bit 1-切换成功0-失败
* @details 流程:
* 1. 若前台已有应用运行,且该应用未挂载在后台,则对其执行 onClose() 关闭生命周期
* 2. 将 fg_app 指针指向新的 app
* 3. 若该 app 目前并未在后台槽位中运行,则执行其 OnStart() 启动生命周期
*/
void AppManager_StartApp(AppID app_id);
bit AppManager_SwitchToForeground(WristbandApp *app);
/**
* @brief 向当前活跃的前台应用程序派发事件
* @param evt 要分发派送的系统事件
* @brief 动态将一个应用挂载到后台槽位
* @param app 目标应用的结构体指针
* @return bit 1-挂载成功0-槽位已满挂载失败
* @details 后台总共支持 3 个槽位。若挂载成功,其 onRun 将会持续在主循环中被轮询。
*/
bit AppManager_AttachToBackground(WristbandApp *app);
/**
* @brief 动态将一个应用从后台卸载
* @param app 目标应用的结构体指针
* @details 从后台槽位数组中移除该指针。若该应用当前也不在前台运行,将对其执行 onClose() 清理外设。
*/
void AppManager_DetachFromBackground(WristbandApp *app);
/**
* @brief 将捕获的事件派发给前台活跃应用
* @param evt 系统派发来的事件
*/
void AppManager_DispatchEvent(SystemEvent evt);
/**
* @brief 在系统主循环中持续轮询运行活跃应用
* @details 负责从全局注册表中定位到 active_app并轮询执行其 onRun() 周期回调
* 该接口同时集成了【CPU占用率限制机制】如果在调用 onRun 前后,检测到应用
* 占用 CPU 时间超过了 APP_ONRUN_MAX_TICKS (5ms),它将在下一次循环中暂时挂起
* 该应用,强制释放本次 CPU 占用以防止界面卡死或影响底层射频解调。
* @brief 在系统主循环中持续轮询轮转前后台所有活跃应用
* @details 负责轮询前台 fg_app 对应的 onRun(),并遍历轮询后台 bg_apps 数组中所有有效应用的 onRun()。
*/
void AppManager_RunActiveApp(void);
/**
* @brief 获取当前前台活跃应用的唯一应用程序 ID
* @return AppID 当前活跃前台应用的枚举ID
* @brief 获取当前前台活跃应用的 ID
* @return u8 当前活跃前台应用的 ID 编号。若无则返回 255 (0xFF)
*/
AppID AppManager_GetActiveAppID(void);
u8 AppManager_GetActiveAppID(void);
// 兼容性接口声明
void AppManager_StartApp(u8 app_id);
/* ====== 时间编辑状态机交互接口 ====== */
/**
* @brief 启动时钟数值调整编辑状态机
* @details 由 MenuApp 的 "HORLOGE" 项被确认点击后触发。用于直接将系统运行状态切入
* STATE_SET_TIME控制灯条常亮蓝色马达短振反馈并进入时间参数微调页。
*/
void Start_Time_Edit(void);
// ====== 系统中各独立 App 实例的外包声明 (各 App 内部进行实体定义) ======
extern WristbandApp clock_app;
extern WristbandApp menu_app;
extern WristbandApp pair_app;
extern WristbandApp alarm_app;
extern WristbandApp sos_app;
extern WristbandApp rf_monitor_app; // 后台射频监控应用
#endif // __APP_MANAGER_H__