1. 程式人生 > >Android Camera原理之openCamera模組(一)

Android Camera原理之openCamera模組(一)

我們平時開發,知道怎麼排程api,怎麼調起camera,怎麼呼叫camera的例項來操作camera就可以了,但是這些排程的背後都做了什麼事情,我們可能不太清楚,本文打算從openCamera這個呼叫談起,展開說下camera調起之後底層是怎麼工作的?

Camera操作過程中最重要的四個步驟:

  • CameraManager-->openCamera ---> 開啟相機
  • CameraDeviceImpl-->createCaptureSession ---> 建立捕獲會話
  • CameraCaptureSession-->setRepeatingRequest
    ---> 設定預覽介面
  • CameraDeviceImpl-->capture ---> 開始捕獲圖片

1.CameraManager

CameraManager是本地的SystemService集合中一個service,在SystemServiceRegistry中註冊:

        registerService(Context.CAMERA_SERVICE, CameraManager.class,
                new CachedServiceFetcher<CameraManager>() {
            @Override
            public CameraManager createService(ContextImpl ctx) {
                return new CameraManager(ctx);
            }});

SystemServiceRegistry中有兩個HashMap集合來儲存本地的SystemService資料,有一點要注意點一些,這和Binder的service不同,他們不是binder service,只是普通的呼叫模組,整合到一個本地service中,便於管理。

    private static final HashMap<Class<?>, String> SYSTEM_SERVICE_NAMES =
            new HashMap<Class<?>, String>();
    private static final HashMap<String, ServiceFetcher<?>> SYSTEM_SERVICE_FETCHERS =
            new HashMap<String, ServiceFetcher<?>>();

2.openCamera函式

CameraManager中兩個openCamera(...),只是一個傳入Handler,一個傳入Executor,是想用執行緒池來執行Camera中耗時操作。

public void openCamera(@NonNull String cameraId,
            @NonNull final CameraDevice.StateCallback callback, @Nullable Handler handler)

public void openCamera(@NonNull String cameraId,
            @NonNull @CallbackExecutor Executor executor,
            @NonNull final CameraDevice.StateCallback callback)
  • cameraId 是一個標識,標識當前要開啟的camera
  • callback 是一個狀態回撥,當前camera被開啟的時候,這個狀態回撥會被觸發的。
  • handler 是傳入的一個執行耗時操作的handler
  • executor 操作執行緒池

瞭解一下openCamera的呼叫流程:

openCamera流程.jpg

2.1 openCameraDeviceUserAsync函式

private CameraDevice openCameraDeviceUserAsync(String cameraId,
            CameraDevice.StateCallback callback, Executor executor, final int uid)
            throws CameraAccessException
{
//......
}

返回值是CameraDevice,從《Android Camera模組解析之拍照》中講解了Camera framework模組中主要類之間的關係,CameraDevice是抽象類,CameraDeviceImpl是其實現類,就是要獲取CameraDeviceImpl的例項。
這個函式的主要作用就是到底層獲取相機裝置的資訊,並獲取當前指定cameraId的裝置例項。
本函式的主要工作可以分為下面五點:

  • 獲取當前cameraId指定相機的裝置資訊
  • 利用獲取相機的裝置資訊建立CameraDeviceImpl例項
  • 呼叫遠端CameraService獲取當前相機的遠端服務
  • 將獲取的遠端服務設定到CameraDeviceImpl例項中
  • 返回CameraDeviceImpl例項

2.2 獲取當前cameraId指定相機的裝置資訊

CameraCharacteristics characteristics = getCameraCharacteristics(cameraId);

