在rk3568上架构纯c语言json脚本+webrtc服务音频设备播放设备程序

1. 源码文件树形结构

复制代码
.
├── tang.c
├── tang_app.c
├── tang_key_function.c
├── tang_tts.c
├── tang_musicplayer.c
├── tang_ui.c (条件编译)
├── include/
├── modules/
│   ├── tang_module_linein.c
│   ├── tang_module_cloud_music.c
│   ├── tang_module_local_music.c (条件编译)
│   ├── tang_module_dmr.c (条件编译)
│   ├── tang_module_mulroom.c (条件编译)
│   ├── tang_module_airplay.c (条件编译)
│   ├── tang_module_bt.c (条件编译)
│   ├── tang_module_vr.c (条件编译)
│   ├── tang_module_camera.c (条件编译)
│   ├── camera/
│   │   ├── camera.c
│   │   ├── lcd.c
│   │   ├── video.c
│   │   ├── savebmp.c
│   │   └── convert.c
│   └── song_supplyer/
│       ├── speech.c
│       ├── ximalaya.c
│       └── jushang.c
├── misc/
│   ├── battery_capacity.c
│   ├── tts_baidu.c
│   ├── dms.c (条件编译)
│   └── lapsule_control.c (条件编译)
└── ingenicplayer/
    ├── appserver.c
    ├── ingenicplayer.c
    └── device.c

2. 应用程序树形结构

复制代码
tang (主程序)
├── 核心功能层
│   ├── 应用主循环 (tang_app.c)
│   ├── 按键处理 (tang_key_function.c)
│   ├── TTS引擎 (tang_tts.c)
│   └── 音乐播放器 (tang_musicplayer.c)
├── 模块层
│   ├── 音频输入模块
│   ├── 云音乐模块
│   ├── 本地音乐模块
│   ├── DMR (数字媒体渲染器)
│   ├── 多房间音频
│   ├── AirPlay模块
│   ├── 蓝牙模块
│   ├── 语音识别模块
│   ├── 摄像头模块
│   └── 歌曲供应商接口
└── 服务层
    ├── 电池管理
    ├── 报警服务
    ├── WebRTC处理
    ├── 设备管理服务
    └── 胶囊控制

3. 设计思想树形结构

复制代码
软件设计思想
├── 模块化架构
│   ├── 功能模块化 (每个功能独立模块)
│   ├── 条件编译机制
│   └── 插件式设计
├── 分层架构
│   ├── 核心层 (基础功能)
│   ├── 模块层 (业务功能)
│   └── 服务层 (系统服务)
├── 设计模式
│   ├── 策略模式 (TTS/VR供应商选择)
│   ├── 工厂模式 (歌曲供应商)
│   ├── 观察者模式 (事件处理)
│   ├── 外观模式 (模块接口统一)
│   └── 命令模式 (按键处理)
├── 配置驱动开发
│   ├── 编译时功能开关
│   ├── 供应商选择配置
│   └── 硬件适配配置
└── 跨平台考虑
    ├── MIPS架构优化
    ├── 库依赖抽象
    └── 安装脚本适配

4. 软件架构分析

核心架构特征:

  1. 模块化插件架构 - 每个功能都是独立的模块,通过条件编译控制

  2. 事件驱动设计 - 基于libevent库,支持异步事件处理

  3. 多层抽象 - 硬件抽象层、功能模块层、应用逻辑层分离

使用的设计模式:

  • 策略模式:TTS引擎、VR引擎、歌曲供应商可替换

  • 工厂模式:根据不同配置创建不同的功能模块实例

  • 外观模式:为复杂子系统提供统一接口

  • 观察者模式:事件处理机制

5. 运行性能特征

性能优化措施:

  1. 编译优化-O2优化级别,异步栈展开

  2. 内存管理:动态库加载,共享内存使用

  3. 并发处理 :多线程支持(-lpthread),异步事件处理

  4. 硬件加速:使用专用音频处理库(resample, alsa)

性能关键点:

  • 音频处理:重采样、WebRTC音频处理

  • 网络通信:UPnP、AirPlay、云服务

  • 多媒体播放:硬件解码优化

  • 实时性:语音识别响应、按键处理

6. 系统依赖分析

核心依赖库

  • levent - 事件驱动框架

  • lplayer - 音频播放

  • ljson-c - 数据解析

  • lasound - 音频系统

  • lpthread - 多线程

功能专用库

  • 语音识别(TTS/VR):百度、捷通、思必驰等

  • 网络服务:UPnP、AirPlay、WebRTC

  • 多媒体:PNG解码、摄像头处理

  • 系统服务:电源管理、WiFi、共享内存

这个设计体现了嵌入式Linux系统软件的典型特征:模块化、可配置、资源受限环境优化,以及面向多种硬件变体的适配能力。

Makefile架构:

复制代码
# 获取当前工作目录的绝对路径
DIR_CUR := $(shell pwd)
​
# 自定义函数:字符串截取
# $1: string - 要截取的字符串
# $2: start pos - 起始位置
# $3: length - 截取长度
define substring
$(shell echo `expr substr $(1) $(2) $(3)`)
endef
​
# 功能模块开关定义,使用?=表示如果未定义则赋默认值0(关闭)
BT ?= 0                    # 蓝牙功能开关
VR ?= 0                    # 语音识别功能开关
TTS ?= 0                   # 文本转语音功能开关
LAPSULE ?= 0               # 胶囊控制功能开关
INGENICPLAYER ?= 0         # 播放器功能开关(保留,可能需替换)
DMR ?= 0                   # 数字媒体渲染器功能开关
WEBRTC ?= 0                # WebRTC音频处理功能开关
DMS ?= 0                   # 设备管理服务功能开关
AIRPLAY ?= 0               # AirPlay功能开关
LOCALPLAYER ?= 0           # 本地播放器功能开关
ALARM ?= 0                 # 闹钟功能开关
MULROOM ?= 0               # 多房间音频功能开关
CAMERA ?= 0                # 摄像头功能开关
​
# RK3568 Linux 64位交叉编译工具链定义
CC = aarch64-linux-gnu-gcc              # ARM64架构C编译器
CXX = aarch64-linux-gnu-g++             # ARM64架构C++编译器
STRIP = aarch64-linux-gnu-strip         # 二进制文件strip工具
INSTALL = install                       # 安装命令
DESTDIR =                               # 目标目录前缀(为空表示根目录)
PREFIX = /usr                           # 安装前缀目录
INITDIR = /etc/init.d/                  # 初始化脚本目录
SBINDIR = $(PREFIX)/sbin                # 系统二进制文件目录
​
# 源代码文件列表定义
SRCS = tang.c tang_app.c tang_key_function.c tang_tts.c tang_musicplayer.c  # 核心源文件
SRCS += misc/battery_capacity.c                                              # 电池容量检测
SRCS += modules/tang_module_linein.c                                         # 线性输入模块
​
# 通用编译选项
CFLAGS = -fPIC -Wall -Werror -g -O2 -I. -I./include/ -I./modules/ -I$(MOLIB_DIR)/usr/include -I$(MOLIB_UPDATER_DIR)/usr/include -I$(tang_DIR)/usr/include -I$(tang_UPDATER_DIR)/usr/include
# 编译选项说明:
# -fPIC: 生成位置无关代码
# -Wall: 开启所有警告
# -Werror: 将警告视为错误
# -g: 包含调试信息
# -O2: 优化级别2
# -I: 头文件搜索路径
CFLAGS += -rdynamic -fasynchronous-unwind-tables  # 支持动态链接和异步栈展开
​
# 链接选项
LDFLAGS = -g -lpthread -lstdc++ -L$(MOLIB_DIR)/usr/lib -L$(MOLIB_UPDATER_DIR)/usr/lib -L$(tang_DIR)/usr/lib -L$(tang_UPDATER_DIR)/usr/lib
# 链接选项说明:
# -g: 包含调试信息
# -lpthread: 链接pthread线程库
# -lstdc++: 链接C++标准库
# -L: 库文件搜索路径
LDFLAGS += -Wl,-rpath-link,$(MOLIB_DIR)/usr/lib:$(MOLIB_UPDATER_DIR)/usr/lib:$(tang_DIR)/usr/lib  # 运行时库搜索路径
​
# 基础依赖库(适配RK3568 Linux环境)
LDFLAGS += -levent -lpower -lwifi -lvolume -ltips -lsharememory -lini -lutils -lpthread -lplayer -ljson-c -lm -lresample -lnvrw -lupdater -lmusiclist -llinklist -lasound -llocalstream
# 库说明:
# -levent: libevent事件驱动库
# -lpower: 电源管理库
# -lwifi: WiFi功能库
# -lvolume: 音量控制库
# -ltips: 提示功能库
# -lsharememory: 共享内存库
# -lini: INI配置文件解析库
# -lutils: 工具函数库
# -lplayer: 播放器核心库
# -ljson-c: JSON解析库
# -lm: 数学库
# -lresample: 音频重采样库
# -lnvrw: NVR读写库
# -lupdater: 系统更新库
# -lmusiclist: 音乐列表库
# -llinklist: 链表库
# -lasound: ALSA音频库
# -llocalstream: 本地流媒体库
​
# 添加云音乐模块
SRCS += modules/tang_module_cloud_music.c
​
# 根据歌曲供应商选择相应模块
ifeq ("$(SONG_SUPPLYER)","aispeech")          # 思必驰歌曲供应商
SRCS += modules/song_supplyer/speech.c
endif
​
ifeq ("$(SONG_SUPPLYER)","ximalaya")          # 喜马拉雅歌曲供应商
SRCS += modules/song_supplyer/ximalaya.c
LDFLAGS += -lximalaya                         # 链接喜马拉雅SDK
endif
​
ifeq ("$(SONG_SUPPLYER)","jushang")           # 炬尚歌曲供应商
SRCS += modules/song_supplyer/jushang.c
LDFLAGS += -lvr_jushang                       # 链接炬尚语音识别SDK
endif
​
# 本地播放器功能条件编译
ifeq ($(LOCALPLAYER),1)                       # 如果启用本地播放器
SRCS += modules/tang_module_local_music.c     # 添加本地音乐模块
LDFLAGS += -llocalplayer                      # 链接本地播放器库
else
$(warning localplayer func CLOSED!!!!)        # 警告:本地播放器功能关闭
endif
​
# 数字媒体渲染器功能条件编译
ifeq ($(DMR),1)                               # 如果启用DMR功能
CFLAGS += -I$(MOLIB_DIR)/usr/include/upnp     # 添加UPnP头文件路径
LDFLAGS += -lrender                           # 链接渲染器库
SRCS += modules/tang_module_dmr.c             # 添加DMR模块
else
$(warning dmr func CLOSED!!!!)                # 警告:DMR功能关闭
endif
​
# 多房间音频功能条件编译
ifeq ($(MULROOM),1)                           # 如果启用多房间音频
SRCS += modules/tang_module_mulroom.c         # 添加多房间模块
LDFLAGS += -lmulroom                          # 链接多房间音频库
else
$(warning multiroom func CLOSED!!!!)          # 警告:多房间功能关闭
endif
​
# 摄像头功能条件编译(RK3568支持MIPI摄像头)
ifeq ($(CAMERA),1)                            # 如果启用摄像头功能
SRCS += modules/camera/camera.c \             # 添加摄像头相关源文件
    modules/camera/lcd.c\
    modules/camera/video.c\
    modules/camera/savebmp.c\
    modules/camera/convert.c\
    modules/tang_module_camera.c
# RK3568可能需要添加特定的摄像头库
LDFLAGS += -lv4l2 -lrockchip_mpp             # 添加V4L2和Rockchip媒体处理库
else
$(warning camera func CLOSED!!!!)             # 警告:摄像头功能关闭
endif
​
# TTS引擎选择条件编译
ifeq ("$(TTS)","baidu")                       # 百度TTS引擎
SRCS += misc/tts_baidu.c                      # 添加百度TTS实现
else
ifeq ("$(TTS)","jietong")                     # 捷通TTS引擎
LDFLAGS +=  -lhci_sys -lhci_curl -lhci_tts -ltts_jietong  # 链接捷通TTS相关库
else
ifeq ("$(TTS)","aispeech")                    # 思必驰TTS引擎
LDFLAGS +=  -lvr                              # 链接思必驰语音库
endif
endif
endif
​
# AirPlay功能条件编译
ifeq ($(AIRPLAY),1)                           # 如果启用AirPlay
SRCS += modules/tang_module_airplay.c         # 添加AirPlay模块
else
$(warning airplay func CLOSED!!!!)            # 警告:AirPlay功能关闭
endif
​
# 蓝牙功能条件编译(RK3568通常使用Realtek或Broadcom蓝牙)
ifeq ($(BT),0)                                # 如果蓝牙功能关闭
$(warning bt func are CLOSED!!!!)             # 警告:蓝牙功能关闭
else
SRCS += modules/tang_module_bt.c              # 添加蓝牙模块
endif
ifeq ("$(call substring,$(BT),1,3)", "rtk")   # Realtek蓝牙模块(RK3568常用)
LDFLAGS += -lrtk_btcore -lbtstack            # 链接Realtek蓝牙核心库
endif
ifeq ("$(call substring,$(BT),1,3)", "bcm")   # Broadcom蓝牙模块
LDFLAGS += -lbsa -lbt -lappcommon -lchannels -lrecord  # 链接Broadcom蓝牙库
endif
​
# 播放器功能条件编译(适配RK3568硬件解码)
ifeq ($(INGENICPLAYER),1)                     # 如果启用硬件播放器
SRCS +=  ingenicplayer/appserver.c ingenicplayer/ingenicplayer.c ingenicplayer/device.c  # 添加播放器源文件
LDFLAGS += -lappserver -lrockchip_mpp -lrga   # 链接应用服务器和Rockchip媒体处理库
else
$(warning ingenicplayer func CLOSED!!!!)      # 警告:硬件播放器功能关闭
endif
​
# 语音识别功能条件编译
ifeq ("$(VR)","0")                            # 如果语音识别功能关闭
$(warning vr func are CLOSED!!!!)             # 警告:语音识别功能关闭
else
SRCS += modules/tang_module_vr.c              # 添加语音识别模块
endif
ifeq ("$(VR)","aispeech")                     # 思必驰语音识别
LDFLAGS +=  -lvr                              # 链接思必驰语音库
endif
ifeq ("$(VR)","iflytek")                      # 科大讯飞语音识别
LDFLAGS += -lvr_iflytek                       # 链接科大讯飞语音库
endif
ifeq ("$(VR)","jietong")                      # 捷通语音识别
LDFLAGS += -lvr_jietong -lrecord -lwakeup_jietong  # 链接捷通语音识别和唤醒库
endif
​
# UI功能条件编译(RK3568支持多种显示接口)
ifeq ("$(UI)","0")                            # 如果UI功能关闭
$(warning ui func are CLOSED!!!!)             # 警告:UI功能关闭
else
SRCS += tang_ui.c                             # 添加UI模块
endif
ifeq ("$(UI)","lcd")                          # LCD UI
LDFLAGS += -llcd -llcdshow -lpng -lz -ldrm -lrockchip_drm  # 链接LCD显示、PNG和DRM库
endif
ifeq ("$(UI)","smartui")                      # 智能UI
LDFLAGS += -lsmartui                          # 链接智能UI库
endif
ifeq ("$(UI)","wayland")                      # Wayland UI(RK3568常用)
LDFLAGS += -lwayland-client -lwayland-egl     # 链接Wayland客户端库
endif
​
# 闹钟功能条件编译
ifeq ($(ALARM),1)                             # 如果启用闹钟功能
LDFLAGS += -lalarm                            # 链接闹钟库
else
$(warning alarm func CLOSED!!!!)              # 警告:闹钟功能关闭
endif
​
# WebRTC功能条件编译
ifeq ($(WEBRTC),1)                            # 如果启用WebRTC
LDFLAGS += -lwebrtc_audio_processing -lwebrtc  # 链接WebRTC音频处理库
else
$(warning webrtc func CLOSED!!!!)             # 警告:WebRTC功能关闭
endif
​
# 设备管理服务功能条件编译
ifeq ($(DMS),1)                               # 如果启用DMS
SRCS += misc/dms.c                            # 添加设备管理服务模块
else
$(warning dms func CLOSED!!!!)                # 警告:DMS功能关闭
endif
​
# 胶囊控制功能条件编译
ifeq ($(LAPSULE),1)                           # 如果启用胶囊控制
SRCS += misc/lapsule_control.c                # 添加胶囊控制模块
else
$(warning lapsule func CLOSED!!!!)            # 警告:胶囊控制功能关闭
endif
​
# RK3568特定优化选项
CFLAGS += -march=armv8-a+crc -mtune=cortex-a55  # ARM64架构优化
LDFLAGS += -Wl,--hash-style=gnu               # 使用GNU哈希风格
​
# 目标文件生成规则:将所有的.c文件转换为.c.o文件
OBJS = $(patsubst %.c, %.c.o, $(SRCS))
# 最终目标文件名
TARGET = tang
​
# 默认目标
all:$(TARGET)
​
# 链接目标:将所有的.o文件链接成可执行文件
$(TARGET):$(OBJS)
    $(CC) -o $@ $(OBJS) $(LDFLAGS)
