Camera API : Camera.getNumberOfCameras()分析

高通 Camera API: Camera.getNumberOfCameras()分析

背景

最近调试的高通设备 有前摄 后摄 扫描头 三个camera设备
但是app 使用接口 Camera.getNumberOfCameras()的返回值为2. 出于好奇 看了一下接口源码实现

接口实现分析

    /**
     * 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() {
        boolean exposeAuxCamera = false;
        String packageName = ActivityThread.currentOpPackageName();
        /* Force to expose only two cameras
         * if the package name does not falls in this bucket
         */
        String packageList = SystemProperties.get("vendor.camera.aux.packagelist");
        if (packageList.length() > 0) {
            TextUtils.StringSplitter splitter = new TextUtils.SimpleStringSplitter(',');
            splitter.setString(packageList);
            for (String str : splitter) {
                if (packageName.equals(str)) {
                    exposeAuxCamera = true;
                    break;
                }
            }
        }
        int numberOfCameras = _getNumberOfCameras();
        if (exposeAuxCamera == false && (numberOfCameras > 2)) {
            numberOfCameras = 2;
        }
        return numberOfCameras;
    }

    /**
     * Returns the number of physical cameras available on this device.
     */
    /** @hide */
    public native static int _getNumberOfCameras();

作为对比 AOSP的代码如下:

    /**
     * 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 native static int getNumberOfCameras();

我们可以看到 高通的实现做了一层简单的封装
AOSP中获取物理设备的接口加入了_前缀变为隐藏起开
对app开放的是高通封装后的实现
在这个封装中 加入了一个属性 “vendor.camera.aux.packagelist”
只有在这个属性中定义的应用才能获得超过2个的摄像头
默认这个属性只有高通的骁龙相机

#Expose aux camera for below packages
vendor.camera.aux.packagelist=org.codeaurora.snapcam

其他app,当设备camera设备超过3个的时候,只能获得2个的结果

为什么?

拙以为 这个接口是针对手机的物理形态适配的 一个前摄 一个后摄。 多余三个的情况多余的情况大概率是后摄的多镜头 可以看做一个设备

如何处理?

如果想单独使用扫描头作为物理设备:
可以如下尝试操作来打开

		try {
           Method openMethod = Class.forName("android.hardware.Camera").getMethod(
                   "openLegacy", int.class, int.class);
           mCamera = (android.hardware.Camera) openMethod.invoke(
                   null, 2, CAMERA_HAL_API_VERSION_1_0);
   		mCamera.setDisplayOrientation(oritationAdjust);

       } catch (Exception e) {
           /* Retry with open if openLegacy doesn't exist/fails */
           Log.v(TAG, "openLegacy failed due to " + e.getMessage()
                   + ", using open instead");
           mCamera = android.hardware.Camera.open(2);
       }
   	

拓展

类似的接口还有
CameraManager.getCameraIdList()

        /**
         * Get a list of all camera IDs that are at least PRESENT; ignore devices that are
         * NOT_PRESENT or ENUMERATING, since they cannot be used by anyone.
         */
        public String[] getCameraIdList() {
            String[] cameraIds = null;
            synchronized(mLock) {
                // Try to make sure we have an up-to-date list of camera devices.
                connectCameraServiceLocked();

                boolean exposeAuxCamera = false;
                String packageName = ActivityThread.currentOpPackageName();
                String packageList = SystemProperties.get("vendor.camera.aux.packagelist");
                if (packageList.length() > 0) {
                    TextUtils.StringSplitter splitter = new TextUtils.SimpleStringSplitter(',');
                    splitter.setString(packageList);
                    for (String str : splitter) {
                        if (packageName.equals(str)) {
                            exposeAuxCamera = true;
                            break;
                        }
                    }
                }
                int idCount = 0;
                for (int i = 0; i < mDeviceStatus.size(); i++) {
                    if(!exposeAuxCamera && (i == 2)) break;
                    int status = mDeviceStatus.valueAt(i);
                    if (status == ICameraServiceListener.STATUS_NOT_PRESENT ||
                            status == ICameraServiceListener.STATUS_ENUMERATING) continue;
                    idCount++;
                }
                cameraIds = new String[idCount];
                idCount = 0;
                for (int i = 0; i < mDeviceStatus.size(); i++) {
                    if(!exposeAuxCamera && (i == 2)) break;
                    int status = mDeviceStatus.valueAt(i);
                    if (status == ICameraServiceListener.STATUS_NOT_PRESENT ||
                            status == ICameraServiceListener.STATUS_ENUMERATING) continue;
                    cameraIds[idCount] = mDeviceStatus.keyAt(i);
                    idCount++;
                }
            }

            // The sort logic must match the logic in
            // libcameraservice/common/CameraProviderManager.cpp::getAPI1CompatibleCameraDeviceIds
            Arrays.sort(cameraIds, new Comparator<String>() {
                    @Override
                    public int compare(String s1, String s2) {
                        int s1Int = 0, s2Int = 0;
                        try {
                            s1Int = Integer.parseInt(s1);
                        } catch (NumberFormatException e) {
                            s1Int = -1;
                        }

                        try {
                            s2Int = Integer.parseInt(s2);
                        } catch (NumberFormatException e) {
                            s2Int = -1;
                        }

                        // Uint device IDs first
                        if (s1Int >= 0 && s2Int >= 0) {
                            return s1Int - s2Int;
                        } else if (s1Int >= 0) {
                            return -1;
                        } else if (s2Int >= 0) {
                            return 1;
                        } else {
                            // Simple string compare if both id are not uint
                            return s1.compareTo(s2);
                        }
                    }});
            return cameraIds;
        }

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值