一句簡單的呼叫,返回值是CameraCharacteristics,CameraCharacteristics提供了CameraDevice的各種屬性,可以通過getCameraCharacteristics函式來查詢。

    public CameraCharacteristics getCameraCharacteristics(@NonNull String cameraId)
            throws CameraAccessException {
        CameraCharacteristics characteristics = null;
        if (CameraManagerGlobal.sCameraServiceDisabled) {
            throw new IllegalArgumentException("No cameras available on device");
        }
        synchronized (mLock) {
            ICameraService cameraService = CameraManagerGlobal.get().getCameraService();
            if (cameraService == null) {
                throw new CameraAccessException(CameraAccessException.CAMERA_DISCONNECTED,
                        "Camera service is currently unavailable");
            }
            try {
                if (!supportsCamera2ApiLocked(cameraId)) {
                    int id = Integer.parseInt(cameraId);
                    String parameters = cameraService.getLegacyParameters(id);
                    CameraInfo info = cameraService.getCameraInfo(id);
                    characteristics = LegacyMetadataMapper.createCharacteristics(parameters, info);
                } else {
                    CameraMetadataNative info = cameraService.getCameraCharacteristics(cameraId);
                    characteristics = new CameraCharacteristics(info);
                }
            } catch (ServiceSpecificException e) {
                throwAsPublicException(e);
            } catch (RemoteException e) {
                throw new CameraAccessException(CameraAccessException.CAMERA_DISCONNECTED,
                        "Camera service is currently unavailable", e);
            }
        }
        return characteristics;
    }

一個關鍵的函式----> supportsCamera2ApiLocked(cameraId),這個函式的意思是 當前camera服務是否支援camera2 api,如果支援,返回true,如果不支援,返回false。

    private boolean supportsCameraApiLocked(String cameraId, int apiVersion) {
        /*
         * Possible return values:
         * - NO_ERROR => CameraX API is supported
         * - CAMERA_DEPRECATED_HAL => CameraX API is *not* supported (thrown as an exception)
         * - Remote exception => If the camera service died
         *
         * Anything else is an unexpected error we don't want to recover from.
         */
        try {
            ICameraService cameraService = CameraManagerGlobal.get().getCameraService();
            // If no camera service, no support
            if (cameraService == null) return false;

            return cameraService.supportsCameraApi(cameraId, apiVersion);
        } catch (RemoteException e) {
            // Camera service is now down, no support for any API level
        }
        return false;
    }

呼叫的CameraService對應的是ICameraService.aidl,對應的實現類在frameworks/av/services/camera/libcameraservice/CameraService.h
下面是CameraManager與CameraService之間的連線關係圖示:

CameraService生成.jpg


CameraManagerGlobal是CameraManager中的內部類,服務端在native層,《Android Camera模組解析之拍照》中camera2介紹的時候已經說明了當前cameraservice是放在frameworks/av/services/camera/libcameraservice/中的,編譯好了之後會生成一個libcameraservices.so的共享庫。熟悉camera程式碼,首先應該熟悉camera架構的程式碼。

 

這兒監測的是當前camera架構是基於HAL什麼版本的,看下面的switch判斷:

  • 當前device是基於HAL1.0 HAL3.0 HAL3.1,並且apiversion不是API_VERSION_2,此時支援,這裡要搞清楚了,這裡的API_VERSION_2不是api level 2,而是camera1還是camera2.
  • 當前device是基於HAL3.2 HAL3.3 HAL3.4,此時支援
  • 目前android版本,正常情況下都是支援camera2的
Status CameraService::supportsCameraApi(const String16& cameraId, int apiVersion,
        /*out*/ bool *isSupported) {
    ATRACE_CALL();

    const String8 id = String8(cameraId);

    ALOGV("%s: for camera ID = %s", __FUNCTION__, id.string());

    switch (apiVersion) {
        case API_VERSION_1:
        case API_VERSION_2:
            break;
        default:
            String8 msg = String8::format("Unknown API version %d", apiVersion);
            ALOGE("%s: %s", __FUNCTION__, msg.string());
            return STATUS_ERROR(ERROR_ILLEGAL_ARGUMENT, msg.string());
    }

    int deviceVersion = getDeviceVersion(id);
    switch(deviceVersion) {
        case CAMERA_DEVICE_API_VERSION_1_0:
        case CAMERA_DEVICE_API_VERSION_3_0:
        case CAMERA_DEVICE_API_VERSION_3_1:
            if (apiVersion == API_VERSION_2) {
                ALOGV("%s: Camera id %s uses HAL version %d <3.2, doesn't support api2 without shim",
                        __FUNCTION__, id.string(), deviceVersion);
                *isSupported = false;
            } else { // if (apiVersion == API_VERSION_1) {
                ALOGV("%s: Camera id %s uses older HAL before 3.2, but api1 is always supported",
                        __FUNCTION__, id.string());
                *isSupported = true;
            }
            break;
        case CAMERA_DEVICE_API_VERSION_3_2:
        case CAMERA_DEVICE_API_VERSION_3_3:
        case CAMERA_DEVICE_API_VERSION_3_4:
            ALOGV("%s: Camera id %s uses HAL3.2 or newer, supports api1/api2 directly",
                    __FUNCTION__, id.string());
            *isSupported = true;
            break;
        case -1: {
            String8 msg = String8::format("Unknown camera ID %s", id.string());
            ALOGE("%s: %s", __FUNCTION__, msg.string());
            return STATUS_ERROR(ERROR_ILLEGAL_ARGUMENT, msg.string());
        }
        default: {
            String8 msg = String8::format("Unknown device version %x for device %s",
                    deviceVersion, id.string());
            ALOGE("%s: %s", __FUNCTION__, msg.string());
            return STATUS_ERROR(ERROR_INVALID_OPERATION, msg.string());
        }
    }

    return Status::ok();
}