​
# 模式规则:将.c文件编译为.o文件
%.c.o:%.c
    $(CC) $(CFLAGS) -c $^ -o $@
​
# 安装目标
install:
    $(INSTALL) -d $(DESTDIR)$(SBINDIR)        # 创建sbin目录
    $(INSTALL) -d $(DESTDIR)$(INITDIR)        # 创建init.d目录
    if [ -e $(TARGET) ]; then \               # 如果目标文件存在
        $(INSTALL) -m 755 -s --strip-program=$(STRIP) $(TARGET) $(DESTDIR)$(SBINDIR)/; \  # 安装并strip可执行文件
        $(INSTALL) -m 755 S10tang.sh $(DESTDIR)$(INITDIR)/; \  # 安装启动脚本
    fi
​
# 清理目标
clean:
    -rm -rf $(OBJS) $(TARGET)                 # 删除所有目标文件和可执行文件
​
# 卸载目标
uninstall:
    if [ -e $(DESTDIR)$(SBINDIR)/$(TARGET) ]; then \  # 如果已安装的目标文件存在
        rm -rf $(DESTDIR)$(SBINDIR)/$(TARGET); \      # 删除可执行文件
        rm -rf $(DESTDIR)$(INITDIR)/S10tang.sh; \     # 删除启动脚本
    fi
​
# 声明伪目标
.PHONY:all clean install uninstall $(TARGET)

主要源码框架:

tang.c

复制代码
#include <string.h>    // 性能:字符串操作,内存拷贝可能成为瓶颈
#include <stdlib.h>    // 架构特点:标准库基础,内存管理和程序控制
#include <signal.h>    // 软件设计模式:观察者模式 - 信号处理机制
#include <stdbool.h>   // 可读性:布尔类型支持,提高代码表达力
#include <unistd.h>    // 性能:系统调用封装,进程控制
#include <pthread.h>   // 软件设计模式:主动对象模式 - 多线程支持
#include <errno.h>     // 架构特点:错误处理基础
#include <time.h>      // 性能:时间相关操作
#include <sys/types.h> // 架构特点:系统类型定义
#include <pwd.h>       // 可读性:用户信息获取,可能用于权限控制
#include <sys/stat.h>  // 性能:文件状态检查
#include <linux/input.h> // 软件设计模式:事件驱动模式 - 输入事件处理
#include <fcntl.h>     // 性能:文件控制,非阻塞IO可能
#include <execinfo.h>  // 架构特点:调试支持,堆栈跟踪
​
// 软件设计模式:外观模式 - 统一的模块接口头文件
#include "event_interface.h"       // 事件管理接口
#include "wifi_interface.h"        // 网络功能
#include "volume_interface.h"      // 音频控制
#include "player_interface.h"      // 媒体播放
#include "tips_interface.h"        // 用户提示
#include "json-c/json.h"           // 性能:JSON解析,可能影响启动速度
#include "utils_interface.h"       // 工具函数
#include "power_interface.h"       // 电源管理
#include "sharememory_interface.h" // 软件设计模式:共享内存模式 - 进程间通信
#include "ini_interface.h"         // 配置管理
#include "nvrw_interface.h"        // 非易失存储
#include "updater_interface.h"     // 更新功能
#include "localplayer_interface.h" // 本地播放
​
// 架构特点:应用专用头文件,分层设计
#include "tang_config.h"           // 配置定义
#include "lapsule_control.h"       // 胶囊控制(特定硬件功能)
#include "battery_capacity.h"      // 电池管理
#include "ingenicplayer.h"         // 播放器
​
// 核心应用模块
#include "tang_app.h"              // 主应用逻辑
#include "tang_ui.h"               // 用户界面
#include "tang_musicplayer.h"      // 音乐播放
#include "tang_key_function.h"     // 按键功能
​
#include "tang_tts.h"              // 文本转语音
#ifdef SUPPORT_BT
#include "modules/tang_module_bt.h" // 软件设计模式:条件编译模块 - 蓝牙功能
#endif
#ifdef SUPPORT_VR
#include "modules/tang_module_vr.h" // VR功能
#include "vr_interface.h"          // VR接口
#endif
​
#if (SUPPORT_MULROOM == 1)
#include "mulroom_interface.h"     // 多房间音频
#include "modules/tang_module_mulroom.h" // 多房间模块
#endif /* SUPPORT_MULROOM == 1 */
​
// 软件设计模式:模块化设计 - 功能模块分离
#include "modules/tang_module_linein.h"      // 线路输入
#include "modules/tang_module_local_music.h" // 本地音乐
​
#if (SUPPORT_ALARM == 1)
#include "alarm_interface.h"       // 闹钟功能
#endif
​
// 软件设计模式:单例模式 - 全局事件处理器
event_handler *keyevent_handler = NULL;  // 按键事件处理器
event_handler *miscevent_handler = NULL; // 杂项事件处理器
char *app_name = NULL;                   // 应用名称
int tfcard_status = -1;                  // TF卡状态,性能:存储检测
static int null_cnt = 0;                 // 空计数,架构特点:状态跟踪
​
#if (SUPPORT_MULROOM == 1)
#define MULROOM_INFO_PATH   "/usr/data/mulroom.json"  // 架构特点:配置文件路径
static enum mul_state mulroom_state = MUL_IDLE;  // 多房间状态机
#endif /* SUPPORT_MULROOM == 1 */
​
#if (SUPPORT_BT == BT_BCM)
// 软件设计模式:配置常量模式 - 蓝牙音量参数
#define APP_HS_CALL_VOLUME_MAX  15  // 耳机通话最大音量
#define APP_AVK_VOLUME_MAX      17  // AVK音频最大音量
int bsa_ble_start_regular_enable = 0;  // BLE启动标志
int bsa_start_regular_enable = 0;      // BSA启动标志
int ble_hh_add_dev_enable = 0;         // BLE设备添加标志
int bt_link_state = BT_LINK_DISCONNECTED;  // 蓝牙连接状态机
pthread_t bt_reconnect_pthread;        // 性能:蓝牙重连线程
pthread_t bt_ring_pthread;             // 蓝牙铃声线程
int bt_reconnect_num = 0;              // 重连次数
bool bt_ring_flag;                     // 铃声标志
int disc_num = -1;                     // 发现设备数量
pthread_mutex_t bt_reconnect_lock;     // 软件设计模式:保护性暂停模式 - 线程同步
​
// 性能:音量映射表,避免运行时计算
static UINT8 avk_volume_set_dsp[APP_AVK_VOLUME_MAX] = {0, 6, 12, 18, 25, 31, 37, 43, 50, 56, 62, 68, 75, 81, 87, 93, 100};
static UINT8 avk_volume_set_phone[APP_AVK_VOLUME_MAX] = {0, 7, 15, 23, 31, 39, 47, 55, 63, 71, 79, 87, 95, 103, 111, 119, 127};
​
// 软件设计模式:状态模式 - 蓝牙调试状态
enum {
    DG_IDLE,
    DG_CONNECTED,
    DG_CONNECT_FAILED,
    DG_DISCONNECTED,
};
int bt_dg_flag = DG_IDLE;  // 蓝牙调试状态
​
#if (SUPPORT_BSA_A2DP_SOURCE == 1)
int bt_av_link_state = BT_LINK_DISCONNECTED;  // A2DP源状态
extern int avk_source_set_audio_output(char *ao_iface);  // 音频输出设置
#endif /* SUPPORT_BSA_A2DP_SOURCE */
​
#if (SUPPORT_BSA_PBC == 1)
// 软件设计模式:数据字典模式 - 电话簿路径定义
enum {
    TEL_ICH_PATH,       /* Path to local incoming calls history object */
    TEL_OCH_PATH,       /* Path to local outgoing calls history object */
    TEL_MCH_PATH,       /* Path to local missed calls history object */
    TEL_CCH_PATH,       /* Path to local combined calls history object */
    TEL_PB_PATH,        /* Path to local main phone book object */
    SIM1_TEL_ICH_PATH,  /* Path to SIM Card incoming calls history object */
    SIM1_TEL_OCH_PATH,  /* Path to SIM Card outgoing calls history object */
    SIM1_TEL_MCH_PATH,  /* Path to SIM Card missed calls history object */
    SIM1_TEL_CCH_PATH,  /* Path to SIM Card combined calls history object */
    SIM1_TEL_PB_PATH,   /* Path to SIM Card main phone book object */
};
​
// 可读性:清晰的路径映射,便于维护
static char *tel_str[] = {
    [TEL_ICH_PATH]       = "telecom/ich.vcf",       [TEL_OCH_PATH]       = "telecom/och.vcf",
    [TEL_MCH_PATH]       = "telecom/mch.vcf",   [TEL_CCH_PATH]       = "telecom/cch.vcf",
    [TEL_PB_PATH]        = "telecom/pb.vcf",        [SIM1_TEL_ICH_PATH]  = "SIM1/telecom/ich.vcf",
    [SIM1_TEL_OCH_PATH]  = "SIM1/telecom/och.vcf",  [SIM1_TEL_MCH_PATH]  = "SIM1/telecom/mch.vcf",
    [SIM1_TEL_CCH_PATH]  = "SIM1/telecom/cch.vcf",  [SIM1_TEL_PB_PATH]   = "SIM1/telecom/pb.vcf",
};
#endif /* SUPPORT_BSA_PBC */
#endif /* SUPPORT_BT */
​
// 软件设计模式:查找表模式 - 信号号到字符串映射
// 性能:数组查找O(1),比switch更高效
static char *signal_str[] = {
    [1] = "SIGHUP",       [2] = "SIGINT",       [3] = "SIGQUIT",      [4] = "SIGILL",      [5] = "SIGTRAP",
    [6] = "SIGABRT",      [7] = "SIGBUS",       [8] = "SIGFPE",       [9] = "SIGKILL",     [10] = "SIGUSR1",
    [11] = "SIGSEGV",     [12] = "SIGUSR2",     [13] = "SIGPIPE",     [14] = "SIGALRM",    [15] = "SIGTERM",
    [16] = "SIGSTKFLT",   [17] = "SIGCHLD",     [18] = "SIGCONT",     [19] = "SIGSTOP",    [20] = "SIGTSTP",
    [21] = "SIGTTIN",     [22] = "SIGTTOU",     [23] = "SIGURG",      [24] = "SIGXCPU",    [25] = "SIGXFSZ",
    [26] = "SIGVTALRM",   [27] = "SIGPROF",     [28] = "SIGWINCH",    [29] = "SIGIO",      [30] = "SIGPWR",
    [31] = "SIGSYS",      [34] = "SIGRTMIN",    [35] = "SIGRTMIN+1",  [36] = "SIGRTMIN+2", [37] = "SIGRTMIN+3",
    [38] = "SIGRTMIN+4",  [39] = "SIGRTMIN+5",  [40] = "SIGRTMIN+6",  [41] = "SIGRTMIN+7", [42] = "SIGRTMIN+8",
    [43] = "SIGRTMIN+9",  [44] = "SIGRTMIN+10", [45] = "SIGRTMIN+11", [46] = "SIGRTMIN+12", [47] = "SIGRTMIN+13",
    [48] = "SIGRTMIN+14", [49] = "SIGRTMIN+15", [50] = "SIGRTMAX-14", [51] = "SIGRTMAX-13", [52] = "SIGRTMAX-12",
    [53] = "SIGRTMAX-11", [54] = "SIGRTMAX-10", [55] = "SIGRTMAX-9",  [56] = "SIGRTMAX-8", [57] = "SIGRTMAX-7",
    [58] = "SIGRTMAX-6",  [59] = "SIGRTMAX-5",  [60] = "SIGRTMAX-4",  [61] = "SIGRTMAX-3", [62] = "SIGRTMAX-2",
    [63] = "SIGRTMAX-1",  [64] = "SIGRTMAX",
};
​
// 软件设计模式:帮助命令模式 - 统一的命令行接口
// 可读性:清晰的帮助信息格式
static void usage(const char *app_name)
{
    printf("%s [-bsh] \n"
           " -h     help (show this usage text)\n"
           " -s/-S  TODO\n"
           " -b/-B  run a daemon in the background\n", app_name);
​
    return;
}
​
char buf[16] = {};  // 性能:静态缓冲区,避免重复分配
​
// 软件设计模式:错误处理模式 - 统一的信号处理函数
// 性能:崩溃时资源清理,避免资源泄漏
void sig_handler(int signo)
{
    char cmd[64] = {};
    void *array[10];
    int size = 0;
    char **strings = NULL;
    int i = 0;
​
    // 可读性:详细的错误信息输出
    printf("\n\n[%s: %d] tang crashed by signal %s.\n", __func__, __LINE__, signal_str[signo]);
​
    // 架构特点:堆栈跟踪支持,便于调试
    printf("Call Trace:\n");
    size = backtrace(array, 10);
    strings = backtrace_symbols(array, size);
    if (strings) 
    {
        for (i = 0; i < size; i++)
        {
            printf ("  %s\n", strings[i]);
        }
        free (strings);  // 性能:及时释放堆栈字符串
    } 
    else 
    {
        printf("Not Found\n\n");
    }
​
    // 软件设计模式:条件诊断模式 - 针对特定信号额外诊断
    if (signo == SIGSEGV || signo == SIGBUS ||
        signo == SIGTRAP || signo == SIGABRT) 
    {
        sprintf(cmd, "cat /proc/%d/maps", getpid());
        printf("Process maps:\n");
        system(cmd);  // 性能:系统调用开销,但崩溃时可接受
    }
​
    // 软件设计模式:资源清理模式 - 有序关闭所有服务
    printf("stop all services\n");
    stopall(-1);
​
    printf("unregister event manager\n");
    tang_event_handler_put(keyevent_handler);
    tang_event_handler_put(miscevent_handler);
​
    printf("unregister network manager\n");
    unregister_from_networkmanager();
​
#if (SUPPORT_ALARM == 1)
    printf("unregister alarm manager\n");
    unregister_to_alarm_manager();
#endif
​
    // 架构特点:共享内存清理,避免残留
    share_mem_clear();
    share_mem_destory();
​
    exit(-1);  // 性能:立即退出,避免进一步损坏
}
​
#ifdef SUPPORT_VR
#if (SUPPORT_VR_WAKEUP == VR_WAKEUP_KEY_LONGPRESS)
// 软件设计模式:状态标志模式 - VR唤醒控制
int vr_flag = 0;
// 软件设计模式:异步任务模式 - VR长按键处理线程
// 性能:后台线程处理,不阻塞主流程
void *vr_longbutton_func(void *arg)
{
    vr_flag = 1;
    tang_vr_wakeup();  // VR唤醒功能
    vr_flag = 0;
​
    return NULL; // make compile happy. 可读性:明确的返回值说明
}
​
​
// 软件设计模式:工厂方法模式 - 创建特定功能的线程
// 代码可拓展性:通过条件编译支持不同VR唤醒方式,易于添加新的唤醒模式
// 运行性能:使用线程分离(detach)避免资源泄漏,减少线程管理开销
int create_vr_longbutton_pthread()
{
    int ret = 0;
    pthread_t vr_longbutton_thread = 0;
​
    // 架构优势:状态检查避免重复创建线程,防止资源竞争
    // 代码可读性:清晰的条件判断,防止重复启动
    if(vr_flag == 0) 
​
    {
        ret = pthread_create(&vr_longbutton_thread, NULL, vr_longbutton_func, NULL);
        if(ret != 0)
        {
            // 错误处理完善,提供详细的错误信息
            printf ("Create iflytek pthread failed: %s!\n", strerror(errno));
            return ret;
        }
        // 运行性能:分离线程,系统自动回收资源,避免僵尸线程
        pthread_detach(vr_longbutton_thread);
    }
​
    return ret;
}
#endif
#endif
​
// 软件设计模式:状态标志模式 - 使用布尔标志管理WiFi配置状态
// 代码可读性:变量命名清晰,明确表示WiFi配置状态
bool wifi_configing = false;
pthread_t wifi_config_pthread;
// 架构优势:使用静态初始化的互斥锁,避免动态初始化开销和竞争条件
pthread_mutex_t wifi_config_lock = PTHREAD_MUTEX_INITIALIZER;
​
// 软件设计模式:命令模式 - 将WiFi配置操作封装为可执行单元
// 运行性能:线程可取消,避免长时间阻塞,提高系统响应性
void *wifi_config_func(void *args)
{
    // 架构优势:设置线程取消状态,支持优雅的线程终止
    pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
    pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL);
