1. 故事开场:一个「插了却看不见」的 BUG
插上 UVC 摄像头 → dmesg 里出现 /dev/video2
Camera2 打开 id="2" → crash:CAMERA_DISCONNECTED
问题:内核都识别了,为何 Camera2 就是找不到?
答案:原生 ROM 默认把 EXTERNAL 开关关掉了 —— 它根本没把 UVC 设备注册到 CameraService。
2. 两条路线对比:内置相机 vs USB 摄像头
| 维度 | 内置相机 | USB 摄像头(UVC) |
|---|---|---|
| 物理接口 | MIPI CSI-2 | USB 2.0/3.0 |
| 内核驱动 | camera sensor driver | uvcvideo |
| HAL 枚举 | 编译时固定声明 | 需动态注册 |
| 默认实例 | back/0 front/1 | 默认无 external/2 |
| 3A/HDR/防抖 | 完整 pipeline | 无 |
| 功耗 | 可控 | 未知 + 500 mA 供电 |
| 安全模型 | 用户可见 | 可「偷窥」 |
| 原生 ROM | 必开 | 默认关 |
3. 主流程:一次「预览」到底走了多少层?
左:内置相机(永远开启)
右:USB 相机(被编译开关屏蔽)
4. 架构图:到底「关」在了哪一层?
%% 架构层级图
graph TD
A[App] -->|Camera2/CameraX| B(CameraService)
B --> |HIDL/AIDL| C[CameraProvider@2.6]
C -->|legacy/0| D[CameraModule (内置)]
C -->|external/0| E[ExternalCameraProvider]
E -.->|libuvc| F[uvcvideo /dev/video2]
D -->|ioctl| G[sensor /dev/video0]
style E fill:#f9f,stroke:#333
style F fill:#f9f,stroke:#333
click E "https://source.android.com/docs/core/camera/external-camera" _blank
关键:
ExternalCameraProvider 在 AOSP 源码里默认不编进 system.img!
手机厂 device.mk 里没加,导致 Provider 不注册 → CameraService 看不到任何 EXTERNAL 实例。
5. 源码级证据:开关在哪里?
| 文件 | 作用 | 默认状态 |
|---|---|---|
device/google/xxx/device.mk | 是否把 external-service 编进镜像 | 注释掉 |
external_camera_config.xml | 声明支持分辨率/帧率 | 不存在 |
manifest.xml | 注册 <instance>external/0</instance> | 无 |
SELinux policy hal_camera_provider_external.te | 允许 Provider 运行 | 未导入 |
只要 1 个编译变量就能打开:
# 在 device.mk 里解开即可
PRODUCT_PACKAGES += android.hardware.camera.provider@2.6-external-service
PRODUCT_COPY_FILES += $(LOCAL_PATH)/external_camera_config.xml:$(TARGET_COPY_OUT_VENDOR)/etc/external_camera_config.xml
6. 打开之后的效果
adb shell dumpsys media.camera | grep EXTERNAL
Device 2 maps to "external/0"
getCameraIdList() 返回 [0, 1, 2],FEATURE_CAMERA_EXTERNAL=true,Camera2 无需任何改动即可预览。
7. 结语:技术不是做不到,只是产品不需要
- 原生 AOSP 把 EXTERNAL 做成「编译时可选」→ 手机厂为了功耗、安全、CTS 成本 一律不选。
- 于是 99% 零售机 内核可见 / framework 不可见,才会出现「插了 USB 摄像头却报 CAMERA_DISCONNECTED」的诡异现象。
- 真想玩,就 自己编译 AOSP 把那两行 makefile 解开,或者 直接绕过 Camera2 用 UVCCamera —— 这才是民间正道。
8. 一张图带走全部知识点

复制→渲染→收藏,下次再有人问你“为什么 openCamera("2") 崩了”,直接把这篇甩给他。
参考文章
以我之思,借AI之力



被折叠的 条评论
为什么被折叠?