採用camera2 api來獲取相機裝置的資訊。

CameraMetadataNative info = cameraService.getCameraCharacteristics(cameraId);
characteristics = new CameraCharacteristics(info);

getCameraCharacteristics呼叫流程.jpg

 

其中DeviceInfo3是CameraProviderManager::ProviderInfo::DeviceInfo3,CameraProviderManager中的結構體,最終返回的是CameraMetadata型別,它是一個Parcelable型別,native中對應的程式碼是frameworks/av/camera/include/camera/CameraMetadata.h,java中對應的是frameworks/base/core/java/android/hardware/camera2/impl/CameraMetadataNative.java,Parcelable型別是可以跨程序傳輸的。下面是在native中定義CameraMetadata為CameraMetadataNative

namespace hardware {
namespace camera2 {
namespace impl {
using ::android::CameraMetadata;
typedef CameraMetadata CameraMetadataNative;
}
}
}

我們關注其中的一個呼叫函式:

status_t CameraProviderManager::getCameraCharacteristicsLocked(const std::string &id,
        CameraMetadata* characteristics) const {
    auto deviceInfo = findDeviceInfoLocked(id, /*minVersion*/ {3,0}, /*maxVersion*/ {4,0});
    if (deviceInfo == nullptr) return NAME_NOT_FOUND;

    return deviceInfo->getCameraCharacteristics(characteristics);
}

發現了呼叫了一個findDeviceInfoLocked(...)函式,返回型別是一個DeviceInfo結構體,CameraProviderManager.h中定義了三個DeviceInfo結構體,除了DeviceInfo之外,還有DeviceInfo1與DeviceInfo3,他們都繼承DeviceInfo,其中DeviceInfo1為HALv1服務,DeviceInfo3為HALv3-specific服務,都是提供camera device一些基本資訊。這裡主要看下findDeviceInfoLocked(...)函式:

CameraProviderManager::ProviderInfo::DeviceInfo* CameraProviderManager::findDeviceInfoLocked(
        const std::string& id,
        hardware::hidl_version minVersion, hardware::hidl_version maxVersion) const {
    for (auto& provider : mProviders) {
        for (auto& deviceInfo : provider->mDevices) {
            if (deviceInfo->mId == id &&
                    minVersion <= deviceInfo->mVersion && maxVersion >= deviceInfo->mVersion) {
                return deviceInfo.get();
            }
        }
    }
    return nullptr;
}