​
    // 状态管理:设置配置状态,防止重复进入配置模式
    wifi_configing = true;
​
    // 代码可拓展性:模块化停止操作,便于扩展其他模块
    tang_module_stop();
    stopall(1);
    tang_config_wifi();
​
    // 状态清理:重置状态标志,允许后续操作
    wifi_configing = false;
​
    return NULL; // make compile happy.  // 代码可读性:明确的返回值说明
}
​
// 软件设计模式:线程池模式 - 管理WiFi配置线程的生命周期
// 架构优势:互斥锁保护,防止多线程竞争条件
int create_wifi_config_pthread(void)
{
    pthread_mutex_lock(&wifi_config_lock);
    // 代码可拓展性:支持取消前一个线程,避免资源泄漏
    // cancle previous thread.
    if (wifi_configing)
    {
        pthread_cancel(wifi_config_pthread);
    }
​
    // 运行性能:创建分离线程,系统自动管理资源
    // enter wifi config mode.
    if (pthread_create(&wifi_config_pthread, NULL, wifi_config_func, NULL) == -1) 
    {
        // 错误处理:详细的错误信息和资源清理
        printf("Create wifi config pthread failed: %s.\n", strerror(errno));
        pthread_mutex_unlock(&wifi_config_lock);
        return -1;
    }
    pthread_detach(wifi_config_pthread);
​
    pthread_mutex_unlock(&wifi_config_lock);
​
    return 0;
}
​
// 软件设计模式:模板方法模式 - WiFi切换与配置使用相似的模式
// 代码可读性:清晰的变量命名,与配置功能对应
bool wifi_switching = false;
pthread_t wifi_switch_pthread;
pthread_mutex_t wifi_switch_lock = PTHREAD_MUTEX_INITIALIZER;
​
// 架构优势:函数结构一致,便于维护和理解
void *wifi_switch_func(void *args)
{
    pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
    pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL);
​
    wifi_switching = true;
​
    // 代码可拓展性:统一的模块停止接口,支持功能扩展
    tang_module_stop();
    stopall(1);
    tang_wifi_mode();
​
    wifi_switching = false;
​
    return NULL; // make compile happy.
}
​
// 软件设计模式:代码复用模式 - 与配置线程创建逻辑高度一致
int create_wifi_switch_pthread(void)
{
    pthread_mutex_lock(&wifi_switch_lock);
    // cancle previous thread.
    if (wifi_switching)
    {
        pthread_cancel(wifi_switch_pthread);
    }
​
    // enter wifi switch mode.
    if (pthread_create(&wifi_switch_pthread, NULL, wifi_switch_func, NULL) == -1) 
    {
        printf("Create wifi switch pthread failed: %s.\n", strerror(errno));
        pthread_mutex_unlock(&wifi_switch_lock);
        return -1;
    }
    pthread_detach(wifi_switch_pthread);
​
    pthread_mutex_unlock(&wifi_switch_lock);
​
    return 0;
}
​
#if (SUPPORT_LOCALPLAYER == 1)
// 软件设计模式:回调模式 - TF卡扫描完成的事件通知
// 代码可拓展性:条件编译支持功能可选,便于产品定制
void tfcard_scan_1music_callback(void)
{
#if 0
    // 架构优势:状态管理,跟踪TF卡状态
    tfcard_status = 1;
    // 运行性能:异步启动本地音乐模块,不阻塞扫描过程
    tang_module_local_music_startup();
#endif
}
​
// 软件设计模式:观察者模式 - 扫描完成通知订阅者
// 代码可读性:清晰的函数命名,明确表示扫描完成
void tfcard_scan_done_callback(char *musiclist)
{
#if 1
    /* TODO; musicplayer add queue */
    // 架构优势:状态更新与模块启动分离,提高可测试性
    tfcard_status = 1;
    tang_module_local_music_startup();
#endif
}
#endif  /* SUPPORT_LOCALPLAYER */
​
// 软件设计模式:策略模式 - 根据蓝牙状态执行不同操作
// 运行性能:状态检查避免不必要的操作
static void key_bluetooth_handler(void)
{
#if (SUPPORT_BT == BT_BCM)
    int state = 0;
​
    // 架构优势:统一的状态获取接口,便于维护
    state = tang_bluetooth_hs_get_call_state();
    if (state == CALLSETUP_STATE_INCOMMING_CALL) 
    {
        // 代码可读性:清晰的日志输出,便于调试
        printf(">>>>>>>>>>>>>answer call>>>>>\n");
        tang_bluetooth_hs_answer_call();
    } 
    else if (state == CALL_STATE_LEAST_ONE_CALL_ONGOING ||
               state == CALLSETUP_STATE_OUTGOING_CALL ||
               state == CALLSETUP_STATE_REMOTE_BEING_ALERTED_IN_OUTGOING_CALL ||
               state == CALLHELD_STATE_NO_CALL_HELD) 
    {
        printf(">>>>>>>>>>>>>hang up>>>>>\n");
        tang_bluetooth_hs_hangup_call();
    }
    else if (state == CALLSETUP_STATE_WAITING_CALL) 
    {
        /* you can do other operation */
        // 代码可拓展性:预留扩展点,支持更多操作
        tang_bluetooth_hs_hold_call(BTHF_CHLD_TYPE_HOLDACTIVE_ACCEPTHELD);
    } 
    else if (state == CALLHELD_STATE_PLACED_ON_HOLD_OR_SWAPPED) 
    {
        /* you can do other operation */
        tang_bluetooth_hs_hold_call(BTHF_CHLD_TYPE_RELEASEACTIVE_ACCEPTHELD);
    } 
    else 
    {
        // 错误处理:不支持状态的明确提示
        printf("not support state : %d\n", state);
    }
#endif
}
​
#if (SUPPORT_BT == BT_BCM)
// 软件设计模式:自动重试模式 - 实现蓝牙自动重连机制
// 运行性能:互斥锁保护共享资源,避免竞争条件
static void *bt_auto_reconnect_pthread(void *args)
{
    /* auto reconnect time:
     * 10 minute */
    int ret = 0;
​
    // 架构优势:互斥锁保护重连逻辑,确保线程安全
    pthread_mutex_lock(&bt_reconnect_lock);
    bt_reconnect_num = 10;
    // 代码可读性:清晰的重试循环,最大重试次数控制
    while (bt_reconnect_num > 0) 
    {
        // 运行性能:状态检查避免不必要的重连尝试
        if (BT_LINK_DISCONNECTING == tang_bluetooth_get_link_status() ||
            BT_LINK_CONNECTING == tang_bluetooth_get_link_status() ||
            BT_LINK_DISCONNECTED == tang_bluetooth_get_link_status()) 
        {
            printf("bt_auto_reconnect_pthread start!\n");
            ret = tang_bluetooth_auto_reconnect(USE_HS_AVK, 0);
            printf("ret = %d\n", ret);
            if (ret == 0) 
            {
                printf("reconnect successful!\n");
                bt_reconnect_num = 0;
            } 
            else if (ret == -1) 
            {
                // 重试机制:失败时递减重试计数
                printf("reconnect failed, retry!\n");
                bt_reconnect_num--;
            } 
            else if (ret == -2) 
            {
                // 错误处理:特定错误码的特殊处理
                printf("bt_reconnect_devices.xml not existed, no connected device\n");
                bt_reconnect_num = 0;
            } 
            else 
            {
                printf("Not supported this type: %d\n", ret);
            }
        } 
        else if (BT_LINK_CONNECTED == tang_bluetooth_get_link_status()) 
        {
            // 运行性能:已连接状态立即退出,避免不必要的循环
            printf("bt link status == BT_LINK_CONNECTED !\n");
            bt_reconnect_num = 0;
        }
    }
​
    // 资源清理:重置重连状态
    bt_reconnect_num = 0;
    pthread_mutex_unlock(&bt_reconnect_lock);
    printf("return bt_auto_reconnect_pthread !\n");
​
    return NULL;
}
​
// 软件设计模式:简单工厂模式 - 创建蓝牙重连线程
// 代码可拓展性:易于扩展其他类型的蓝牙管理线程
int bluetooth_create_auto_reconnect_pthread()
{
    if (pthread_create(&bt_reconnect_pthread, NULL, bt_auto_reconnect_pthread, NULL) != 0) {
        printf("create bt_auto_reconnect_pthread failed !\n");
        return -1;
    }
    // 运行性能:分离线程,自动资源回收
    pthread_detach(bt_reconnect_pthread);
    return 0;
}
​
​
// 软件设计模式:命令模式 - 提供取消重连线程的统一接口
// 运行性能:直接设置标志位,无锁操作,快速响应取消请求
// 可读性:函数命名清晰,明确表示取消蓝牙重连线程
int bluetooth_cancel_auto_reconnect_pthread()
{
    bt_reconnect_num = 0;  // 架构优势:简单的标志位清零,立即终止重连循环
    return 0;
}
​
// 软件设计模式:工作者线程模式 - 专门处理蓝牙铃声播放
// 运行性能:循环播放铃声,sleep(1)控制播放间隔,避免CPU过度占用
static void *bluetooth_ring_pthread(void *args)
{
    bt_ring_flag = true;  // 状态管理:设置铃声播放标志
    while (bt_ring_flag) 
    {  
        // 架构优势:通过标志位控制循环,支持优雅终止
        printf("tang_play_key: bluetooth_ring\n");
        tang_play_key_sync("bluetooth_ring");  // 运行性能:同步播放,确保铃声完整性
        sleep(1);  // 性能考虑:1秒间隔平衡响应性和资源消耗
    }
​
    return NULL;
}
​
// 软件设计模式:工厂方法模式 - 创建铃声播放线程
// 可拓展性:统一的线程创建接口,易于扩展其他音频播放线程
int bluetooth_create_ring_pthread()
{
    if (pthread_create(&bt_ring_pthread, NULL, bluetooth_ring_pthread, NULL) != 0) 
    {
        printf("create bt_ring_pthread failed !\n");  // 错误处理:创建失败日志
        return -1;
    }
    pthread_detach(bt_ring_pthread);  // 资源管理:分离线程,系统自动回收资源
    return 0;
}
​
// 软件设计模式:资源清理模式 - 停止铃声播放并释放资源
// 运行性能:标志位设置立即生效,快速停止铃声循环
int bluetooth_cancel_ring_pthread()
{
    printf("bluetooth_cancel_ring_pthread !\n");  // 可读性:清晰的调试日志
    bt_ring_flag = false;  // 架构优势:原子操作停止循环,无需锁保护
​
    return tang_stop_tone();  // 代码设计:返回停止音调的结果,提供操作反馈
}
#endif
​
/*******************************************************************************
 * long press
 *******************************************************************************/
