如何在应用中利用系统提供的 AI 服务(如语音合成、图像增强)?
解读
面试官问“如何利用系统提供的 AI 服务”,并不是想听“调个第三方 SDK 就行”。他考察的是:
- 你是否知道 Android 官方把哪些 AI 能力下沉到了系统层(即设备端,非云端),以及这些能力在国内 ROM 与 GMS 环境下的可用性差异;
- 你是否能把“能力→接口→权限→生命周期→性能”串成一条完整的技术路径;
- 你是否具备“国内合规”意识:工信部 26 号文、个人信息保护“最小必要”原则、数据出境评估办法,都会直接影响你能否直接调用 Google 云端模型;
- 你是否能在面试现场给出“最小可验证 Demo”级别的关键代码片段,并解释背后的线程模型与内存拷贝点。
一句话:要体现出“我知道国内什么能调、什么不能调,不能调时我有替代方案,而且我能让老板少踩监管坑”。
知识点
-
Android 官方 AI 服务分类
- 语音合成 TTS:android.speech.tts.TextToSpeech,完全开源,不依赖 GMS,国内 ROM 全量保留。
- 语音识别:android.speech.SpeechRecognizer,依赖 RecognitionService;国内 ROM 普遍阉割 Google 识别引擎,需切换成系统内置“讯飞服务”或“小爱同学服务”。
- 图像增强:Android 12 引入 android.media.effect.EffectFactory,提供自动 HDR、夜景、人脸修复等 GPU 滤镜;国内 ROM 仅小米、OPPO 部分机型完整实现,华为走自家 HiAI 路线。
- ML Kit 标记为“GMS 扩展服务”,工信部备案号在华为、荣耀设备上无法拉起,需要降级到“离线模型 + 自研 SDK”。
-
系统服务调用流程
- 能力探测:PackageManager.queryIntentServices + 系统特征常量(如 PackageManager.FEATURE_AUDIO_OUTPUT_PROCESSED)判断设备端是否内置引擎。
- 权限声明:TTS 无需敏感权限;图像增强需 CAMERA、RECORD_AUDIO;若走到“云端识别”还需 INTERNET、ACCESS_NETWORK_STATE,并在隐私政策里声明“向境外传输语音数据”。
- 生命周期绑定:TextToSpeech.OnInitListener 回调成功后再 speak;EffectFactory 依赖 EGLContext,必须在 GL 线程创建,且与 Camera2/CameraX 的 Surface 共享同一线程。
- 性能与合规:语音流式回调在 Binder 线程,需立即 hand-off 到后台线程;图像增强每帧 1920×1080 耗时 6~8 ms,必须丢到 RenderScript 或 Vulkan compute queue,避免阻塞 UI 线程导致掉帧。
-
国内替代方案
- 语音合成:小米系统接口 com.miui.tts.IMiuiTtsService、华为 HiAI Engine.TTS;均提供 AIDL 绑定,但 SDK 包藏在系统私有路径,需用反射或 OEM 提供的 jar。
- 图像增强:华为 HiAI Engine.IMAGE_SUPER_RES、OPPO AIUnit;能力探测走 HwHiAI.isFeatureSupported();返回 false 时降级到 OpenGL ES 3.1 着色器方案。
-
面试加分细节
- 提到“我先把模型下载到 /data/user/0/packagename/files/ai_models,再用 MappedByteBuffer 加载,避免每次从 assets 拷贝”;
- 提到“我在 init 阶段加入 ThreadPoolExecutor,限制并发 2 路,防止多实例把系统 HAL 层 GPU 上下文打满”;
- 提到“针对国内 32 位 ROM,我把 .tflite 模型量化成 int8,模型体积从 12 MB 压到 3.8 MB,首次加载耗时 180 ms→45 ms”。
答案
“以语音合成为例,我的完整实现分四步: 第一步,能力探测。在 Application.onCreate 里用 PackageManager.queryIntentServices(new Intent(RecognitionService.SERVICE_INTERFACE), 0) 判断系统是否内置识别引擎;若返回空列表,说明是华为/荣耀机器,就切换到华为自带的‘com.huawei.tts’服务。 第二步,初始化与权限。TextToSpeech 本身不敏感,但我要在 8.0+ 上支持‘男声/女声’切换,需要下载 28 MB 离线音色包;我把下载逻辑放在 WorkManager 里,只在 Wi-Fi 且充电时执行,并在隐私政策里写明‘音色包仅本地使用,不上传云端’,满足工信部 26 号文要求。 第三步,生命周期与线程。TTS 引擎初始化是异步的,我在 ViewModel 里暴露 LiveData<Boolean> ttsReady,当 onInit 回调 status == SUCCESS 时才设为 true;UI 层监听后把按钮置为可点击,防止用户连续点击触发 ANR。播放语音时,我把 HashMap<String, String> params 里的 KEY_PARAM_STREAM 设为 AudioManager.STREAM_NOTIFICATION,这样即使用户在后台听歌,也不会被我的提示音打断。 第四步,性能与异常。我在 speak 之前先调用 TextToSpeech.synthesizeToFile() 把文本预合成到 cacheDir,如果耗时 > 150 ms,就放弃实时播放,直接提示‘正在为您朗读’并后台播放;同时捕获‘-2(TTS.ERROR_NOT_INSTALLED_YET)’异常,引导用户到系统设置里安装离线数据包。 上线后,我们监控到 TTS 初始化成功率 99.3%,平均首帧延迟 82 ms,OPPO 实验室功耗测试仅增加 3.2 mA,满足运营商入库标准。”
图像增强部分可同理展开:先通过 EffectFactory.isEffectSupported(EffectFactory.EFFECT_HDR) 探测,再创建 EffectContext 与 Camera2 共享 EGLContext,每帧在 GPU 完成色调映射,最后把处理后的 GLES30.Texture 交给 SurfaceFlinger,全程零 CPU 拷贝;若探测失败,则降级到自研 OpenGL ES 3.1 着色器,保持接口一致,让业务层无感知。
拓展思考
- 折叠屏场景:当应用从 6.5 英寸主屏切换到 8 英寸内屏时,图像增强的输入分辨率从 1920×1080 变成 2480×1860,GPU 负载瞬间提升 1.8 倍;我通过 DisplayManager.DisplayListener 监听折叠事件,动态把 EffectFactory 的 render quality 从 HIGH 降到 MEDIUM,帧率依旧保持 60 fps,功耗只增加 120 mW。
- 车载场景:Android Automotive OS 不允许安装 GMS,语音合成只能走系统内置引擎;但车规级要求冷启动 ≤ 1.5 s,我把 TTS 初始化提前到 SystemUI 进程,通过 CarService 把引擎 Binder 句柄透传给第三方应用,应用端直接跨进程调用,冷启动耗时从 800 ms 降到 120 ms。
- 合规演进:2024 年《生成式 AI 备案新规》要求“语音合成内容需添加可追踪水印”;我在合成 PCM 流里插入 16 bit 不可闻高频序列,并在 Metadata 区写入 128 bit UUID,后台收到用户投诉时可快速定位到具体版本与设备,满足网信办溯源要求,同时不影响听觉体验。