這兒的是mProviders是ProviderInfo型別的列表,這個ProviderInfo也是CameraProviderManager.h中定義的結構體,並且上面3種DeviceInfo都是定義在ProviderInfo裡面的。下面給出了ProviderInfo的程式碼大綱,裁剪了很多程式碼,但是我們還是能看到核心的程式碼:ProviderInfo是管理當前手機的camera device裝置的,通過addDevice儲存在mDevices中,接下來我們看下這個addDevice是如何工作的。

    struct ProviderInfo :
            virtual public hardware::camera::provider::V2_4::ICameraProviderCallback,
            virtual public hardware::hidl_death_recipient
    {
    //......
        ProviderInfo(const std::string &providerName,
                sp<hardware::camera::provider::V2_4::ICameraProvider>& interface,
                CameraProviderManager *manager);
        ~ProviderInfo();

        status_t initialize();

        const std::string& getType() const;

        status_t addDevice(const std::string& name,
                hardware::camera::common::V1_0::CameraDeviceStatus initialStatus =
                hardware::camera::common::V1_0::CameraDeviceStatus::PRESENT,
                /*out*/ std::string *parsedId = nullptr);

        // ICameraProviderCallbacks interface - these lock the parent mInterfaceMutex
        virtual hardware::Return<void> cameraDeviceStatusChange(
                const hardware::hidl_string& cameraDeviceName,
                hardware::camera::common::V1_0::CameraDeviceStatus newStatus) override;
        virtual hardware::Return<void> torchModeStatusChange(
                const hardware::hidl_string& cameraDeviceName,
                hardware::camera::common::V1_0::TorchModeStatus newStatus) override;

        // hidl_death_recipient interface - this locks the parent mInterfaceMutex
        virtual void serviceDied(uint64_t cookie, const wp<hidl::base::V1_0::IBase>& who) override;

        // Basic device information, common to all camera devices
        struct DeviceInfo {
            //......
        };
        std::vector<std::unique_ptr<DeviceInfo>> mDevices;
        std::unordered_set<std::string> mUniqueCameraIds;
        int mUniqueDeviceCount;

        // HALv1-specific camera fields, including the actual device interface
        struct DeviceInfo1 : public DeviceInfo {
            //......
        };

        // HALv3-specific camera fields, including the actual device interface
        struct DeviceInfo3 : public DeviceInfo {
            //......
        };

    private:
        void removeDevice(std::string id);
    };
  • mProviders是如何新增的?
  • addDevice是如何工作的?

mProviders新增的流程:
1.CameraService --> onFirstRef()
2.CameraService --> enumerateProviders()
3.CameraProviderManager --> initialize(this)
initialize(...)函式原型是:

status_t initialize(wp<StatusListener> listener,
            ServiceInteractionProxy *proxy = &sHardwareServiceInteractionProxy);

第2個引數預設是sHardwareServiceInteractionProxy型別,

    struct ServiceInteractionProxy {
        virtual bool registerForNotifications(
                const std::string &serviceName,
                const sp<hidl::manager::V1_0::IServiceNotification>
                &notification) = 0;
        virtual sp<hardware::camera::provider::V2_4::ICameraProvider> getService(
                const std::string &serviceName) = 0;
        virtual ~ServiceInteractionProxy() {}
    };

    // Standard use case - call into the normal generated static methods which invoke
    // the real hardware service manager
    struct HardwareServiceInteractionProxy : public ServiceInteractionProxy {
        virtual bool registerForNotifications(
                const std::string &serviceName,
                const sp<hidl::manager::V1_0::IServiceNotification>
                &notification) override {
            return hardware::camera::provider::V2_4::ICameraProvider::registerForNotifications(
                    serviceName, notification);
        }
        virtual sp<hardware::camera::provider::V2_4::ICameraProvider> getService(
                const std::string &serviceName) override {
            return hardware::camera::provider::V2_4::ICameraProvider::getService(serviceName);
        }
    };

hardware::camera::provider::V2_4::ICameraProvider::getService(serviceName)出處在./hardware/interfaces/camera/provider/2.4/default/CameraProvider.cpp,傳入的引數可能是下面兩種的一個:
const std::string kLegacyProviderName("legacy/0"); 代表 HALv1
const std::string kExternalProviderName("external/0"); 程式碼HALv3-specific

ICameraProvider* HIDL_FETCH_ICameraProvider(const char* name) {
    if (strcmp(name, kLegacyProviderName) == 0) {
        CameraProvider* provider = new CameraProvider();
        if (provider == nullptr) {
            ALOGE("%s: cannot allocate camera provider!", __FUNCTION__);
            return nullptr;
        }
        if (provider->isInitFailed()) {
            ALOGE("%s: camera provider init failed!", __FUNCTION__);
            delete provider;
            return nullptr;
        }
        return provider;
    } else if (strcmp(name, kExternalProviderName) == 0) {
        ExternalCameraProvider* provider = new ExternalCameraProvider();
        return provider;
    }
    ALOGE("%s: unknown instance name: %s", __FUNCTION__, name);
    return nullptr;
}