// 软件设计模式:状态机模式 - 定义长按按键的状态转换
// 可读性:枚举命名清晰,完整描述长按按键生命周期
enum key_long_press_state {
    KEY_LONG_PRESS_INVALID = 0,  // 初始或结束状态
    KEY_LONG_PRESS_WAIT,         // 等待判断长短按
    KEY_LONG_PRESS_CANCEL,       // 短按取消长按判断
    KEY_LONG_PRESS_DONE,         // 长按确认
};
​
// 软件设计模式:策略模式 + 观察者模式 - 按键信息与处理策略封装
// 架构优势:统一管理所有按键事件,支持动态处理策略
struct input_event_key_info {
    char *name;  // 可读性:按键名称,便于调试和日志
    int key_code;  // 硬件抽象:Linux输入事件键值
    enum key_long_press_state state;  // 状态管理:当前按键状态
    pthread_t pthread;  // 并发控制:每个按键独立线程
    pthread_mutex_t lock;  // 线程安全:保护状态变量
    pthread_cond_t cond;  // 同步机制:线程间通信
    int timeout_second;  // 配置灵活:可配置的长按超时时间
    void (*handler)(bool long_press);  // 策略模式:长短按不同处理函数
};
​
// 软件设计模式:策略实现 - WiFi切换处理策略
// 可拓展性:易于添加新的按键处理逻辑
static void wifi_switch_handler(bool long_press)
{
    if (long_press)
    {
        create_wifi_config_pthread();  // 长按进入配置模式
    }
    else
    {
        create_wifi_switch_pthread();  // 短按切换模式
    }
}
​
// 软件设计模式:策略实现 - 音量下降处理策略
// 用户体验:长短按实现不同功能,提高操作效率
static void volume_down_handler(bool long_press)
{
    if (long_press)
    {
        tang_previous_song();  // 长按上一曲
    }
    else
    {
        tang_volume_down();    // 短按音量减
    }
}
​
// 软件设计模式:策略实现 - 音量上升处理策略
// 架构优势:统一的处理模式,便于维护
static void volume_up_handler(bool long_press)
{
    if (long_press)
    {
        tang_next_song();  // 长按下一曲
    }
    else
    {
        tang_volume_up();  // 短按音量加
    }
}
​
// 软件设计模式:策略实现 - 播放暂停处理策略
// 功能集成:单一按键集成播放控制和蓝牙功能
static void play_pause_handler(bool long_press)
{
    if (long_press)
    {
        key_bluetooth_handler();  // 长按蓝牙控制
    }
    else
    {
        tang_play_pause();       // 短按播放暂停
    }
}
​
// 软件设计模式:注册表模式 - 集中管理所有按键配置
// 可拓展性:数组形式便于添加新按键,无需修改核心逻辑
static struct input_event_key_info input_event_key_infos[] = {
    {  // WiFi切换按键配置
        .name = "wifi_switch_key",
        .key_code = KEY_MODE,  // 硬件映射:Linux标准键值
        .lock = PTHREAD_MUTEX_INITIALIZER,  // 性能:静态初始化,避免运行时开销
        .cond = PTHREAD_COND_INITIALIZER,
        .timeout_second = 1,  // 用户体验:1秒长按阈值
        .handler = wifi_switch_handler,  // 策略绑定:WiFi处理函数
    },
    {  // 音量加按键配置
        .name = "volume_up_key", 
        .key_code = KEY_VOLUMEUP,
        .lock = PTHREAD_MUTEX_INITIALIZER,
        .cond = PTHREAD_COND_INITIALIZER,
        .timeout_second = 1,
        .handler = volume_up_handler,  // 策略绑定:音量加处理函数
    },
    {  // 音量减按键配置
        .name = "volume_down_key",
        .key_code = KEY_VOLUMEDOWN,
        .lock = PTHREAD_MUTEX_INITIALIZER,
        .cond = PTHREAD_COND_INITIALIZER,
        .timeout_second = 1,
        .handler = volume_down_handler,  // 策略绑定:音量减处理函数
    },
    {  // 播放暂停按键配置
        .name = "play_pause_key",
        .key_code = KEY_PLAYPAUSE,
        .lock = PTHREAD_MUTEX_INITIALIZER,
        .cond = PTHREAD_COND_INITIALIZER,
        .timeout_second = 1,
        .handler = play_pause_handler,  // 策略绑定:播放控制函数
    },
};
​
// 软件设计模式:状态机处理模式 - 长按按键判断逻辑
// 运行性能:条件变量实现高效等待,避免忙等待
static void *key_long_press_func(void *args)
{
    struct timeval now;
    struct timespec timeout;
    struct input_event_key_info *info = (struct input_event_key_info *)args;
​
    pthread_mutex_lock(&info->lock);
    // 状态检查:立即取消情况(快速释放)
    if (info->state == KEY_LONG_PRESS_CANCEL) 
    {
        info->state = KEY_LONG_PRESS_INVALID;
        printf("%s short press\n", info->name);  // 可读性:明确的状态日志
        if (info->handler)
            info->handler(false);  // 策略执行:短按处理
        pthread_mutex_unlock(&info->lock);
        return NULL;
    }
​
    // 超时设置:计算条件变量等待时间
    gettimeofday(&now, NULL);
    timeout.tv_sec = now.tv_sec + info->timeout_second;
    timeout.tv_nsec = now.tv_usec * 1000;  // 时间转换:微秒到纳秒
​
    // 运行性能:条件变量定时等待,精确控制长按时间
    pthread_cond_timedwait(&info->cond,
                           &info->lock, &timeout);
​
    // 状态判断:等待期间被取消
    if (info->state == KEY_LONG_PRESS_CANCEL) 
    {
        info->state = KEY_LONG_PRESS_INVALID;
        printf("%s short press\n", info->name);
        if (info->handler)
            info->handler(false);  // 策略执行:短按处理
        pthread_mutex_unlock(&info->lock);
        return NULL;
    }
​
    // 状态转换:确认长按操作
    info->state = KEY_LONG_PRESS_DONE;
​
    printf("%s long press\n", info->name);
    if (info->handler)
    {
        info->handler(true);  // 策略执行:长按处理
    }
    pthread_mutex_unlock(&info->lock);
​
    return NULL;
}
​
// 软件设计模式:工厂方法模式 - 创建长按检测线程
// 架构优势:统一的长按检测入口,状态检查防止重复创建
static void create_key_long_press_pthread(struct input_event_key_info *info)
{
    pthread_mutex_lock(&info->lock);
    // 状态验证:防止重复处理同一按键
    if (info->state != KEY_LONG_PRESS_INVALID) 
    {
        pthread_mutex_unlock(&info->lock);
        return ;
    }
    info->state = KEY_LONG_PRESS_WAIT;  // 状态更新:进入等待判断
    pthread_mutex_unlock(&info->lock);
​
    // 线程创建:每个按键独立的长按检测线程
    if (pthread_create(&info->pthread, NULL, key_long_press_func, (void *)info) == -1) 
    {
        printf("Create key long press pthread failed: %s.\n", strerror(errno));
        return ;
    }
    pthread_detach(info->pthread);  // 资源管理:分离线程自动回收
}
​
// 软件设计模式:状态转换模式 - 取消长按检测
// 运行性能:条件变量信号立即唤醒等待线程
static void key_long_press_cancel(struct input_event_key_info *info)
{
    pthread_mutex_lock(&info->lock);
​
    // 状态处理:根据当前状态执行不同取消逻辑
    if (info->state == KEY_LONG_PRESS_DONE) 
    {
        // 长按已完成,直接重置状态
        info->state = KEY_LONG_PRESS_INVALID;
    } 
    else if (info->state == KEY_LONG_PRESS_WAIT) 
    {
        // 正在等待,发送取消信号
        info->state = KEY_LONG_PRESS_CANCEL;
        pthread_cond_signal(&info->cond);  // 同步机制:立即唤醒等待线程
    }
​
    pthread_mutex_unlock(&info->lock);
}
​
​
// 软件设计模式:策略路由模式 - 根据输入事件路由到对应的按键处理器
// 运行性能:线性搜索O(n),但按键数量有限,实际性能可接受
// 可读性:清晰的循环结构,易于理解事件匹配逻辑
static int input_event_handler(struct input_event event)
{
    int i;
    struct input_event_key_info *info;
​
    // 架构优点:使用编译时计算数组大小,避免硬编码
    // 可拓展性:新增按键只需在数组中添加,无需修改此函数
    for (i = 0; i < sizeof(input_event_key_infos) / sizeof(struct input_event_key_info); i++) 
    {
        info = &input_event_key_infos[i];
​
        // 事件匹配:根据键值匹配预定义的按键配置
        if (event.code == info->key_code) 
        {
            // 状态机驱动:按键按下启动长按检测,释放取消检测
            if (event.value == 1)
            {
                create_key_long_press_pthread(info);  // 按下:开始长按检测
            }
            else
            {
                key_long_press_cancel(info);          // 释放:取消长按检测
            }
​
            return 0;  // 性能优化:匹配成功立即返回
        }
    }
​
    return -1;  // 未匹配的按键事件
}
​
// 软件设计模式:观察者模式 - 事件回调函数,响应系统事件
// 架构优点:统一的事件处理入口,模块化设计
void keyevent_callback(tang_event event, void *param)
{
    // 软件设计模式:状态模式 - 根据事件类型分支处理
    switch (event.type) {
    case EVENT_KEY:
        // 输入验证:确保是键盘事件,提高代码健壮性
        if (event.event.key.key.type != EV_KEY)
        {
            printf("Only support keyboard now.\n");
            break;
        }
        // 可读性:详细的调试日志,便于问题定位
        printf("[DEBUG] key %s %s!!!\n",
               keycode_str[event.event.key.key.code], keyvalue_str[event.event.key.key.value]);
​
#if (SUPPORT_USB_AUDIO == 1)
        // 软件设计模式:条件过滤模式 - USB音频模式下的按键过滤
        // 架构优点:功能隔离,USB模式下限制部分按键功能
        if(tang_usb_audio_is_in() == 1)
        {
            if (event.event.key.key.code != KEY_POWER
                && event.event.key.key.code != KEY_VOLUMEUP
                && event.event.key.key.code != KEY_VOLUMEDOWN)
            {
                    return;  // 性能优化:早期返回避免不必要处理
            }
        }
#endif
        // 软件设计模式:责任链模式 - 先尝试通用长按处理,再处理特殊按键
        // 运行性能:通用处理成功则提前返回
        if (input_event_handler(event.event.key.key) == 0)
            break;
​
        // 按键按下事件处理(非长按按键)
        if (event.event.key.key.value == 1) {
            // 软件设计模式:命令模式 - 将按键映射到具体操作命令
            switch (event.event.key.key.code)
            {
            case KEY_RECORD:
#ifdef SUPPORT_VR
                // 软件设计模式:状态依赖命令 - 根据VR状态执行不同操作
                // 可拓展性:支持多种VR唤醒模式的条件编译
#if (SUPPORT_VR_WAKEUP == VR_WAKEUP_KEY_SHORTPRESS || SUPPORT_VR_WAKEUP == VR_WAKEUP_VOICE_KEY_MIX)
                // 状态机决策:根据VR当前状态选择相应操作
                if (tang_vr_get_status() == VR_AEC) {
                    printf("AEC mode, wakeup\n");
                    tang_vr_aec_wakeup();  // AEC模式下的唤醒
                } else if (tang_vr_get_status() == VR_ASR) {
                    printf("ASR mode, interrupt\n");
                    tang_vr_asr_break();   // ASR模式下的中断
                }
#elif (SUPPORT_VR_WAKEUP == VR_WAKEUP_KEY_LONGPRESS)
                // 异步处理:创建VR长按线程,避免阻塞主线程
                if(create_vr_longbutton_pthread()) {  // in case of block.
                    printf("create_iflytek_pthread failed!\n");
                    break;
                }
#endif
#endif
                break;
            case KEY_F1:
                // 软件设计模式:工厂方法调用 - 创建WiFi配置线程
                create_wifi_config_pthread(); // in case of block.
                break;
            case KEY_BLUETOOTH:
                // 直接函数调用:蓝牙按键处理
                key_bluetooth_handler();
                break;
            case KEY_PREVIOUSSONG:
                // 命令执行:上一曲操作
                tang_previous_song();
                break;
            case KEY_NEXTSONG:
                // 命令执行:下一曲操作
                tang_next_song();
                break;
            case KEY_MENU:
                // 命令执行:音源切换
                tang_snd_source_switch();
                break;
            case KEY_F3:            /* music music Shortcut key 1 */
                // 软件设计模式:参数化命令 - 带参数的快捷操作
                tang_music_list(0);
                break;
            case KEY_F4:            /* music music Shortcut key 2 */
                tang_music_list(1);
                break;
            case KEY_F5:            /* music music Shortcut key 3 */
                tang_music_list(2);
                break;
            case KEY_POWER:
                // 系统命令:关机操作
                tang_power_off();
                break;
            default:
                // 架构优点:静默处理未支持按键,避免不必要的日志输出
                //printf("UnSupport key down in %s:%s:%d.\n", __FILE__, __func__, __LINE__);
                break;
            }
        } else {
            // 按键释放事件处理
            // 软件设计模式:有限状态机 - 处理按键释放状态
            switch (event.event.key.key.code) {
            case KEY_RECORD:
                /*TODO: add VR_WAKEUP_KEY_LONGPRESS support*/
                // 可拓展性:预留VR长按释放处理接口
                break;
            default:
                // 大多数按键释放不需要特殊处理
                break;
            }
        }
        break;
    case EVENT_MISC:
    default:
        // 软件设计模式:默认处理 - 忽略不支持的事件类型
        // 架构优点:良好的向前兼容性
        break;
    }
​
    return;
}
​
// 软件设计模式:观察者模式 - 处理各种杂项事件的回调函数
// 架构优点:统一的事件处理入口,模块化设计
void miscevent_callback(tang_event event, void *param)
{
    // 软件设计模式:状态模式 - 根据事件类型分支处理
    switch (event.type) {
    case EVENT_MISC:
        // 可读性:清晰的事件日志,便于调试
        printf("[misc event] %s : %s.\n", event.event.misc.name, event.event.misc.type);
        
        // 软件设计模式:策略模式 - 根据事件名称路由到不同处理逻辑
        // Linein事件处理
        if (!strcasecmp(event.event.misc.name, "linein")
#if (SUPPORT_MULROOM == 1)
            && mulroom_state != MUL_GROUP_RECEIVER  // 架构优点:状态检查,避免冲突
#endif /* SUPPORT_MULROOM == 1 */
            ) {
            if (!strcasecmp(event.event.misc.type, "plugin")) { // linein plugin
                // 运行性能:UI更新与硬件操作分离
                tang_ui_linein_plugin();
                tang_module_stop();
                tang_linein_on();
                lapsule_do_linein_on();  // 特定硬件操作
            } else if (!strcasecmp(event.event.misc.type, "plugout")) { // linein plugout
                tang_ui_linein_plugout();
                tang_linein_off();
                lapsule_do_linein_off();
            }
        } else if(!strcasecmp(event.event.misc.name, "usb")) {
#if 0
            // 架构缺点:注释掉的代码影响可读性,应该移除或使用条件编译
            if (!strcasecmp(event.event.misc.type, "connected")) { // usb plugin
                system("umount /mnt/sdcard/");
                system("echo /dev/mmcblk0p1 > /sys/devices/platform/jz-dwc2/dwc2/gadget/lun0/file");
            } else if (!strcasecmp(event.event.misc.type, "disconnected")) { // usb plugout
                system("echo  0 > /sys/class/android_usb/android0/enable");
                system("mount /dev/mmcblk0p1 /mnt/sdcard/");
            }
#endif
#if (SUPPORT_USB_AUDIO == 1)
        } else if(!strcasecmp(event.event.misc.name, "uaudio")) {
            // 可拓展性:USB音频功能的条件编译支持
            if (!strcasecmp(event.event.misc.type, "connected")) {
                tang_usb_audio_plug_in();
            }else if(!strcasecmp(event.event.misc.type,"disconnected")){
                tang_usb_audio_plug_out();
            }
#endif
        } else if (!strcasecmp(event.event.misc.name, "tfcard")) {
            // 软件设计模式:状态检查模式 - 避免重复处理
            if (!strcasecmp(event.event.misc.type, "plugin")) { // tfcard plugin
                if (tfcard_status != 1) {
                    tang_ui_localplayer_plugin();
                    tang_play_key("tf_add");
                    tfcard_status = 1;  // 状态管理:更新TF卡状态
                } else {
                    // do nothing.  // 运行性能:避免重复操作
                }
            } else if (!strcasecmp(event.event.misc.type, "plugout")) { // tfcard plugout
                if (tfcard_status != 0) {
                    tang_ui_localplayer_plugout();
#if (SUPPORT_LOCALPLAYER == 1)
                    if (snd_source == SND_SRC_LOCALPLAY)
                        tang_musicplayer_stop(tang_musicplayer_handler);  // 条件停止播放器
#endif
                    tang_play_key("tf_remove");
                    tfcard_status = 0;
                }
            }
        } else if (!strcasecmp(event.event.misc.name, "headset")) {
            // 架构缺点:空实现,应该移除或添加实际功能
            if (!strcasecmp(event.event.misc.type, "plugin")) { // headset plugin
                printf("headset plugin.\n");
                // do nothing.
            } else if (!strcasecmp(event.event.misc.type, "plugout")) { // headset plugout
                printf("headset plugout.\n");
                // do nothing.
            }
        } else if (!strcasecmp(event.event.misc.name, "spdif")) {
            // 类似地,空实现影响代码质量
            if (!strcasecmp(event.event.misc.type, "plugin")) { // spdif-out plugin
                printf("spdif plugin.\n");
                // do nothing.
            } else if (!strcasecmp(event.event.misc.type, "plugout")) { // spdif-out plugout
                printf("spdif plugout.\n");
                // do nothing.
            }
        } else if (!strcasecmp(event.event.misc.name, "volume")) {
            // 软件设计模式:事件日志模式 - 记录但不处理
            if (!strcasecmp(event.event.misc.type, "update music")) {
                printf("%s volume to %d.\n", event.event.misc.type, event.event.misc.value[0]);
            } else if (!strcasecmp(event.event.misc.type, "update bt_music")) {
                printf("%s volume to %d.\n", event.event.misc.type, event.event.misc.value[0]);
            } else if (!strcasecmp(event.event.misc.type, "update bt_call")) {
                printf("%s volume to %d.\n", event.event.misc.type, event.event.misc.value[0]);
            } else if (!strcasecmp(event.event.misc.type, "update unknown")) {
                printf("%s volume to %d.\n", event.event.misc.type, event.event.misc.value[0]);
            } else {
                printf("unhandle volume event: %s.\n", event.event.misc.type);
            }
#if (SUPPORT_BT == BT_BCM)
        } else if (!strcasecmp(event.event.misc.name, "bluetooth")) {
            // 软件设计模式:复杂状态机 - 蓝牙连接状态管理
            if (!strcasecmp(event.event.misc.type, "connecting")) {
                ; // do nothing if bluetooth device is connecting.
            } else if (!strcasecmp(event.event.misc.type, "disc_new")) {
            } else if (!strcasecmp(event.event.misc.type, "disc_complete")) {
                bsa_start_regular_enable = 1;  // 状态更新:发现完成
            } else if (!strcasecmp(event.event.misc.type, "sec_link_down")) {
                /*
                 * Reason code 0x13: Mobile terminate bluetooth connection
                 * Reason code 0x8: connection timeout(beyond distance)
                 */
                // 软件设计模式:错误分类处理
                UINT8 link_down_data = 0;
                link_down_data = tang_bluetooth_get_link_down_status();
                if (link_down_data == 0x13) {
                    printf("Mobile terminate bluetooth connection.\n");
                } else if (link_down_data == 0x8) {
                    printf("BT connection timeout(beyond distance maybe)!\n");
                    int state = 0;
                    state = bluetooth_create_auto_reconnect_pthread();  // 自动重连
                    if (state == 0) {
                        printf("bluetooth_create_auto_reconnect_pthread success !\n");
                    } else if (state == -1) {
                        printf("bluetooth_create_auto_reconnect_pthread failed !\n");
                    }
                } else if (link_down_data == 0x16) {
                    printf("connection terminated by local host!\n");
                } else {
                    printf("not handle link_down_data %d, Ignore.\n", link_down_data);
                }
            } else {
                printf("unhandle bluetooth event: %s.\n", event.event.misc.type);
            }
        } else if (!strcasecmp(event.event.misc.name, "bt_hs")) {
            // 软件设计模式:事件处理链 - 蓝牙电话事件处理
            if (!strcasecmp(event.event.misc.type, "connected")) {
                if (tang_bluetooth_get_link_status() == BT_LINK_CONNECTED) {
                    if (bt_link_state == BT_LINK_DISCONNECTED) {
                        bt_link_state = BT_LINK_CONNECTED;
                        tang_ui_bt_connected();
                        tang_bluetooth_set_visibility(0, 0);
                        //tang_module_stop();
                        /* FIXME: do not stop if music playing. will skip tone. */
                        tang_play_key_sync("bluetooth_connect");  // 同步播放连接音
                        /* snd_source = SND_SRC_BT_AVK; */
                    }
#if (SUPPORT_BSA_PBC == 1)
                    tang_bluetooth_pbc_open_connection();  // 电话本连接
#endif
                }
            } else if (!strcasecmp(event.event.misc.type, "disconnected")) {
                bluetooth_cancel_ring_pthread();  // 资源清理:停止铃声
                if (tang_bluetooth_get_link_status() == BT_LINK_DISCONNECTED) {
                    if (bt_link_state == BT_LINK_CONNECTED) {
                        bt_link_state = BT_LINK_DISCONNECTED;
                        tang_play_key("bluetooth_disconnect");
                        tang_bluetooth_set_visibility(1, 1);
                        tang_ui_bt_disconnected();
                    }
#if (SUPPORT_BSA_PBC == 1)
                    tang_bluetooth_pbc_close_connection();
#endif
                }
            } else if (!strcasecmp(event.event.misc.type, "ring")) {
                // 软件设计模式:资源冲突管理 - VR与蓝牙铃声互斥
#ifdef SUPPORT_VR
                if (tang_vr_get_status()) {
                    printf("invoking tang_vr_stop()\n");
                    tang_vr_stop();  // 停止VR以播放铃声
                }
#endif
                //TODO: should pause here, resume music after hangup.
                if (tang_module_stop()) {
                    printf("can not ring.\n");
                } else {
                    bluetooth_create_ring_pthread();  // 创建铃声线程
                    snd_source = SND_SRC_BT_AVK;      // 更新音源状态
                }
            } else if (!strcasecmp(event.event.misc.type, "hangup")) {
                bluetooth_cancel_ring_pthread();      // 停止铃声
#ifdef SUPPORT_VR
                if(!tang_vr_get_status()) {
                    printf("invoking tang_vr_start()\n");
                    tang_vr_start();  // 挂断后重启VR
                }
#endif
            } else if (!strcasecmp(event.event.misc.type, "call")) {
                bluetooth_cancel_ring_pthread();
#ifdef SUPPORT_VR
                if (tang_vr_get_status()) {
                    printf("invoking tang_vr_stop()\n");
                    tang_vr_stop();
                }
#endif
                //TODO: should pause here, resume music after hangup.
                if (tang_module_stop()) {
                    share_mem_set(BT_HS_DOMAIN, RESPONSE_CANCEL);  // 共享内存通信
                } else {
                    share_mem_set(BT_HS_DOMAIN, RESPONSE_DONE);
                    snd_source = SND_SRC_BT_AVK;
                }
            } else if (!strcasecmp(event.event.misc.type, "close")) {
            } else if (!strcasecmp(event.event.misc.type, "vgs")) {
                // 软件设计模式:数据转换 - 手机音量到设备音量的映射
                int volume = event.event.misc.value[0];
                tang_volume_set(volume * 100 / APP_HS_CALL_VOLUME_MAX, BT_CALL_VOLUME);
                printf("phone volume: %d, tang set hs volume: %d\n",
                       volume,
                       volume * 100 / APP_HS_CALL_VOLUME_MAX);
            } else {
                printf("unhandle bt phone event: %s.\n", event.event.misc.type);
            }
        } else if (!strcasecmp(event.event.misc.name, "bt_avk")) {
            // 软件设计模式:事件镜像 - 与bt_hs类似但独立的处理逻辑
            if (!strcasecmp(event.event.misc.type, "connected")) {
                if (tang_bluetooth_get_link_status() == BT_LINK_CONNECTED) {
                    if (bt_link_state == BT_LINK_DISCONNECTED) {
                        bt_link_state = BT_LINK_CONNECTED;
                        tang_ui_bt_connected();
                        tang_bluetooth_set_visibility(0, 0);
                        //tang_module_stop();
                        /* FIXME: do not stop if music playing. will skip tone. */
                        tang_play_key_sync("bluetooth_connect");
                    }
                }
            } else if (!strcasecmp(event.event.misc.type, "disconnected")) {
                if (tang_bluetooth_get_link_status() == BT_LINK_DISCONNECTED) {
                    if (bt_link_state == BT_LINK_CONNECTED) {
                        bt_link_state = BT_LINK_DISCONNECTED;
                        tang_play_key("bluetooth_disconnect");
                        tang_bluetooth_set_visibility(1, 1);
                        tang_ui_bt_disconnected();
                    }
                }
            } else if (!strcasecmp(event.event.misc.type, "play")) {
                if (tang_module_stop()) {
                    share_mem_set(BT_AVK_DOMAIN, RESPONSE_CANCEL);
                } else {
                    share_mem_set(BT_AVK_DOMAIN, RESPONSE_DONE);
                    snd_source = SND_SRC_BT_AVK;
                }
            } else if (!strcasecmp(event.event.misc.type, "pause")) {
                printf("bt music player paused(or stopped).\n");
            } else if (!strcasecmp(event.event.misc.type, "set_abs_vol")) {
                // 软件设计模式:查找表模式 - 音量映射
                int index = 0;
                int volume = 0;
                int fd = 0;
                volume = event.event.misc.value[0];
                fd = event.event.misc.value[1];
                // 逆向查找音量映射
                for (index = (APP_AVK_VOLUME_MAX -1); index >= 0; index--) {
                    if (avk_volume_set_phone[index] <= volume)
                        break;
                }
                if (index < 0) {
                    printf("failed to get music volume %d from avk_volume_set_dsp\n", volume);
                    break;
                }
                // 软件设计模式:适配器模式 - 支持不同音频后端
                if (AUDIO_OSS == get_audio_type()) {
                    /* Note: add app_avk_cb.fd judged, because when play tts,
                     * we reviced ABS_VOL_CMD_EVT, and set volume to dsp,
                     * it will generate a case of sound mutation */
                    if (fd != -1) {
                        tang_volume_set(avk_volume_set_dsp[index], BT_MUSIC_VOLUME);
                    } else {
                        // 配置持久化
                        char vol[8] = {};
                        sprintf(vol, "%d", avk_volume_set_dsp[index]);
                        if (tang_ini_setkey("/usr/data/system.ini", "volume", "bt_music", vol)) {
                            printf("save volume to /usr/data/system.ini error.\n");
                            break;
                        }
                    }
                } else if (AUDIO_ALSA == get_audio_type()) {
                    tang_volume_set(avk_volume_set_dsp[index], BT_MUSIC_VOLUME);
                } else {
                    printf("Not support audio type: %d!!\n", get_audio_type());
                }
                printf("phone volume: 0x%x, tang set avk volume: %d\n",
                        volume,
                        avk_volume_set_dsp[index]);
            } else if (!strcasecmp(event.event.misc.type, "get_elem_attr")) {
                // 软件设计模式:数据解析模式 - 解析音乐元数据
                int i = 0;
                int attr_id = 0;
                tBSA_AVK_GET_ELEMENT_ATTR_MSG *p_data = NULL;
                p_data = tang_bluetooth_avk_get_element_att();
                printf("p_data->num_attr = %d\n", p_data->num_attr);
                printf("p_data->status = %d\n", p_data->status);
                for (i = 0; i < p_data->num_attr; i++) {
                    attr_id = p_data->attr_entry[i].attr_id;
                    // 音乐信息分类输出
                    if (attr_id == AVRC_MEDIA_ATTR_ID_TITLE) {
                        printf("music Title: %s\n", p_data->attr_entry[i].name.data);
                    } else if (attr_id == AVRC_MEDIA_ATTR_ID_ARTIST) {
                        printf("music Artist Name: %s\n", p_data->attr_entry[i].name.data);
                    } else if (attr_id == AVRC_MEDIA_ATTR_ID_ALBUM) {
                        printf("music Album Name: %s\n", p_data->attr_entry[i].name.data);
                    } else if (attr_id == AVRC_MEDIA_ATTR_ID_TRACK_NUM) {
                        printf("music Track Number: %s\n", p_data->attr_entry[i].name.data);
                    } else if (attr_id == AVRC_MEDIA_ATTR_ID_NUM_TRACKS) {
                        printf("music Total Number of Tracks: %s\n", p_data->attr_entry[i].name.data);
                    } else if (attr_id == AVRC_MEDIA_ATTR_ID_GENRE) {
                        printf("music Genre: %s\n", p_data->attr_entry[i].name.data);
                    } else if (attr_id == AVRC_MEDIA_ATTR_ID_PLAYING_TIME) {
                        printf("music Playing Time: %s\n", p_data->attr_entry[i].name.data);
                    }
                }
            } else if (!strcasecmp(event.event.misc.type, "play_status")) {
                // 运行性能:获取播放状态信息
                tBSA_AVK_GET_PLAY_STATUS_MSG *play_status_msg;
                play_status_msg = tang_bluetooth_avk_get_play_status();
                printf("play status : %d\n", play_status_msg->play_status);
                printf("play song len : %d\n", play_status_msg->song_len);
                printf("play song pos : %d\n", play_status_msg->song_pos);
            } else {
                printf("unhandle bt music event: %s.\n", event.event.misc.type);
            }
        } else if (!strcasecmp(event.event.misc.name, "bt_av")) {
            // A2DP源模式处理
            if (!strcasecmp(event.event.misc.type, "open")) {
                /* open successful */
                if (event.event.misc.value[0] == 0) {
#if (SUPPORT_BSA_A2DP_SOURCE == 1)
                    bt_av_link_state = BT_LINK_CONNECTED;
                    char *ao_iface = "stream:sockfile=/var/run/bt-av-stream.socket";
                    avk_source_set_audio_output(ao_iface);  // 设置音频输出接口
#endif
                /* open failed */
                } else {
#if (SUPPORT_BSA_A2DP_SOURCE == 1)
                    bt_av_link_state = BT_LINK_CONNECT_FAILED;
#endif
                    printf("AV open failed!\n");
                }
            } else if (!strcasecmp(event.event.misc.type, "disconnected")) {
#if (SUPPORT_BSA_A2DP_SOURCE == 1)
                bt_av_link_state = BT_LINK_DISCONNECTED;
                char *ao_iface = "oss:/dev/dsp";  // 回退到默认音频输出
                avk_source_set_audio_output(ao_iface);
#endif
            } else if (!strcasecmp(event.event.misc.type, "play")) {
            } else if (!strcasecmp(event.event.misc.type, "pause")) {
            /* REMOTE_CMD_EVT */
            } else if (!strcasecmp(event.event.misc.type, "RC")) {
                // 软件设计模式:命令分发模式 - 远程控制命令处理
                int av_cur_play_state;
                switch(event.event.misc.value[0]) {
                    case BSA_AV_RC_PLAY:
                        printf("AV RC Play!\n");
                        av_cur_play_state = tang_bluetooth_av_get_play_state();
                        switch (av_cur_play_state) {
                            case APP_AV_PLAY_PAUSED:
                                tang_bluetooth_av_resume_play();
                                break;
                            case APP_AV_PLAY_STOPPED:
                                break;
                            case APP_AV_PLAY_STARTED:
                                /* Already started */
                                break;
                            case APP_AV_PLAY_STOPPING:
                                /* Stop in progress */
                                break;
                            default:
                                printf("Unsupported play state (%d)\n", av_cur_play_state);
                                break;
                        }
                        break;
                    case BSA_AV_RC_STOP:
                        printf("AV RC Stop!\n");
                        tang_bluetooth_av_stop_play();
                        break;
                    case BSA_AV_RC_PAUSE:
                        printf("AV RC Pause!\n");
                        tang_bluetooth_av_pause_play();
                        break;
                    case BSA_AV_RC_FORWARD:
                        printf("AV RC Forward!\n");
                        break;
                    case BSA_AV_RC_BACKWARD:
                        printf("AV RC Backward!\n");
                        break;
                    case BSA_AV_RC_VOL_UP:
                        printf("AV RC VOl_UP!\n");
                        break;
                    case BSA_AV_RC_VOL_DOWN:
                        printf("AV RC VOl_DOWN!\n");
                        break;
                    default:
                        printf("key: 0x%x", event.event.misc.value[0]);
                        break;
                }
            } else if (!strcasecmp(event.event.misc.type, "rc_open")) {
            } else if (!strcasecmp(event.event.misc.type, "rc_close")) {
            } else {
                printf("unhandle bt music event: %s.\n", event.event.misc.type);
            }
        } else if (!strcasecmp(event.event.misc.name, "bt_ble")) {
            // BLE蓝牙低功耗处理
            if (!strcasecmp(event.event.misc.type, "disc_new")) {
            } else if (!strcasecmp(event.event.misc.type, "disc_complete")) {
                bsa_ble_start_regular_enable = 1;
#if (SUPPORT_BSA_BLE_HH == 0)
                // 软件设计模式:设备枚举模式 - 遍历发现的BLE设备
                int index;
                tAPP_DISCOVERY_CB *app_discovery_cb = NULL;
                app_discovery_cb = tang_bluetooth_disc_get_device_info();
                for (index = 0; index < APP_DISC_NB_DEVICES; index++) {
                    if (app_discovery_cb->devs[index].in_use != FALSE) {
                        printf("Dev: %d\n", index);
                        // 设备信息详细输出
                        printf("\tBdaddr:%02x:%02x:%02x:%02x:%02x:%02x \n",
                                app_discovery_cb->devs[index].device.bd_addr[0],
                                app_discovery_cb->devs[index].device.bd_addr[1],
                                app_discovery_cb->devs[index].device.bd_addr[2],
                                app_discovery_cb->devs[index].device.bd_addr[3],
                                app_discovery_cb->devs[index].device.bd_addr[4],
                                app_discovery_cb->devs[index].device.bd_addr[5]);
                        printf("\tName: %s\n", app_discovery_cb->devs[index].device.name);
                        char *ble_name = (char *)app_discovery_cb->devs[index].device.name;
                        if (!strcmp(ble_name, "BSA_BLE"))
                        {
                            // 特定设备的制造商数据解析
                            bsa_manu_data manu_data;
                            int index = 0;
                            UINT8 * eir_data = app_discovery_cb->devs[index].device.eir_data;
                            tang_bluetooth_parse_eir_manuf_specific(eir_data, &manu_data);
                            printf("manu_data.data_length = %d\n", manu_data.data_length);
                            printf("manu_data.company_id = 0x%02x\n", manu_data.company_id);
                            printf("manu_data: \n");
                            for (index = 0; index < manu_data.data_length; index++)
                            {
                                printf("%x ", manu_data.p_manu[index]);
                            }
                            printf("\n");
                        }
                        printf("\tClassOfDevice: %02x:%02x:%02x => %s\n",
                               app_discovery_cb->devs[index].device.class_of_device[0],
                               app_discovery_cb->devs[index].device.class_of_device[1],
                               app_discovery_cb->devs[index].device.class_of_device[2],
                               tang_bluetooth_get_cod_string(app_discovery_cb->devs[index].device.class_of_device));
                        printf("\tRssi: %d\n", app_discovery_cb->devs[index].device.rssi);
                        if (app_discovery_cb->devs[index].device.eir_vid_pid[0].valid) {
                            printf("\tVidSrc: %d Vid: 0x%04X Pid: 0x%04X Version: 0x%04X",
                                   app_discovery_cb->devs[index].device.eir_vid_pid[0].vendor_id_source,
                                   app_discovery_cb->devs[index].device.eir_vid_pid[0].vendor,
                                   app_discovery_cb->devs[index].device.eir_vid_pid[0].product,
                                   app_discovery_cb->devs[index].device.eir_vid_pid[0].version);
                        }
                    }
                }
#endif
            } else {
                printf("unhandle bt ble event: %s.\n", event.event.misc.type);
            }
        } else if (!strcasecmp(event.event.misc.name, "bt_hh")) {
            // 蓝牙HID设备处理
            if (!strcasecmp(event.event.misc.type, "add_dev")) {
                ble_hh_add_dev_enable = 1;
            } else if (!strcasecmp(event.event.misc.type, "connected")) {
            } else if (!strcasecmp(event.event.misc.type, "close")) {
            } else {
                printf("unhandle bt hh event: %s.\n", event.event.misc.type);
            }
        } else if (!strcasecmp(event.event.misc.name, "bt_avrcp")) {
            // AVRCP协议事件处理
            if (!strcasecmp(event.event.misc.type, "playing")) {
                printf("playing!\n");
            } else if (!strcasecmp(event.event.misc.type, "paused")) {
                printf("pause!\n");
            } else if (!strcasecmp(event.event.misc.type, "stopped")) {
                printf("stopped!\n");
            } else if (!strcasecmp(event.event.misc.type, "track_change")) {
                tang_bluetooth_avk_send_get_element_att_cmd();  // 获取新曲目信息
            } else if (!strcasecmp(event.event.misc.type, "play_pos")) {
                printf("play_pos: %d\n", event.event.misc.value[0]);
            }
        } else if (!strcasecmp(event.event.misc.name, "bt_ops")) {
            // 对象推送服务处理
            if (!strcasecmp(event.event.misc.type, "connected")) {
            } else if (!strcasecmp(event.event.misc.type, "disconnected")) {
            } else if (!strcasecmp(event.event.misc.type, "send_request")) {
                char *ops_file_name = NULL;
                ops_file_name = tang_bluetooth_ops_get_object_name();
                printf("ops_file_name = %s\n", ops_file_name);
                printf("len = %d\n", strlen(ops_file_name));
            } else if (!strcasecmp(event.event.misc.type, "send_start")) {
            } else if (!strcasecmp(event.event.misc.type, "send_end")) {
            }
        } else if (!strcasecmp(event.event.misc.name, "bt_dg")) {
            // 蓝牙调试事件处理
            if (!strcasecmp(event.event.misc.type, "open")) {
                printf("state: %d\n", event.event.misc.value[0]);
                if (event.event.misc.value[0] == 0)
                    bt_dg_flag = DG_CONNECTED;
                else if (event.event.misc.value[0] == 1)
                    bt_dg_flag = DG_CONNECT_FAILED;
            } else if (!strcasecmp(event.event.misc.type, "disconnected")) {
                bt_dg_flag = DG_DISCONNECTED;
            } else if (!strcasecmp(event.event.misc.type, "find_service")) {
            }
        /* phone book client */
        } else if (!strcasecmp(event.event.misc.name, "bt_pbc")) {
            // 电话本客户端处理
            if (!strcasecmp(event.event.misc.type, "connected")) {
#if (SUPPORT_BSA_PBC == 1)
                tang_bluetooth_pbc_get_phonebook(tel_str[TEL_PB_PATH]);  // 获取电话本
#endif /* SUPPORT_BSA_PBC */
            } else if (!strcasecmp(event.event.misc.type, "disconnected")) {
            }
#endif /* SUPPORT_BT */
        } else if (!strcasecmp(event.event.misc.name, "dlna")) {
            // DLNA媒体服务器事件处理
            if (!strcasecmp(event.event.misc.type, "connected")) {
                ; // do nothing on dlna device connected event
            } else if (!strcasecmp(event.event.misc.type, "disconnected")) {
                ; // do nothing on dlna device disconnected event
            } else if (!strcasecmp(event.event.misc.type, "play")){
                if (tang_module_stop())
                    share_mem_set(RENDER_DOMAIN, RESPONSE_CANCEL);
                else
                    share_mem_set(RENDER_DOMAIN, RESPONSE_DONE);
            } else if (!strcasecmp(event.event.misc.type, "pause")){
                printf("dlna player paused.\n");
            } else if (!strcasecmp(event.event.misc.type, "resume")){
                printf("dlna player resume.\n");
            } else {
                printf("unhandle dlna event: %s.\n", event.event.misc.type);
            }
        } else if (!strcasecmp(event.event.misc.name, "musicplayer")) {
            // 音乐播放器事件处理
            if (!strcasecmp(event.event.misc.type, "play")) {
                if (tang_module_stop())
                    share_mem_set(MUSICPLAYER_DOMAIN, RESPONSE_CANCEL);
                else
                    share_mem_set(MUSICPLAYER_DOMAIN, RESPONSE_DONE);
            } else if (!strcasecmp(event.event.misc.type, "playing")) {
                printf("music player playing.\n");
            } else if (!strcasecmp(event.event.misc.type, "pause")) {
                printf("music player paused.\n");
            } else if (!strcasecmp(event.event.misc.type, "resume")) {
                printf("music player resume.\n");
            } else {
                printf("unhandle music event: %s.\n", event.event.misc.type);
            }
        } else if (!strcasecmp(event.event.misc.name, "airplay")) {
            // AirPlay事件处理
            if (!strcasecmp(event.event.misc.type, "connected")) {
                if (tang_module_stop())
                    share_mem_set(AIRPLAY_DOMAIN, RESPONSE_CANCEL);
                else
                    share_mem_set(AIRPLAY_DOMAIN, RESPONSE_DONE);
            } else if (!strcasecmp(event.event.misc.type, "disconnected")) {
                printf("phone disconnected, airplay play stop.\n");
            } else if (!strcasecmp(event.event.misc.type, "paused")) {
                printf("airplay play paused.\n");
            } else if (!strcasecmp(event.event.misc.type, "resumed")) {
                printf("airplay play resumed.\n");
            }
        } else if (!strcasecmp(event.event.misc.name, "localplayer")) {
            // 本地播放器事件处理
            if (!strcasecmp(event.event.misc.type, "play")) {
                if (tang_module_stop())
                    share_mem_set(LOCALPLAYER_DOMAIN, RESPONSE_CANCEL);
                else
                    share_mem_set(LOCALPLAYER_DOMAIN, RESPONSE_DONE);
            } else if (!strcasecmp(event.event.misc.type, "playing")) {
                printf("localplayer playing.\n");
            } else if (!strcasecmp(event.event.misc.type,"pause")) {
                printf("localplayer paused.\n");
            } else if (!strcasecmp(event.event.misc.type,"resume")) {
                printf("localplayer resumed.\n");
            }
        } else if (!strcasecmp(event.event.misc.name,"vr")) {
            // VR语音识别事件处理
            if (!strcasecmp(event.event.misc.type,"vr wake up"))
                tang_ui_asr_wakeup();
            else if (!strcasecmp(event.event.misc.type,"vr failed"))
                tang_ui_asr_failed();
            else if (!strcasecmp(event.event.misc.type,"vr unclear"))
                tang_ui_asr_unclear();
#if (SUPPORT_MULROOM == 1)
        } else if (!strcasecmp(event.event.misc.name, "multiroom")) {
            // 多房间音频事件处理
            if (!strcasecmp(event.event.misc.type, "group_dist")) {
                printf("group dist event\n");
                module_mulroom_audio_change(MR_AO_DISTRIBUTOR);  // 切换到分发模式
            } else if (!strcasecmp(event.event.misc.type, "dismiss_dist")) {
                printf("dismiss dist event\n");
                module_mulroom_audio_change(MR_AO_NORMAL);       // 回退到普通模式
            } else if (!strcasecmp(event.event.misc.type, "group_recv")) {
                printf("group recv event\n");
                tang_module_stop();
                stopall(-1);  // 停止所有服务
            } else if (!strcasecmp(event.event.misc.type, "dismiss_recv")) {
                printf("dismiss recv event\n");
                startall(-1);  // 启动所有服务
            }
#endif /* SUPPORT_MULROOM == 1 */
        } else {
            // 默认处理:未支持的事件
            printf("Unhandle event: %s-%s.\n", event.event.misc.name, event.event.misc.type);
        }
        break;
    case EVENT_KEY:
    default:
        // 软件设计模式:默认分支 - 忽略不支持的事件类型
        break;
    }
​
    return;
}
​
​
/* 
 * 架构设计分析:
 * 优点:采用事件驱动架构,通过JSON消息进行组件间通信,松耦合设计
 * 缺点:函数职责过重,违反了单一职责原则,包含太多不同关注点的处理逻辑
 * 设计模式:观察者模式(事件回调)、有限状态机模式(网络状态转换)
 */
