小米845系列机器类原生调用红外摄像头进行人脸识别

小米845系列机器类原生调用红外摄像头进行人脸识别

KaguraiYoRoy
2025-03-06 / 0 评论 / 42 阅读 / 正在检测是否收录...

背景

小米845系列的小米8、小米8屏幕指纹版有一颗前置红外摄像头用于面部识别,这样即使在无光的环境下仍可以使用面部解锁。然而如果使用LineageOS的设备树不加修改编译出来的类原生无法使用红外摄像头,只能使用普通的摄像头,而PixelExperience的设备树是可以的,故探究其原因。

原因

CameraID

首先是需要指定人脸识别模块使用红外摄像头。翻阅PixelExperience的相关设备树源码可以发现:在overlay中设置了调用CameraID5的摄像头用作人脸识别。

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <integer name="override_front_cam_id">5</integer>
    <bool name="use_alternative_vendor_impl">true</bool>
</resources>

PixelExperience使用的是motorola的人脸解锁方案,而现在很多类原生使用的是AOSPA的ParanoidSense,因此上述设置的overlay并不适用。

查阅ParanoidSense源码可以看到:使用了Properties属性ro.face.sense_service.camera_id标识使用的摄像头。

    val cameraIdProp = SystemProperties.get("ro.face.sense_service.camera_id")

因此理论上只要设置ro.face.sense_service.camera_id属性为5即可使其调用红外人脸摄像头。

vendor.camera.aux.packagelist属性

如果仅仅设置上述CameraID相关属性,那么人脸模块调用时会直接报错。翻阅Frameworks部分的代码可以得知:系统默认隐藏了除主前摄和主后摄之外的其他辅助摄像头(即AUXCamera),而红外摄像头也属于AUXCamera之一。

取LineageOS的Framework代码作为例子:

    /**
     * Returns the number of physical cameras available on this device.
     * The return value of this method might change dynamically if the device
     * supports external cameras and an external camera is connected or
     * disconnected.
     *
     * If there is a
     * {@link android.hardware.camera2.CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES_LOGICAL_MULTI_CAMERA
     * logical multi-camera} in the system, to maintain app backward compatibility, this method will
     * only expose one camera per facing for all logical camera and physical camera groups.
     * Use camera2 API to see all cameras.
     *
     * @return total number of accessible camera devices, or 0 if there are no
     *   cameras or an error was encountered enumerating them.
     */
    public static int getNumberOfCameras() {
        int numberOfCameras = _getNumberOfCameras();
        if (!shouldExposeAuxCamera() && numberOfCameras > 2) {
            numberOfCameras = 2;
        }
        return numberOfCameras;
    }

不难看出,即使设备有大于2颗摄像头,若函数shouldExposeAuxCamera()返回为False则会强制指定摄像头数量为2,阻止程序访问CameraID>2的摄像头;再来看看这个判断函数的定义:

    /**
     * @hide
     */
    public static boolean shouldExposeAuxCamera() {
        /**
         * Force to expose only two cameras
         * if the package name does not falls in this bucket
         */
        String packageName = ActivityThread.currentOpPackageName();
        if (packageName == null)
            return true;
        List<String> packageList = Arrays.asList(
                SystemProperties.get("vendor.camera.aux.packagelist", packageName).split(","));
        List<String> packageExcludelist = Arrays.asList(
                SystemProperties.get("vendor.camera.aux.packageexcludelist", "").split(","));

        return packageList.contains(packageName) && !packageExcludelist.contains(packageName);
    }

可以看出,假如包名在属性vendor.camera.aux.packagelist中并且不在vendor.camera.aux.packageexcludelist中就会返回为True,否则False。

那么解决方案就很明了了:将ParanoidSense的包名加到vendor.camera.aux.packagelist属性中即可让其能够调用到红外摄像头。

解决

将ParanoidSense的包名co.aospa.sense加到vendor.camera.aux.packagelist中:

设置ro.face.sense_service.camera_id属性以指定摄像头:

在crDroid魔改的ParanoidSense中,因指定了其位于system_ext(https://gitlab.com/crdroidandroid/android_packages_apps_FaceUnlock/-/commit/545688260eb32ba19f348e84e3cae89ba29f20d1),故将这个属性加到system_ext的prop文件中。

0

评论 (0)

取消