addDevice是如何工作的?
1.CameraProviderManager::ProviderInfo::initialize()初始化的時候是檢查當前的camera device,檢查的執行函式是:

    std::vector<std::string> devices;
    hardware::Return<void> ret = mInterface->getCameraIdList([&status, &devices](
            Status idStatus,
            const hardware::hidl_vec<hardware::hidl_string>& cameraDeviceNames) {
        status = idStatus;
        if (status == Status::OK) {
            for (size_t i = 0; i < cameraDeviceNames.size(); i++) {
                devices.push_back(cameraDeviceNames[i]);
            }
        } });

最終呼叫到./hardware/interfaces/camera/provider/2.4/default/CameraProvider.cpp中的getCameraIdList函式:CAMERA_DEVICE_STATUS_PRESENT表明當前的camera是可用的,mCameraStatusMap儲存了所有的camera 裝置列表。

Return<void> CameraProvider::getCameraIdList(getCameraIdList_cb _hidl_cb)  {
    std::vector<hidl_string> deviceNameList;
    for (auto const& deviceNamePair : mCameraDeviceNames) {
        if (mCameraStatusMap[deviceNamePair.first] == CAMERA_DEVICE_STATUS_PRESENT) {
            deviceNameList.push_back(deviceNamePair.second);
        }
    }
    hidl_vec<hidl_string> hidlDeviceNameList(deviceNameList);
    _hidl_cb(Status::OK, hidlDeviceNameList);
    return Void();
}

我們理一下整體的呼叫結構:

Camera分層體系.jpg

 

1.上面談的camera2 api就是在framework層的,在應用程式程序中。
2.CameraService,是camera2 api binder IPC通訊方式呼叫到服務端的,camera相關的操作都在在服務端進行。所在的位置就是./frameworks/av/services/camera/下面
3.服務端也只是一個橋樑,service也會呼叫到HAL,硬體抽象層,具體位置在./hardware/interfaces/camera/provider/2.4
4.camera driver,底層的驅動層了,這是真正操作硬體的地方。

2.3 利用獲取相機的裝置資訊建立CameraDeviceImpl例項

android.hardware.camera2.impl.CameraDeviceImpl deviceImpl =
                    new android.hardware.camera2.impl.CameraDeviceImpl(
                        cameraId,
                        callback,
                        executor,
                        characteristics,
                        mContext.getApplicationInfo().targetSdkVersion);

建立CameraDevice例項,傳入了剛剛獲取的characteristics引數(camera裝置資訊賦值為CameraDevice例項)。這個例項接下來還是使用,使用的時候再談一下。

2.4 呼叫遠端CameraService獲取當前相機的遠端服務

                    // Use cameraservice's cameradeviceclient implementation for HAL3.2+ devices
                    ICameraService cameraService = CameraManagerGlobal.get().getCameraService();
                    if (cameraService == null) {
                        throw new ServiceSpecificException(
                            ICameraService.ERROR_DISCONNECTED,
                            "Camera service is currently unavailable");
                    }
                    cameraUser = cameraService.connectDevice(callbacks, cameraId,
                            mContext.getOpPackageName(), uid);

這個函式的主要目的就是連線當前的cameraDevice裝置。呼叫到CameraService::connectDevice中。

connectDevice呼叫流程.jpg