​
// 时间同步线程函数 - 在后台线程中执行时间同步操作
static void *sync_time_func(void *arg)
{
#if (SUPPORT_MULROOM == 1)
    // 多房间支持模式:使用专用的NTPD模块
    module_mulroom_run_ntpd();
#else
    // 单机模式:直接调用系统ntpd命令进行时间同步
    // 性能问题:使用system()调用创建新进程,性能开销较大
    // 安全性:直接执行shell命令存在安全风险
    tang_system("ntpd -nq");
#endif
​
#if (SUPPORT_ALARM == 1)
    // 支持闹钟功能:使用专门的RTC设置接口
    tang_alarm_set_rtc_time(time(NULL));
#else
    // 不支持闹钟:使用hwclock命令写入硬件时钟
    // 可维护性问题:硬编码设备路径"/dev/rtc0",缺乏灵活性
    tang_system("hwclock -w -u -f /dev/rtc0");
#endif
​
    return NULL;
}
​
/* 
 * 网络事件回调函数 - 处理所有网络相关状态变化
 * 软件设计问题:函数过长,违反单一职责原则,应该拆分为多个专门的处理函数
 * 性能考虑:JSON解析和字符串比较可能成为性能瓶颈
 */
int network_callback(const char *p)
{
    pthread_t sync_time_pthread;
    struct json_object *wifi_event = NULL;
    char test[64] = {0};  // 临时缓冲区,命名不清晰,用途不明确
    wifi_ctl_msg_t new_mode;
    event_info_t network_event;
​
    // 日志输出:良好的调试信息
    printf("[%s] network event: %s\n", __func__, p);
    
    // JSON解析:使用json-c库解析事件数据
    // 错误处理:缺乏对解析失败的检查
    wifi_event = json_tokener_parse(p);
    //printf("event.to_string()=%s\n", json_object_to_json_string(event));
​
    // 初始化事件结构体
    memset(&network_event, 0, sizeof(event_info_t));
    
    // JSON字段提取:重复代码模式,可考虑提取为辅助函数
    struct json_object *tmp = NULL;
    json_object_object_get_ex(wifi_event, "name", &tmp);
    if(tmp != NULL){
        // 字符串拷贝:使用strncpy但未确保null终止,存在安全隐患
        strncpy(network_event.name, json_object_get_string(tmp), 
                strlen(json_object_get_string(tmp)));
        //printf("name:%s\n", json_object_get_string(tmp));
    }
​
    json_object_object_get_ex(wifi_event, "type", &tmp);
    if(tmp != NULL){
        strncpy(network_event.type, json_object_get_string(tmp), 
                strlen(json_object_get_string(tmp)));
        //printf("type:%s\n", json_object_get_string(tmp));
    }
​
    json_object_object_get_ex(wifi_event, "content", &tmp);
    if(tmp != NULL){
        strncpy(network_event.content, json_object_get_string(tmp), 
                strlen(json_object_get_string(tmp)));
        //printf("content:%s\n", json_object_get_string(tmp));
    }
​
    // 初始化WiFi控制消息
    memset(&new_mode, 0, sizeof(wifi_ctl_msg_t));
    
    /* 
     * STA状态事件处理 - 工作站模式状态变化
     * 设计模式:有限状态机,处理连接状态转换
     */
    if (!strncmp(network_event.type, event_type_str[EVENT_TYPE_STA_STATUS], 
                 strlen(event_type_str[EVENT_TYPE_STA_STATUS]))) {
        //printf("[%s]: %s\n", network_event.type, network_event.content);
        null_cnt = 0;  // 重置空状态计数器
        
        // STA连接开始事件
        if(!strncmp(network_event.content, "STA_CONNECT_STARTING", 
                    strlen("STA_CONNECT_STARTING"))){
            tang_ui_net_connecting();      // 更新UI状态
            tang_play_key("wifi_linking"); // 播放连接音效
        }
​
        // STA连接失败事件
        if(!strncmp(network_event.content, "STA_CONNECT_FAILED", 
                    strlen("STA_CONNECT_FAILED"))){
            // 提取失败原因
            json_object_object_get_ex(wifi_event, "reason", &tmp);
            if(tmp != NULL){
                strncpy(test, json_object_get_string(tmp), 
                        strlen(json_object_get_string(tmp)));
                printf("STA_CONNECT_FAILED REASON:%s\n", json_object_get_string(tmp));
            }
            {
                tang_ui_net_connect_failed();  // UI更新
                tang_play_key("wifi_link_failed"); // 音效反馈
                
                // 切换到下一个网络
                new_mode.cmd = SW_STA_NEXT_NET;
                new_mode.param.switch_sta.connect_timeout = -1;
                if(request_wifi_mode(new_mode) != true)
                    printf("ERROR: [%s] Request Network Failed, Please Register First!!!!\n", app_name);
            }
        }
        
        // STA扫描完成事件
        if(!strncmp(network_event.content, "STA_SCAN_OVER", 
                    strlen("STA_SCAN_OVER"))){
            // 启动网络配置
            new_mode.cmd = SW_NETCFG;
            new_mode.param.network_config.timeout_ms = -1;
            new_mode.param.network_config.method_maps |= NET_CONFIG_METHOD_COOEE;
            new_mode.param.network_config.vendor = NET_VENDOR_BROADCOM;
            if(request_wifi_mode(new_mode) != true)
                printf("ERROR: [%s] Request Network Failed, Please Register First!!!!\n", app_name);
        }
    } 
    /* 
     * 网络配置事件处理 - 配网过程状态变化
     * 代码重复:与STA状态处理有相似模式,可抽象共用逻辑
     */
    else if (!strncmp(network_event.type, event_type_str[EVENT_TYPE_NET_CFG], 
                      strlen(event_type_str[EVENT_TYPE_NET_CFG]))) {
        //printf("[%s]: %s\n", network_event.type, network_event.content);
        null_cnt = 0;
        
        // 配网开始
        if(!strncmp(network_event.content, net_cfg_status_str[NET_CFG_STATUS_STARTING], 
                    strlen(net_cfg_status_str[NET_CFG_STATUS_STARTING]))) {
            tang_ui_net_config();          // UI更新
            tang_play_key("airkiss_config"); // 音效反馈
        }
​
        // 配网失败
        if(!strncmp(network_event.content, net_cfg_status_str[NET_CFG_STATUS_FAILED], 
                    strlen(net_cfg_status_str[NET_CFG_STATUS_FAILED]))) {
            tang_ui_net_config_failed();   // UI更新
            tang_play_key("airkiss_config_fail"); // 音效反馈
            
            // 提取失败原因
            json_object_object_get_ex(wifi_event, "reason", &tmp);
            if(tmp != NULL){
                strncpy(test, json_object_get_string(tmp), 
                        strlen(json_object_get_string(tmp)));
                printf("NETWORK CONFIGURE REASON:%s\n", json_object_get_string(tmp));
            }
            
            // 切换到AP模式进行重新配置
            //new_mode.cmd = SW_STA;
            new_mode.cmd = SW_AP;  // 切换到AP模式
            //new_mode.cmd = SW_NETCFG;
            if(request_wifi_mode(new_mode) != true)
                printf("ERROR: [%s] Request Network Failed, Please Register First!!!!\n", app_name);
        } 
        // 配网成功
        else if (!strncmp(network_event.content, net_cfg_status_str[NET_CFG_STATUS_SUCCESS], 
                          strlen(net_cfg_status_str[NET_CFG_STATUS_SUCCESS]))) {
            tang_ui_net_config_success();  // UI更新
            tang_play_key("airkiss_config_success"); // 音效反馈
            
            {
#if 1  // 条件编译,应该使用更具描述性的宏
                // 提取网络配置信息
                json_object_object_get_ex(wifi_event, "ssid", &tmp);
                if(tmp != NULL){
                    strncpy(test, json_object_get_string(tmp), 
                            strlen(json_object_get_string(tmp)));
                    printf("ssid:%s\n", json_object_get_string(tmp));
                }
                json_object_object_get_ex(wifi_event, "passwd", &tmp);
                if(tmp != NULL){
                    strncpy(test, json_object_get_string(tmp), 
                            strlen(json_object_get_string(tmp)));
                    printf("passwd:%s\n", json_object_get_string(tmp));
                }
                json_object_object_get_ex(wifi_event, "ip", &tmp);
                if(tmp != NULL){
                    strncpy(test, json_object_get_string(tmp), 
                            strlen(json_object_get_string(tmp)));
                    printf("ip:%s\n", json_object_get_string(tmp));
                }
#endif
            }
        } 
        // 配网取消
        else if(!strncmp(network_event.content, net_cfg_status_str[NET_CFG_STATUS_CANCEL], 
                         strlen(net_cfg_status_str[NET_CFG_STATUS_CANCEL]))) {
            tang_play_key("airkiss_config_quit"); // 音效反馈
        }
    } 
    /* 
     * WiFi模式变化事件处理 - 主要的工作模式切换逻辑
     * 复杂度高:包含大量状态相关的业务逻辑
     */
    else if (!strncmp(network_event.type, event_type_str[EVENT_TYPE_WIFI_MODE], 
                      strlen(event_type_str[EVENT_TYPE_WIFI_MODE]))) {
        //printf("[%s]: %s\n", network_event.type, network_event.content);
        
        // 提取上一个模式(但未使用,代码质量问题)
        json_object_object_get_ex(wifi_event, "last", &tmp);
        if(tmp != NULL){
            strncpy(test, json_object_get_string(tmp), 
                    strlen(json_object_get_string(tmp)));
            //printf("last:%s\n", json_object_get_string(tmp));
        }
        
        // 获取当前WiFi模式
        wifi_info_t infor = get_wifi_mode();
        
        // 停止相关服务
        tang_system("killall ntpd > /dev/null 2>&1");
        tang_system("killall dnsmasq > /dev/null 2>&1");
        
        // AP模式处理
        if (infor.wifi_mode == WIFI_MODE_AP) {
            null_cnt = 0;
            tang_ui_net_connect_failed();  // UI状态更新
            tang_led_turn_off(LED_RECORD); // LED控制
            tang_led_turn_slow_flash(LED_WIFI);
            tang_play_key("wifi_ap_mode"); // 音效
            
#if (SUPPORT_USB_AUDIO == 1)
            // USB音频检查
            if(tang_usb_audio_is_in() == 0)
#endif
                startall(1);  // 启动相关服务
        } 
        // STA模式处理 - 最复杂的逻辑分支
        else if (infor.wifi_mode == WIFI_MODE_STA) {
            tang_ui_net_connected();  // UI更新
            null_cnt = 0;
            tang_led_turn_off(LED_RECORD);
            tang_led_turn_on(LED_WIFI);
            tang_play_key("wifi_sta_mode");
​
            // XXX 注释说明需要时间同步
            // 1. 同步网络时间(并以CST格式更新系统时间)
            // 2. 写入硬件RTC(使用UTC格式)
​
            // 创建时间同步线程
            // 性能考虑:每次模式切换都创建线程,可能产生线程创建开销
            if (pthread_create(&sync_time_pthread, NULL, sync_time_func, NULL) == -1)
                printf("Create sync time pthread failed: %s.\n", strerror(errno));
            pthread_detach(sync_time_pthread);  // 线程分离,避免资源泄漏
            
            // 启动DNS服务
            tang_system("dnsmasq &");
​
#if (SUPPORT_MULROOM == 1)
            // 多房间功能支持
            if (mulroom_state != MUL_GROUP_RECEIVER)
                startall(1);
​
            if (mulroom_state != MUL_IDLE) {
                tang_play_tone_sync(NULL);
                /* 在低CPU负载时设置 */
                tang_mulroom_restore_mode();
            }
#else
#if (SUPPORT_USB_AUDIO == 1)
            if(tang_usb_audio_is_in() == 0)
#endif
                startall(1);  // 启动服务
#endif /* SUPPORT_MULROOM == 1 */
        } 
        // NULL模式处理 - 无连接状态
        else if (infor.wifi_mode == WIFI_MODE_NULL) {
            null_cnt++;
            if(null_cnt >= 10){  // 连续10次空状态后重新配网
                null_cnt = 0;
                new_mode.cmd = SW_NETCFG;
                new_mode.param.network_config.timeout_ms = -1;
                new_mode.param.network_config.method_maps |= NET_CONFIG_METHOD_COOEE;
                new_mode.param.network_config.vendor = NET_VENDOR_BROADCOM;
                if(request_wifi_mode(new_mode) != true)
                    printf("ERROR: [%s] Request Network Failed, Please Register First!!!!\n", app_name);
            }
        } else {
            printf("[ERROR]: Unknown event type!!!!!!\n");
        }
    } 
    /* AP状态事件处理 - 热点模式客户端连接状态 */
    else if (!strncmp(network_event.type, event_type_str[EVENT_TYPE_AP_STATUS], 
                      strlen(event_type_str[EVENT_TYPE_AP_STATUS]))) {
        //printf("[%s]: %s\n", network_event.type, network_event.content);
        if(!strncmp(network_event.content, "AP-STA-CONNECTED", 
                    strlen("AP-STA-CONNECTED"))) {
            printf("\nThe client has the connection is successful.\n");
        } else if (!strncmp(network_event.content, "AP-STA-DISCONNECTED", 
                           strlen("AP-STA-DISCONNECTED"))) {
            printf("\nThe client has been disconnected.\n");
        }
    } 
    /* IP地址变化事件 */
    else if (!strncmp(network_event.type, event_type_str[EVENT_TYPE_IP_CHANGE], 
                      strlen(event_type_str[EVENT_TYPE_IP_CHANGE]))) {
        printf("[WARNING] STA IP ADDR HAS CHANGED!!\n");
    } 
    /* 未知事件处理 */
    else {
        printf("Unknown Network Events-[%s]: %s\n", network_event.type, network_event.content);
    }
​
    // 释放JSON对象 - 良好的资源管理
    json_object_put(wifi_event);
    return 0;
}
​
​
/* 
 * 条件编译:闹钟功能支持
 * 架构设计:使用回调函数模式处理闹钟事件
 * 可读性:良好的日志输出,包含完整的闹钟信息
 */
#if (SUPPORT_ALARM == 1)
int alarm_callback(struct alarm_info *a)
{
    // 详细的闹钟信息日志
    printf("alarm callback id: %d, hour: %d, minute: %d, timestamp: %ld info: %s\n",
           a->alarm_id, a->hour, a->minute, a->timestamp, a->prv_info.info);
    return 0;
}
#endif
​
/* 
 * 初始化函数 - 系统启动时的资源初始化
 * 设计模式:模板方法模式 - 定义初始化步骤
 * 架构问题:函数职责不够单一,包含多种不同类型的初始化
 */
static int initall(void)
{
    // recover volume in S01system_init.sh
​
    // 共享内存初始化 - 进程间通信基础
    // 性能:共享内存提供高效的进程间数据共享
    if(0 != share_mem_init()){
        printf("share_mem_init failure.\n");
    }
    if(0 != share_mem_clear()){
        printf("share_mem_clear failure.\n");
    }
​
    // 存储设备状态检测
    // 架构:硬件抽象层设计,检测外部存储设备挂载状态
    if (tang_path_is_mount("/mnt/sdcard")) {
        tfcard_status = 1;
        share_mem_set(SDCARD_DOMAIN, STATUS_INSERT);  // SD卡插入状态
    } else {
        share_mem_set(SDCARD_DOMAIN, STATUS_EXTRACT); // SD卡拔出状态
    }
​
    // U盘状态检测
    if (tang_path_is_mount("/mnt/usb"))
        share_mem_set(UDISK_DOMAIN, STATUS_INSERT);   // U盘插入
    else
        share_mem_set(UDISK_DOMAIN, STATUS_EXTRACT);  // U盘拔出
​
    // TODO: 各种功能模块初始化 - 代码可读性问题:过多的TODO注释
    // shairport init(do not depend network part)
​
    // TODO: render init if needed.
​
    // TODO: localplayer init if needed.
​
    // TODO: bt init if needed.
​
    // TODO: vr init if needed.
​
    // TODO: other init if needed.
​
    return 0;
}
​
/* 
 * 内存检查函数 - 已禁用
 * 设计模式:调试工具模式
 * 性能:在生产环境中被禁用,避免性能开销
 */