Status CameraService::connectDevice(
        const sp<hardware::camera2::ICameraDeviceCallbacks>& cameraCb,
        const String16& cameraId,
        const String16& clientPackageName,
        int clientUid,
        /*out*/
        sp<hardware::camera2::ICameraDeviceUser>* device) {

    ATRACE_CALL();
    Status ret = Status::ok();
    String8 id = String8(cameraId);
    sp<CameraDeviceClient> client = nullptr;
    ret = connectHelper<hardware::camera2::ICameraDeviceCallbacks,CameraDeviceClient>(cameraCb, id,
            /*api1CameraId*/-1,
            CAMERA_HAL_API_VERSION_UNSPECIFIED, clientPackageName,
            clientUid, USE_CALLING_PID, API_2,
            /*legacyMode*/ false, /*shimUpdateOnly*/ false,
            /*out*/client);

    if(!ret.isOk()) {
        logRejected(id, getCallingPid(), String8(clientPackageName),
                ret.toString8());
        return ret;
    }

    *device = client;
    return ret;
}
  • connectDevice函式的第5個引數就是當前binder ipc的返回值,我們connectDevice之後,會得到一個cameraDeviceClient物件,這個物件會返回到應用程式程序中。我們接下來主要看看這個物件是如何生成的。
  • validateConnectLocked:檢查當前的camera device是否可用,這兒的判斷比較簡單,只是簡單判斷當前裝置是否存在。
  • handleEvictionsLocked:處理camera獨佔情況,主要的工作是當前的cameradevice如果已經被其他的裝置使用了,或者是否有比當前呼叫優先順序更高的呼叫等等,在執行完這個函式之後,才能完全判斷當前的camera device是可用的,並且開始獲取camera device的一些資訊開始工作了。
  • CameraFlashlight-->prepareDeviceOpen:此時準備連線camera device 了,需要判斷一下如果當前的camera device有可用的flashlight,那就要開始準備好了,但是flashlight被佔用的那就沒有辦法了。只是一個通知作用。
  • getDeviceVersion:判斷一下當前的camera device的version 版本,主要判斷在CameraProviderManager::getHighestSupportedVersion函式中,這個函式中將camera device支援的最高和最低版本查清楚,然後我們判斷當前的camera facing,只有兩種情況CAMERA_FACING_BACK = 0與CAMERA_FACING_FRONT = 1,這些都是先置判斷條件,只有這些檢查都通過,說明當前camera device是確實可用的。
  • makeClient:是根據當前的CAMERA_DEVICE_API_VERSION來判斷的,當前最新的HAL架構都是基於HALv3的,所以我們採用的client都是CameraDeviceClient
Status CameraService::makeClient(const sp<CameraService>& cameraService,
        const sp<IInterface>& cameraCb, const String16& packageName, const String8& cameraId,
        int api1CameraId, int facing, int clientPid, uid_t clientUid, int servicePid,
        bool legacyMode, int halVersion, int deviceVersion, apiLevel effectiveApiLevel,
        /*out*/sp<BasicClient>* client) {

    if (halVersion < 0 || halVersion == deviceVersion) {
        // Default path: HAL version is unspecified by caller, create CameraClient
        // based on device version reported by the HAL.
        switch(deviceVersion) {
          case CAMERA_DEVICE_API_VERSION_1_0:
            if (effectiveApiLevel == API_1) {  // Camera1 API route
                sp<ICameraClient> tmp = static_cast<ICameraClient*>(cameraCb.get());
                *client = new CameraClient(cameraService, tmp, packageName,
                        api1CameraId, facing, clientPid, clientUid,
                        getpid(), legacyMode);
            } else { // Camera2 API route
                ALOGW("Camera using old HAL version: %d", deviceVersion);
                return STATUS_ERROR_FMT(ERROR_DEPRECATED_HAL,
                        "Camera device \"%s\" HAL version %d does not support camera2 API",
                        cameraId.string(), deviceVersion);
            }
            break;
          case CAMERA_DEVICE_API_VERSION_3_0:
          case CAMERA_DEVICE_API_VERSION_3_1:
          case CAMERA_DEVICE_API_VERSION_3_2:
          case CAMERA_DEVICE_API_VERSION_3_3:
          case CAMERA_DEVICE_API_VERSION_3_4:
            if (effectiveApiLevel == API_1) { // Camera1 API route
                sp<ICameraClient> tmp = static_cast<ICameraClient*>(cameraCb.get());
                *client = new Camera2Client(cameraService, tmp, packageName,
                        cameraId, api1CameraId,
                        facing, clientPid, clientUid,
                        servicePid, legacyMode);
            } else { // Camera2 API route
                sp<hardware::camera2::ICameraDeviceCallbacks> tmp =
                        static_cast<hardware::camera2::ICameraDeviceCallbacks*>(cameraCb.get());
                *client = new CameraDeviceClient(cameraService, tmp, packageName, cameraId,
                        facing, clientPid, clientUid, servicePid);
            }
            break;
          default:
            // Should not be reachable
            ALOGE("Unknown camera device HAL version: %d", deviceVersion);
            return STATUS_ERROR_FMT(ERROR_INVALID_OPERATION,
                    "Camera device \"%s\" has unknown HAL version %d",
                    cameraId.string(), deviceVersion);
        }
    } else {
        // A particular HAL version is requested by caller. Create CameraClient
        // based on the requested HAL version.
        if (deviceVersion > CAMERA_DEVICE_API_VERSION_1_0 &&
            halVersion == CAMERA_DEVICE_API_VERSION_1_0) {
            // Only support higher HAL version device opened as HAL1.0 device.
            sp<ICameraClient> tmp = static_cast<ICameraClient*>(cameraCb.get());
            *client = new CameraClient(cameraService, tmp, packageName,
                    api1CameraId, facing, clientPid, clientUid,
                    servicePid, legacyMode);
        } else {
            // Other combinations (e.g. HAL3.x open as HAL2.x) are not supported yet.
            ALOGE("Invalid camera HAL version %x: HAL %x device can only be"
                    " opened as HAL %x device", halVersion, deviceVersion,
                    CAMERA_DEVICE_API_VERSION_1_0);
            return STATUS_ERROR_FMT(ERROR_ILLEGAL_ARGUMENT,
                    "Camera device \"%s\" (HAL version %d) cannot be opened as HAL version %d",
                    cameraId.string(), deviceVersion, halVersion);
        }
    }
    return Status::ok();
}