#if 0
void check_mem(int line)
{
    return ;
    pid_t pid = getpid();
    time_t timep;
    struct tm *p;
    FILE *fp;
​
    char rss[8] = {};
    char cmd[256] = {};
    char path[256] = {};
​
    // get current time.
    time(&timep);
    p=gmtime(&timep);
​
    printf("capture %d's mem info to %s.\n", pid, path);
​
    // get rss - 获取进程内存使用情况
    fp = popen("/bin/ps wl | grep tang | grep -v grep | tr -s ' ' | cut -d' ' -f6", "r");
    if (!fp) {
        strcpy(rss, "99999");
    } else {
        fgets(rss, 5, fp);
        fclose(fp);
    }
​
    // capture exmap info - 内存映射信息捕获
    sprintf(path, "/tmp/%06d_%04d%02d%02d_%02d:%02d:%02d_%04d_%s.exmap",
            pid, (1900+p->tm_year), (1+p->tm_mon),p->tm_mday, p->tm_hour, p->tm_min, p->tm_sec, line, rss);
​
    sprintf(cmd, "echo %d > /proc/exmap; cat /proc/exmap > %s", pid, path);
    system(cmd);
​
    sprintf(cmd, "cat /proc/%d/maps >> %s", pid, path);
    system(cmd);
}
#endif
​
/* 
 * 编译信息输出函数
 * 可读性:提供有用的调试信息,便于问题定位
 * 架构:系统信息收集工具
 */
static void dump_compile_info(void)
{
    time_t timep;
    struct passwd *pwd;
    char hostname[16] = "Unknown";
​
    // 获取系统信息
    time(&timep);
    pwd = getpwuid(getuid());      // 获取用户信息
    gethostname(hostname, 16);     // 获取主机名
    
    // 输出编译环境信息
    printf("tang compiled at %s on %s@%s\n", asctime(gmtime(&timep)), pwd->pw_name, hostname);
}
​
/* 
 * 版本检查线程函数
 * 设计模式:后台工作者线程模式
 * 性能:周期性检查,避免频繁的版本检查
 * 架构:自动更新机制
 */
void *tang_updater_check_version(void *arg)
{
    nvinfo_t *nvinfo = NULL;
​
    // 无限循环检查版本更新
    while(1) {
        // 检查新版本
        if ((nvinfo = tang_updater_chkver()) != NULL) {
            free(nvinfo);  // 释放版本信息内存
            // 启动更新程序
            tang_system("updater -p");
            break;  // 更新后退出线程
        }
        sleep(10);  // 每10秒检查一次
    }
​
    return NULL;
}
​
/* 
 * 主函数 - 应用程序入口点
 * 设计模式:应用程序骨架模式
 * 架构:模块化启动,事件驱动架构
 */
int main(int argc, char **argv)
{
    int daemonize = 0;  // 守护进程标志
​
    // 全局变量初始化
    app_name = argv[0];  // 保存应用程序名称
    wifi_ctl_msg_t new_mode;
    pthread_t updater_chkver_pthread;  // 版本检查线程
​
    /* 命令行参数解析 - 使用getopt标准库 */
    /* 设计模式:命令行解析器模式 */
    int c;
    while (1) {
        c = getopt(argc, argv, "bBsSh");
        if (c < 0)
            break;
        switch (c) {
        case 'b':
        case 'B':
            daemonize = 1;  // 后台运行模式
            break;
        case 's':
        case 'S':
            break;  // 静默模式?注释不清晰
        case 'h':
            usage(app_name);  // 显示使用帮助
            return 0;
        default:
            usage(app_name);
            return 1;
        }
    }
​
    /* 守护进程化 - 脱离终端在后台运行 */
    /* 架构设计:标准的Linux守护进程创建流程 */
    if (daemonize) {
        if (daemon(0, 1)) {  // daemon(nochdir, noclose)
            perror("daemon");
            return -1;
        }
    }
    
    // 输出编译信息 - 便于调试和版本管理
    dump_compile_info();
​
    /* 多房间功能初始化 */
    /* 架构:功能模块的条件编译,支持不同的产品配置 */
#if (SUPPORT_MULROOM == 1)
    mulroom_state = tang_mulroom_check_saved_mode(MULROOM_INFO_PATH);
#endif /* SUPPORT_MULROOM == 1 */
​
    /* 本地播放器扫描回调注册 */
    /* 设计模式:回调函数模式,异步事件处理 */
#if (SUPPORT_MULROOM == 1)
    if (mulroom_state != MUL_GROUP_RECEIVER) {
#if (SUPPORT_LOCALPLAYER == 1)
        tang_localplayer_scan_callback(tfcard_scan_1music_callback, tfcard_scan_done_callback);
#endif
    }
#else
#if (SUPPORT_LOCALPLAYER == 1)
    tang_localplayer_scan_callback(tfcard_scan_1music_callback, tfcard_scan_done_callback);
#endif
#endif /* SUPPORT_MULROOM == 1 */
​
    // 系统初始化
    initall();
​
    /* 启动不依赖网络的模块 */
    /* 架构设计:分阶段启动,网络相关模块后续启动 */
#if (SUPPORT_MULROOM == 1)
    if (mulroom_state != MUL_GROUP_RECEIVER)
        startall(0);  // 启动所有模块
#else
    // start modules do not depend network.
#if (SUPPORT_USB_AUDIO == 1)
    if(tang_usb_audio_is_in() == 0)
#endif
        startall(0);
#endif /* SUPPORT_MULROOM == 1 */
​
    // 电池容量注册
    register_battery_capacity();
​
    /* 事件处理器注册 - 关键架构组件 */
    /* 设计模式:观察者模式,事件回调机制 */
    // 注册按键事件处理器
    keyevent_handler = tang_event_handler_get(keyevent_callback, app_name);
    // 注册杂项事件处理器  
    miscevent_handler = tang_event_handler_get(miscevent_callback, app_name);
​
    /* 网络管理器注册 - 核心网络功能 */
    /* 架构:服务注册模式 */
    if(register_to_networkmanager(network_callback) != 0) {
        printf("ERROR: [%s] register to Network Server Failed!!!!\n", app_name);
    } else if(!access("/usr/data/wpa_supplicant.conf", R_OK)) {
        // 如果存在WiFi配置文件,自动连接STA模式
        memset(&new_mode, 0, sizeof(new_mode));
        new_mode.cmd = SW_STA;
        new_mode.param.switch_sta.connect_timeout = -1;  // 无限超时
        if(request_wifi_mode(new_mode) != true)
            printf("ERROR: [%s] Request Network Failed, Please Register First!!!!\n", app_name);
    }
​
    /* 闹钟功能初始化 */
    /* 设计模式:时间事件管理器模式 */
#if (SUPPORT_ALARM == 1)
    struct alarm_info *alarm = NULL;
    //register alarm manager
    register_to_alarm_manager(alarm_callback);
​
    // 检查唤醒状态
    if ((alarm = tang_alarm_check_wakeup_status()) != NULL) {
        printf("[%s] hour %d minute %d name %s info %s\n",
                app_name, alarm->hour, alarm->minute, alarm->name, alarm->prv_info.info);
        free(alarm);  // 释放闹钟信息内存
    }
​
    // 启动闹钟
    tang_alarm_start_alarm();
#endif
​
    /* 线路输入检测和处理 */
    /* 架构:硬件事件检测和处理 */
#if (SUPPORT_MULROOM == 1)
    if (mulroom_state != MUL_GROUP_RECEIVER) {
        // process linein insert event on startup.
        if (tang_linein_is_in()) {
            printf("linein detect, switch to linein mode...\n");
            tang_linein_on();  // 切换到线路输入模式
        }
    }
#else
    // process linein insert event on startup.
    if (tang_linein_is_in()) {
        printf("linein detect, switch to linein mode...\n");
        tang_linein_on();
    }
#endif /* SUPPORT_MULROOM == 1 */
​
    /* USB音频设备检测 */
#if (SUPPORT_USB_AUDIO == 1)
    if(tang_usb_audio_is_in() == 1)
        tang_usb_audio_plug_in();  // USB音频设备插入处理
#endif
​
    /* 创建版本检查线程 */
    /* 设计模式:后台任务线程模式 */
    /* 性能:分离线程,不阻塞主线程 */
    if (pthread_create(&updater_chkver_pthread, NULL, tang_updater_check_version, NULL) == -1)
        printf("Create updater check version pthread failed: %s.\n", strerror(errno));
    pthread_detach(updater_chkver_pthread);  // 线程分离,自动回收资源
​
    /* 信号处理设置 - 重要的系统级错误处理 */
    /* 架构:信号驱动架构,处理系统事件 */
    signal(SIGINT, sig_handler);   // 中断信号 (Ctrl+C)
    signal(SIGUSR1, sig_handler);  // 用户定义信号1
    signal(SIGUSR2, sig_handler);  // 用户定义信号2  
    signal(SIGTERM, sig_handler);  // 终止信号
    signal(SIGBUS, sig_handler);   // 总线错误
    signal(SIGSEGV, sig_handler);  // 段错误
    signal(SIGABRT, sig_handler);  // 异常终止
    signal(SIGPIPE, SIG_IGN);      // 忽略管道破裂信号
​
    /* 系统调优 - 内存管理优化 */
    /* 性能:设置内存过量使用,提高系统稳定性 */
    system("echo 1 > /proc/sys/vm/overcommit_memory");
​
    /* 主事件循环 - 简化的事件循环设计 */
    /* 架构:传统的事件循环模式 */
    /* 性能问题:使用sleep循环,不是高效的事件驱动 */
    while(1) {
        sleep(20);  // 每20秒执行一次
        // 清理页面缓存,提高内存使用效率
        system("echo 3 > /proc/sys/vm/drop_caches");
    }
​
    return 0;
}
​
​
相关推荐
文军的烹饪实验室3 小时前
CPU 架构(CPU Architecture)
架构·cpu
getapi3 小时前
一个完整的 AWS 无服务器架构教程
架构·serverless·aws
顾安r3 小时前
10.25 脚本 整理2024全年 GITHUB每周热门项目
linux·c语言·python·github·bash
想不明白的过度思考者3 小时前
Rust——Tokio的多线程调度器架构:深入异步运行时的核心机制
开发语言·架构·rust·多线程
Elieal4 小时前
深入 Maven:从仓库配置到私服架构的进阶实践
java·架构·maven
喻师傅4 小时前
数据仓库——总线架构详解
数据仓库·架构
zhilin_tang4 小时前
构建一个完整的Linux物联网设备共享内存程序测试框架
linux·c语言·架构