CameraClient.jpg

CameraClient與Camera2Client是之前系統版本使用的camera client物件,現在都使用CameraDeviceClient了
BnCamera --> ./frameworks/av/camera/include/camera/android/hardware/ICamera.h
ICamera --> ./frameworks/av/camera/include/camera/android/hardware/ICamera.h
BnCameraDeviceUser --> android/hardware/camera2/BnCameraDeviceUser.h 這是ICameraDeviceUser.aidl自動生成的binder 物件。所以最終得到的client物件就是ICameraDeviceUser.Stub物件。

2.5 將獲取的遠端服務設定到CameraDeviceImpl例項中

deviceImpl.setRemoteDevice(cameraUser);
device = deviceImpl;

這個cameraUser就是cameraservice端設定的ICameraDeviceUser.Stub物件,

    public void setRemoteDevice(ICameraDeviceUser remoteDevice) throws CameraAccessException {
        synchronized(mInterfaceLock) {
            // TODO: Move from decorator to direct binder-mediated exceptions
            // If setRemoteFailure already called, do nothing
            if (mInError) return;

            mRemoteDevice = new ICameraDeviceUserWrapper(remoteDevice);

            IBinder remoteDeviceBinder = remoteDevice.asBinder();
            // For legacy camera device, remoteDevice is in the same process, and
            // asBinder returns NULL.
            if (remoteDeviceBinder != null) {
                try {
                    remoteDeviceBinder.linkToDeath(this, /*flag*/ 0);
                } catch (RemoteException e) {
                    CameraDeviceImpl.this.mDeviceExecutor.execute(mCallOnDisconnected);

                    throw new CameraAccessException(CameraAccessException.CAMERA_DISCONNECTED,
                            "The camera device has encountered a serious error");
                }
            }

            mDeviceExecutor.execute(mCallOnOpened);
            mDeviceExecutor.execute(mCallOnUnconfigured);
        }
    }

這個mRemoteDevice是應用程式程序和android camera service端之間連結的橋樑,上層操作camera的方法會通過呼叫mRemoteDevice來呼叫到camera service端來實現操作底層camera驅動的目的。

小結

本文通過我們熟知的openCamera函式講起,openCamera串起應用程式和cameraService之間的聯絡,通過研究cameraservice程式碼,我們知道了底層是如何通過HAL呼叫camera驅動裝置的。下面會逐漸深入講解camera底層知識,不足之