Camera2 OpenCamera流程

yaoming168發表於2020-12-19


轉載連結: Android P Camera2相機簡單解析

1.CameraManager

檔案路徑:framework\base\core\java\android\hardware\camera2\CameraManager.java

1.1 openCamera函式

CameraManager中兩個openCamera(),一個Handler,一個Executor,Executor用於執行緒池來執行Camera中的耗時操作。

/*
* cameraId 是一個標識,標識當前要開啟的camera;
* callback 是一個狀態回撥,當前camera被開啟的時候,這個狀態回撥會被觸發的;
* handler 是傳入的一個執行耗時操作的handler;
*/
@RequiresPermission(android.Manifest.permission.CAMERA)
public void openCamera(@NonNull String cameraId,
		@NonNull final CameraDevice.StateCallback callback, @Nullable Handler handler)
		throws CameraAccessException {
	openCameraForUid(cameraId, callback, CameraDeviceImpl.checkAndWrapHandler(handler),
			USE_CALLING_UID);
}
// Executor用於執行緒池來執行Camera中的耗時操作
@RequiresPermission(android.Manifest.permission.CAMERA)
public void openCamera(@NonNull String cameraId,
		@NonNull @CallbackExecutor Executor executor,
		@NonNull final CameraDevice.StateCallback callback)
		throws CameraAccessException {
	if (executor == null) {
		throw new IllegalArgumentException("executor was null");
	}
	openCameraForUid(cameraId, callback, executor, USE_CALLING_UID);
}

1.1.1 實現StateCallback 介面,當相機開啟後會回撥onOpened方法,在這個方法裡面開啟預覽

private final CameraDevice.StateCallback mStateCallback = new CameraDevice.StateCallback() {
	@Override
	public void onOpened(CameraDevice cameraDevice) {
		int id = Integer.parseInt(cameraDevice.getId());
		Log.d(TAG, "onOpened " + id);
		//+add by renshangyuan.wt for cameraId find index 2019/3/22
		int cameraId = id;
		id = getIndex(id);
		//-add by renshangyuan.wt for cameraId find index 2019/3/22
		Log.d(TAG, "onOpened " + id+" cameraId="+cameraId);
		mCameraOpenCloseLock.release();
		if (mPaused) {
			return;
		}
		mCameraDevice[id] = cameraDevice;
		mCameraOpened[id] = true;
		if (isBackCamera() && getCameraMode() == DUAL_MODE && cameraId == BAYER_ID) {
			Message msg = mCameraHandler.obtainMessage(OPEN_CAMERA, MONO_ID, 0);
			mCameraHandler.sendMessage(msg);
		} else {
			mCamerasOpened = true;
			mActivity.runOnUiThread(new Runnable() {
				@Override
				public void run() {
					mUI.onCameraOpened(mCameraIdList);
				}
			});
			createSessions();
		}
	}

	@Override
	public void onDisconnected(CameraDevice cameraDevice) {
		int id = Integer.parseInt(cameraDevice.getId());
		//+add by renshangyuan.wt for cameraId find index 2019/3/22
		id = getIndex(id);
		//-add by renshangyuan.wt for cameraId find index 2019/3/22
		Log.d(TAG, "onDisconnected " + id);
		cameraDevice.close();
		mCameraDevice[id] = null;
		mCameraOpenCloseLock.release();
		mCamerasOpened = false;
		if (null != mActivity) {
			Toast.makeText(mActivity,"open camera error id =" + id,
					Toast.LENGTH_LONG).show();
			mActivity.finish();
		}
	}

	@Override
	public void onError(CameraDevice cameraDevice, int error) {
		int id = Integer.parseInt(cameraDevice.getId());
		//+add by renshangyuan.wt for cameraId find index 2019/3/22
		id = getIndex(id);
		//-add by renshangyuan.wt for cameraId find index 2019/3/22
		Log.e(TAG, "onError " + id + " " + error);
		if (mCamerasOpened) {
			mCameraDevice[id].close();
			mCameraDevice[id] = null;
		}
		mCameraOpenCloseLock.release();
		mCamerasOpened = false;
		if (null != mActivity) {
			Toast.makeText(mActivity,"open camera error id =" + id,
					Toast.LENGTH_LONG).show();
			mActivity.finish();
		}
	}

	@Override
	public void onClosed(CameraDevice cameraDevice) {
		int id = Integer.parseInt(cameraDevice.getId());
		//+add by renshangyuan.wt for cameraId find index 2019/3/22
		id = getIndex(id);
		//-add by renshangyuan.wt for cameraId find index 2019/3/22
		Log.d(TAG, "onClosed " + id);
		mCameraDevice[id] = null;
		clearBufferLostFrames();
		mCameraOpenCloseLock.release();
		mCamerasOpened = false;
	}
};

1.2 openCameraForUid()

兩種實際都是呼叫了 openCameraForUid(cameraId, callback, executor, USE_CALLING_UID)這個方法,
具體實現如下:

public void openCameraForUid(@NonNull String cameraId,
            @NonNull final CameraDevice.StateCallback callback, @NonNull Executor executor,
            int clientUid)
            throws CameraAccessException {
        if (cameraId == null) {
            throw new IllegalArgumentException("cameraId was null");
        } else if (callback == null) {
            throw new IllegalArgumentException("callback was null");
        }
        if (CameraManagerGlobal.sCameraServiceDisabled) {
            throw new IllegalArgumentException("No cameras available on device");
        }
        openCameraDeviceUserAsync(cameraId, callback, executor, clientUid);
    }

1.3 openCameraDeviceUserAsync()

這裡做了容錯性判斷,緊接著呼叫了 openCameraDeviceUserAsync(cameraId, callback, executor, clientUid),
返回值是CameraDevice,CameraDevice是抽象類,CameraDeviceImpl是其實現類,就是要獲取CameraDeviceImpl的例項。
這個函式的主要作用就是到底層獲取相機裝置的資訊,並獲取當前指定cameraId的裝置例項。
本函式的主要工作可以分為下面五點:

  • 獲取當前cameraId指定相機的裝置資訊
  • 利用獲取相機的裝置資訊建立CameraDeviceImpl例項
  • 呼叫遠端CameraService獲取當前相機的遠端服務
  • 將獲取的遠端服務設定到CameraDeviceImpl例項中
  • 返回CameraDeviceImpl例項
    此方法的實現如下:
private CameraDevice openCameraDeviceUserAsync(String cameraId,
		CameraDevice.StateCallback callback, Executor executor, final int uid)
		throws CameraAccessException {
	CameraCharacteristics characteristics = getCameraCharacteristics(cameraId);
	CameraDevice device = null;

	synchronized (mLock) {

		ICameraDeviceUser cameraUser = null;
// 建立CameraDeviceImpl例項,返回給應用端的相機物件
		android.hardware.camera2.impl.CameraDeviceImpl deviceImpl =
				new android.hardware.camera2.impl.CameraDeviceImpl(
					cameraId,
					callback,
					executor,
					characteristics,
					mContext.getApplicationInfo().targetSdkVersion);
// 將ICameraDeviceCallbacks 設定到cameraservice中
		ICameraDeviceCallbacks callbacks = deviceImpl.getCallbacks();

		try {
			if (supportsCamera2ApiLocked(cameraId)) {
				// 獲取Framework層CameraServer的服務代理
				ICameraService cameraService = CameraManagerGlobal.get().getCameraService();
				if (cameraService == null) {
					throw new ServiceSpecificException(
						ICameraService.ERROR_DISCONNECTED,
						"Camera service is currently unavailable");
				}
				// 通過cameraService跨程式獲得BpCameraDeviceUser物件,連線到相機裝置,返回得到
				// 遠端CameraDeviceClient的本地介面
				cameraUser = cameraService.connectDevice(callbacks, cameraId,
						mContext.getOpPackageName(), uid);
			} else {
				// Use legacy camera implementation for HAL1 devices
				int id;
				try {
					id = Integer.parseInt(cameraId);
				} catch (NumberFormatException e) {
					throw new IllegalArgumentException("Expected cameraId to be numeric, but it was: "
							+ cameraId);
				}

				Log.i(TAG, "Using legacy camera HAL.");
				cameraUser = CameraDeviceUserShim.connectBinderShim(callbacks, id,
						getDisplaySize());
			}
		} catch (ServiceSpecificException e) {

		} catch (RemoteException e) {

		}
		
		// 將CameraDeviceClient本地代理cameraUser設定到CameraDeviceImpl中進行管理,
		//CameraDeviceImpl中的mRemoteDevice由該cameraUsr包裝而來
		deviceImpl.setRemoteDevice(cameraUser);
		device = deviceImpl;
	}

	return device;
}

這裡主要關注上面的程式碼中的cameraService.connectDevice,這僅僅是Connect到我們的Camera裝置,並不能開啟我們的Camera,所以ICameraDeviceUser cameraUser = null和deviceImpl.setRemoteDevice(cameraUser)也是非常重要的,這裡對應了CameraDeviceImpl .java檔案。但是這裡我們還是先看cameraService.connectDevice實現,實際上是ICameraService.connectDevice,這裡需要注意的是ICameraService實際上是aidl檔案,也是就是說CameraManager通過通過 Binder 機制呼叫了 connectDevice 方法,這個connectDevice方法的實現在CameraService 中。

1.3.1 CameraDeviceImpl繼承CameraDevice

public class CameraDeviceImpl extends CameraDevice
    public CameraDeviceImpl(String cameraId, StateCallback callback, Executor executor,
                        CameraCharacteristics characteristics, int appTargetSdkVersion) {
        mCameraId = cameraId;
        mDeviceCallback = callback;
        mDeviceExecutor = executor;
    }
}

1.3.2 setRemoteDevice的實現

frameworks/base/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java

private ICameraDeviceUserWrapper mRemoteDevice;
    public void setRemoteDevice(ICameraDeviceUser remoteDevice) throws CameraAccessException {
        synchronized(mInterfaceLock) {
            mRemoteDevice = new ICameraDeviceUserWrapper(remoteDevice);
            mDeviceExecutor.execute(mCallOnOpened);
            mDeviceExecutor.execute(mCallOnUnconfigured);
        }
    }
    private final Runnable mCallOnOpened = new Runnable() {
        public void run() {
            sessionCallback = mSessionStateCallback;
            sessionCallback.onOpened(CameraDeviceImpl.this);
            //通知相機應用裝置已開啟,並且返回CameraDeviceImpl物件,相機應用已實現該函式
            mDeviceCallback.onOpened(CameraDeviceImpl.this);
        }
    };

1.3.3 ICameraDeviceUserWrapper

frameworks/base/core/java/android/hardware/camera2/impl/ICameraDeviceUserWrapper.java

public ICameraDeviceUserWrapper(ICameraDeviceUser remoteDevice) {
    mRemoteDevice = remoteDevice;
}

通過以上流程,相機應用獲得了CameraDevice物件,而CameraDevice儲存ICameraDeviceUserWrapper物件,ICameraDeviceUserWrapper儲存BpCameraDeviceUser物件,BpCameraDeviceUser具有跨程式的能力,這樣應用就可以和CameraService端的CameraDeviceClient進行通訊了。

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

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

@NonNull
public CameraCharacteristics getCameraCharacteristics(@NonNull String cameraId)
		throws CameraAccessException {
	CameraCharacteristics characteristics = null;
	if (CameraManagerGlobal.sCameraServiceDisabled) {
		throw new IllegalArgumentException("No cameras available on device");
	}
	synchronized (mLock) {
		/*
		 * Get the camera characteristics from the camera service directly if it supports it,
		 * otherwise get them from the legacy shim instead.
		 */
		ICameraService cameraService = CameraManagerGlobal.get().getCameraService();
		if (cameraService == null) {
			throw new CameraAccessException(CameraAccessException.CAMERA_DISCONNECTED,
					"Camera service is currently unavailable");
		}
		try {
			Size displaySize = getDisplaySize();

			// First check isHiddenPhysicalCamera to avoid supportsCamera2ApiLocked throwing
			// exception in case cameraId is a hidden physical camera.
			if (!isHiddenPhysicalCamera(cameraId) && !supportsCamera2ApiLocked(cameraId)) {
				// Legacy backwards compatibility path; build static info from the camera
				// parameters
				int id = Integer.parseInt(cameraId);

				String parameters = cameraService.getLegacyParameters(id);

				CameraInfo info = cameraService.getCameraInfo(id);

				characteristics = LegacyMetadataMapper.createCharacteristics(parameters, info,
						id, displaySize);
			} else {
				// Normal path: Get the camera characteristics directly from the camera service
				CameraMetadataNative info = cameraService.getCameraCharacteristics(cameraId);
				try {
					info.setCameraId(Integer.parseInt(cameraId));
				} catch (NumberFormatException e) {
					Log.e(TAG, "Failed to parse camera Id " + cameraId + " to integer");
				}
				info.setDisplaySize(displaySize);

				characteristics = new CameraCharacteristics(info);
			}
		} catch (ServiceSpecificException e) {
			throwAsPublicException(e);
		} catch (RemoteException e) {
			// Camera service died - act as if the camera was disconnected
			throw new CameraAccessException(CameraAccessException.CAMERA_DISCONNECTED,
					"Camera service is currently unavailable", e);
		}
	}
	return characteristics;
}

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

2. CameraService.cpp

檔案路徑:/frameworks/av/services/camera/libcameraservice/CameraService.cpp

2.1 cameraService.connectDevice的實現

跨程式呼叫CameraManager->CameraService,返回CameraDeviceClient,將應用端的回撥函式設定給cameraService。

Status CameraService::connectDevice(
        const sp<hardware::camera2::ICameraDeviceCallbacks>& cameraCb,
        const String16& cameraId,
        const String16& clientPackageName,
        int clientUid,
        /*out*/
        sp<hardware::camera2::ICameraDeviceUser>* device) {
    sp<CameraDeviceClient> client = nullptr;
    //呼叫了connectHelper來實現連線相機的邏輯
    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);
            // device指標會在BnCameraService中將其打包為ICamraDeviceUser物件寫到binder reply中返回
    *device = client; // client = CameraDeviceClient
    return ret;
}

2.2 CameraService::connectHelper 實現邏輯

template<class CALLBACK, class CLIENT>
Status CameraService::connectHelper(const sp<CALLBACK>& cameraCb, const String8& cameraId,
        int api1CameraId, int halVersion, const String16& clientPackageName, int clientUid,
        int clientPid, apiLevel effectiveApiLevel, bool legacyMode, bool shimUpdateOnly,
        /*out*/sp<CLIENT>& device) {
        if(!(ret = makeClient(this, cameraCb, clientPackageName,
                cameraId, api1CameraId, facing,
                clientPid, clientUid, getpid(), legacyMode,
                halVersion, deviceVersion, effectiveApiLevel,
                /*out*/&tmp)).isOk()) {
            return ret;
        }
        //轉換BasicClient型別為CLIENT=CameraDeviceClient
        client = static_cast<CLIENT*>(tmp.get());
        //初始化CameraDeviceClient物件
        err = client->initialize(mCameraProviderManager, mMonitorTags);
        device = client;
}

2.3 makeClient的實現

在connectHelper中我們通過makeClient方法完成了client的生成並初始化,具體實現如下:

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) {
        switch(deviceVersion) {
          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;
        }
    }
}

這一塊兒基本就是根據API版本和Device版本來例項化Client的,在Android P 和Camera2的框架上,這裡CameraDeviceClient方法是由CameraDeviceClient.cpp實現的。

3. CameraDeviceClient.cpp

檔案路徑:frameworks/av/services/camera/libcameraservice/api2/CameraDeviceClient.cpp

CameraDeviceClient::CameraDeviceClient(const sp<CameraService>& cameraService,
        const sp<hardware::camera2::ICameraDeviceCallbacks>& remoteCallback,
        const String16& clientPackageName,
        const String8& cameraId,
        int cameraFacing,
        int clientPid,
        uid_t clientUid,
        int servicePid) :
    Camera2ClientBase(cameraService, remoteCallback, clientPackageName,
                cameraId, /*API1 camera ID*/ -1,
                cameraFacing, clientPid, clientUid, servicePid),
    mInputStream(),
    mStreamingRequestId(REQUEST_ID_NONE),
    mRequestIdCounter(0),
    mPrivilegedClient(false) {

    char value[PROPERTY_VALUE_MAX];
    property_get("persist.vendor.camera.privapp.list", value, "");
    String16 packagelist(value);
    if (packagelist.contains(clientPackageName.string())) {
        mPrivilegedClient = true;
    }

    ATRACE_CALL();
    ALOGI("CameraDeviceClient %s: Opened", cameraId.string());
}

3.1 獲得CameraDeviceClient之後進行initialize

status_t CameraDeviceClient::initialize(sp<CameraProviderManager> manager,
        const String8& monitorTags) {
    return initializeImpl(manager, monitorTags);
}
//呼叫父類函式,CameraDeviceClient繼承Camera2ClientBase,初始化時會建立Camera3Device物件
Camera2ClientBase<TClientBase>::Camera2ClientBase(){
    mInitialClientPid = clientPid;
    mDevice = new Camera3Device(cameraId);
}
status_t CameraDeviceClient::initializeImpl(TProviderPtr providerPtr, const String8& monitorTags) {
    res = Camera2ClientBase::initialize(providerPtr, monitorTags);
    mFrameProcessor = new FrameProcessorBase(mDevice);
    mFrameProcessor->run(threadName.string());
    mFrameProcessor->registerListener(FRAME_PROCESSOR_LISTENER_MIN_ID,
                                      FRAME_PROCESSOR_LISTENER_MAX_ID,
                                      /*listener*/this,
                                      /*sendPartials*/true);
}

呼叫了Camera2ClientBase方法,實現程式碼如下:

frameworks/av/services/camera/libcameraservice/common/Camera2ClientBase.cpp

status_t Camera2ClientBase<TClientBase>::initialize(sp<CameraProviderManager> manager,
        const String8& monitorTags) {
    return initializeImpl(manager, monitorTags);
}
status_t Camera2ClientBase<TClientBase>::initializeImpl(TProviderPtr providerPtr,
        const String8& monitorTags) {
    status_t res;
    res = TClientBase::startCameraOps();
    //初始化Camera3Device
    res = mDevice->initialize(providerPtr, monitorTags);
    wp<CameraDeviceBase::NotificationListener> weakThis(this);
    res = mDevice->setNotifyCallback(weakThis);
    return OK;
}

mDevice = new Camera3Device(cameraId)才是重點,是由Camera3Device.cpp實現的。

4. Camera3Device.cpp

檔案路徑:/frameworks/av/services/camera/libcameraservice/device3/Camera3Device.cpp

Camera3Device::Camera3Device(const String8 &id):
        mId(id),
        mOperatingMode(NO_MODE),
        mIsConstrainedHighSpeedConfiguration(false),
        mStatus(STATUS_UNINITIALIZED),
        mStatusWaiters(0),
        mUsePartialResult(false),
        mNumPartialResults(1),
        mTimestampOffset(0),
        mNextResultFrameNumber(0),
        mNextReprocessResultFrameNumber(0),
        mNextShutterFrameNumber(0),
        mNextReprocessShutterFrameNumber(0),
        mListener(NULL),
        mVendorTagId(CAMERA_METADATA_INVALID_VENDOR_ID),
        mLastTemplateId(-1)
{
    ATRACE_CALL();
    camera3_callback_ops::notify = &sNotify;
    camera3_callback_ops::process_capture_result = &sProcessCaptureResult;
    ALOGV("%s: Created device for camera %s", __FUNCTION__, mId.string());
}

到此CameraService.cpp中的makeClient工作就已經完成了並構造了"CameraDeviceClient"

接下來就是connectHelper中的client->initialize這塊兒了,從上面分析我們知道這裡的client 指的物件就是Camera3Device了,所以我們繼續找到Camera3Device中的initialize方法,程式碼如下:

status_t Camera3Device::initialize(sp<CameraProviderManager> manager, const String8& monitorTags) {
    ATRACE_CALL();
    Mutex::Autolock il(mInterfaceLock);
    Mutex::Autolock l(mLock);

    ALOGV("%s: Initializing HIDL device for camera %s", __FUNCTION__, mId.string());
    if (mStatus != STATUS_UNINITIALIZED) {
        CLOGE("Already initialized!");
        return INVALID_OPERATION;
    }
    if (manager == nullptr) return INVALID_OPERATION;

    sp<ICameraDeviceSession> session;
    ATRACE_BEGIN("CameraHal::openSession");
    status_t res = manager->openSession(mId.string(), this,
            /*out*/ &session);
    ATRACE_END();
    if (res != OK) {
        SET_ERR_L("Could not open camera session: %s (%d)", strerror(-res), res);
        return res;
    }

    res = manager->getCameraCharacteristics(mId.string(), &mDeviceInfo);
    if (res != OK) {
        SET_ERR_L("Could not retrive camera characteristics: %s (%d)", strerror(-res), res);
        session->close();
        return res;
    }

    std::shared_ptr<RequestMetadataQueue> queue;
    auto requestQueueRet = session->getCaptureRequestMetadataQueue(
        [&queue](const auto& descriptor) {
            queue = std::make_shared<RequestMetadataQueue>(descriptor);
            if (!queue->isValid() || queue->availableToWrite() <= 0) {
                ALOGE("HAL returns empty request metadata fmq, not use it");
                queue = nullptr;
                // don't use the queue onwards.
            }
        });
    if (!requestQueueRet.isOk()) {
        ALOGE("Transaction error when getting request metadata fmq: %s, not use it",
                requestQueueRet.description().c_str());
        return DEAD_OBJECT;
    }

    std::unique_ptr<ResultMetadataQueue>& resQueue = mResultMetadataQueue;
    auto resultQueueRet = session->getCaptureResultMetadataQueue(
        [&resQueue](const auto& descriptor) {
            resQueue = std::make_unique<ResultMetadataQueue>(descriptor);
            if (!resQueue->isValid() || resQueue->availableToWrite() <= 0) {
                ALOGE("HAL returns empty result metadata fmq, not use it");
                resQueue = nullptr;
                // Don't use the resQueue onwards.
            }
        });
    if (!resultQueueRet.isOk()) {
        ALOGE("Transaction error when getting result metadata queue from camera session: %s",
                resultQueueRet.description().c_str());
        return DEAD_OBJECT;
    }
    IF_ALOGV() {
        session->interfaceChain([](
            ::android::hardware::hidl_vec<::android::hardware::hidl_string> interfaceChain) {
                ALOGV("Session interface chain:");
                for (auto iface : interfaceChain) {
                    ALOGV("  %s", iface.c_str());
                }
            });
    }

    mInterface = new HalInterface(session, queue); //新建硬體抽象層介面例項
    std::string providerType;
    mVendorTagId = manager->getProviderTagIdLocked(mId.string());
    mTagMonitor.initialize(mVendorTagId);
    if (!monitorTags.isEmpty()) {
        mTagMonitor.parseTagsToMonitor(String8(monitorTags));
    }

    return initializeCommonLocked();
}

res = manager->openSession 就是走向open的地方了,但是還是需要繼續到一個方法,不難發現openSession方法由CameraProviderManager.cpp實現。此外在這裡我們還需要注意

  1. auto requestQueueRet = session->getCaptureRequestMetadataQueue(
  2. auto resultQueueRet = session->getCaptureResultMetadataQueue(
    是請求佇列,2中的resultQueueRet 是結果佇列在下一篇中將使用到。

4. CameraProviderManager.cpp

檔案路徑:***/frameworks/av/services/camera/libcameraservice/common/CameraProviderManager.cpp***
具體程式碼如下:

status_t CameraProviderManager::openSession(const std::string &id,
        const sp<hardware::camera::device::V3_2::ICameraDeviceCallback>& callback,
        /*out*/
        sp<hardware::camera::device::V3_2::ICameraDeviceSession> *session) {

    std::lock_guard<std::mutex> lock(mInterfaceMutex);

    auto deviceInfo = findDeviceInfoLocked(id,
            /*minVersion*/ {3,0}, /*maxVersion*/ {4,0});
    if (deviceInfo == nullptr) return NAME_NOT_FOUND;

    auto *deviceInfo3 = static_cast<ProviderInfo::DeviceInfo3*>(deviceInfo);

    Status status;
    hardware::Return<void> ret;
    ret = deviceInfo3->mInterface->open(callback, [&status, &session]
            (Status s, const sp<device::V3_2::ICameraDeviceSession>& cameraSession) {
                status = s;
                if (status == Status::OK) {
                    *session = cameraSession;
                }
            });
    if (!ret.isOk()) {
        ALOGE("%s: Transaction error opening a session for camera device %s: %s",
                __FUNCTION__, id.c_str(), ret.description().c_str());
        return DEAD_OBJECT;
    }
    return mapToStatusT(status);
}

ret = deviceInfo3->mInterface->open 實際上通過Hidl指向了CameraDevice::open(),該方法由CameraDevice.cpp實現。

5. CameraDevice.cpp

檔案路徑:***/hardware/interfaces/camera/device/3.2/default/CameraDevice.cpp***
程式碼如下:

Return<void> CameraDevice::open(const sp<ICameraDeviceCallback>& callback, open_cb _hidl_cb)  {
    Status status = initStatus();
    sp<CameraDeviceSession> session = nullptr;

    if (callback == nullptr) {
        ALOGE("%s: cannot open camera %s. callback is null!",
                __FUNCTION__, mCameraId.c_str());
        _hidl_cb(Status::ILLEGAL_ARGUMENT, nullptr);
        return Void();
    }
    
    if (status != Status::OK) {
        // Provider will never pass initFailed device to client, so
        // this must be a disconnected camera
        ALOGE("%s: cannot open camera %s. camera is disconnected!",
                __FUNCTION__, mCameraId.c_str());
        _hidl_cb(Status::CAMERA_DISCONNECTED, nullptr);
        return Void();
    } else {
        mLock.lock();

        ALOGV("%s: Initializing device for camera %d", __FUNCTION__, mCameraIdInt);
        session = mSession.promote();
        if (session != nullptr && !session->isClosed()) {
            ALOGE("%s: cannot open an already opened camera!", __FUNCTION__);
            mLock.unlock();
            _hidl_cb(Status::CAMERA_IN_USE, nullptr);
            return Void();
        }

        /** Open HAL device */
        status_t res;
        camera3_device_t *device;

        ATRACE_BEGIN("camera3->open");
        res = mModule->open(mCameraId.c_str(),
                reinterpret_cast<hw_device_t**>(&device));
        ATRACE_END();

        if (res != OK) {
            ALOGE("%s: cannot open camera %s!", __FUNCTION__, mCameraId.c_str());
            mLock.unlock();
            _hidl_cb(getHidlStatus(res), nullptr);
            return Void();
        }

        /** Cross-check device version */
        if (device->common.version < CAMERA_DEVICE_API_VERSION_3_2) {
            ALOGE("%s: Could not open camera: "
                    "Camera device should be at least %x, reports %x instead",
                    __FUNCTION__,
                    CAMERA_DEVICE_API_VERSION_3_2,
                    device->common.version);
            device->common.close(&device->common);
            mLock.unlock();
            _hidl_cb(Status::ILLEGAL_ARGUMENT, nullptr);
            return Void();
        }

        struct camera_info info;
        res = mModule->getCameraInfo(mCameraIdInt, &info);
        if (res != OK) {
            ALOGE("%s: Could not open camera: getCameraInfo failed", __FUNCTION__);
            device->common.close(&device->common);
            mLock.unlock();
            _hidl_cb(Status::ILLEGAL_ARGUMENT, nullptr);
            return Void();
        }

        session = createSession(
                device, info.static_camera_characteristics, callback);
        if (session == nullptr) {
            ALOGE("%s: camera device session allocation failed", __FUNCTION__);
            mLock.unlock();
            _hidl_cb(Status::INTERNAL_ERROR, nullptr);
            return Void();
        }
        if (session->isInitFailed()) {
            ALOGE("%s: camera device session init failed", __FUNCTION__);
            session = nullptr;
            mLock.unlock();
            _hidl_cb(Status::INTERNAL_ERROR, nullptr);
            return Void();
        }
        mSession = session;

        IF_ALOGV() {
            session->getInterface()->interfaceChain([](
                ::android::hardware::hidl_vec<::android::hardware::hidl_string> interfaceChain) {
                    ALOGV("Session interface chain:");
                    for (auto iface : interfaceChain) {
                        ALOGV("  %s", iface.c_str());
                    }
                });
        }
        mLock.unlock();
    }
    _hidl_cb(status, session->getInterface());
    return Void();
}

res = mModule->open(mCameraId.c_str(), reinterpret_cast<hw_device_t**>(&device))為開啟Camera的地方,但是這裡還需要繼續跟下去,指向了CameraModule.cpp中實現的open方法。

6. CameraModule.cpp

檔案路徑:***/hardware/interfaces/camera/common/1.0/default/CameraModule.cpp***
程式碼如下:

int CameraModule::open(const char* id, struct hw_device_t** device) {
    int res;
    ATRACE_BEGIN("camera_module->open");
    res = filterOpenErrorCode(mModule->common.methods->open(&mModule->common, id, device));
    ATRACE_END();
    return res;
}

不難發現,mModule->common.methods->open緊接著就是Hal層了,在這裡我們需要先把Hal層啟動流程弄清楚。在系統啟動後,CameraService服務跑起來就是就會啟動Hal層。

7. CameraService

檔案路徑:***/frameworks/av/services/camera/libcameraservice/CameraService.cpp***
程式碼如下:

void CameraService::onFirstRef()
{
    ALOGI("CameraService process starting");

    BnCameraService::onFirstRef();

    // Update battery life tracking if service is restarting
    BatteryNotifier& notifier(BatteryNotifier::getInstance());
    notifier.noteResetCamera();
    notifier.noteResetFlashlight();

    status_t res = INVALID_OPERATION;

    res = enumerateProviders();
    if (res == OK) {
        mInitialized = true;
    }

    CameraService::pingCameraServiceProxy();

    mUidPolicy = new UidPolicy(this);
    mUidPolicy->registerSelf();
}

res = enumerateProviders()說明CameraService在初始化時,要先列舉Provider,實現程式碼如下:

status_t CameraService::enumerateProviders() {
    status_t res;

    std::vector<std::string> deviceIds;
    {
        Mutex::Autolock l(mServiceLock);

        if (nullptr == mCameraProviderManager.get()) {
            mCameraProviderManager = new CameraProviderManager();
            res = mCameraProviderManager->initialize(this);
            if (res != OK) {
                ALOGE("%s: Unable to initialize camera provider manager: %s (%d)",
                        __FUNCTION__, strerror(-res), res);
                return res;
            }
        }


        // Setup vendor tags before we call get_camera_info the first time
        // because HAL might need to setup static vendor keys in get_camera_info
        // TODO: maybe put this into CameraProviderManager::initialize()?
        mCameraProviderManager->setUpVendorTags();

        if (nullptr == mFlashlight.get()) {
            mFlashlight = new CameraFlashlight(mCameraProviderManager, this);
        }

        res = mFlashlight->findFlashUnits();
        if (res != OK) {
            ALOGE("Failed to enumerate flash units: %s (%d)", strerror(-res), res);
        }

        deviceIds = mCameraProviderManager->getCameraDeviceIds();
    }


    for (auto& cameraId : deviceIds) {
        String8 id8 = String8(cameraId.c_str());
        onDeviceStatusChanged(id8, CameraDeviceStatus::PRESENT);
    }

    return OK;
}

這裡又先初始化CameraProviderManager,並獲取第三方廠家TAG,獲取閃光燈,獲取相機裝置數,其中CameraProviderManager的初始化實現如下。

8. CameraProviderManager.cpp

檔案路徑:***/frameworks/av/services/camera/libcameraservice/common/CameraProviderManager.cpp***
具體程式碼如下:

status_t CameraProviderManager::initialize(wp<CameraProviderManager::StatusListener> listener,
        ServiceInteractionProxy* proxy) {
    std::lock_guard<std::mutex> lock(mInterfaceMutex);
    if (proxy == nullptr) {
        ALOGE("%s: No valid service interaction proxy provided", __FUNCTION__);
        return BAD_VALUE;
    }
    mListener = listener;
    mServiceProxy = proxy;

    // Registering will trigger notifications for all already-known providers
    bool success = mServiceProxy->registerForNotifications(
        /* instance name, empty means no filter */ "",
        this);
    if (!success) {
        ALOGE("%s: Unable to register with hardware service manager for notifications "
                "about camera providers", __FUNCTION__);
        return INVALID_OPERATION;
    }

    // See if there's a passthrough HAL, but let's not complain if there's not
    addProviderLocked(kLegacyProviderName, /*expected*/ false);
    addProviderLocked(kExternalProviderName, /*expected*/ false);

    return OK;
}

8.1 CameraProviderManager初始化中做的事情很明瞭,這裡我們需要關注的是addProviderLocked這裡進行查詢並儲存Provider,實現如下:

status_t CameraProviderManager::addProviderLocked(const std::string& newProvider, bool expected) {
    for (const auto& providerInfo : mProviders) {
        if (providerInfo->mProviderName == newProvider) {
            ALOGW("%s: Camera provider HAL with name '%s' already registered", __FUNCTION__,
                    newProvider.c_str());
            return ALREADY_EXISTS;
        }
    }

    sp<provider::V2_4::ICameraProvider> interface;
    interface = mServiceProxy->getService(newProvider); //獲取服務

    if (interface == nullptr) {
        if (expected) {
            ALOGE("%s: Camera provider HAL '%s' is not actually available", __FUNCTION__,
                    newProvider.c_str());
            return BAD_VALUE;
        } else {
            return OK;
        }
    }

    sp<ProviderInfo> providerInfo =
            new ProviderInfo(newProvider, interface, this); //構建
    status_t res = providerInfo->initialize(); //初始化
    if (res != OK) {
        return res;
    }

    mProviders.push_back(providerInfo); //備份

    return OK;
}

8.2這裡需要關注 spprovider::V2_4::ICameraProvider interface這裡的interface,最終指向了CameraProvider.cpp,不過我們需要先關注上面的構建和初始化providerInfo->initialize(),程式碼如下:


status_t CameraProviderManager::ProviderInfo::initialize() {
    status_t res = parseProviderName(mProviderName, &mType, &mId);
    if (res != OK) {
        ALOGE("%s: Invalid provider name, ignoring", __FUNCTION__);
        return BAD_VALUE;
    }
    ALOGI("Connecting to new camera provider: %s, isRemote? %d",
            mProviderName.c_str(), mInterface->isRemote());
    // cameraDeviceStatusChange callbacks may be called (and causing new devices added)
    // before setCallback returns
    hardware::Return<Status> status = mInterface->setCallback(this);
    if (!status.isOk()) {
        ALOGE("%s: Transaction error setting up callbacks with camera provider '%s': %s",
                __FUNCTION__, mProviderName.c_str(), status.description().c_str());
        return DEAD_OBJECT;
    }
    if (status != Status::OK) {
        ALOGE("%s: Unable to register callbacks with camera provider '%s'",
                __FUNCTION__, mProviderName.c_str());
        return mapToStatusT(status);
    }

    hardware::Return<bool> linked = mInterface->linkToDeath(this, /*cookie*/ mId);
    if (!linked.isOk()) {
        ALOGE("%s: Transaction error in linking to camera provider '%s' death: %s",
                __FUNCTION__, mProviderName.c_str(), linked.description().c_str());
        return DEAD_OBJECT;
    } else if (!linked) {
        ALOGW("%s: Unable to link to provider '%s' death notifications",
                __FUNCTION__, mProviderName.c_str());
    }

    // Get initial list of camera devices, if any
    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]);
            }
        } });
    if (!ret.isOk()) {
        ALOGE("%s: Transaction error in getting camera ID list from provider '%s': %s",
                __FUNCTION__, mProviderName.c_str(), linked.description().c_str());
        return DEAD_OBJECT;
    }
    if (status != Status::OK) {
        ALOGE("%s: Unable to query for camera devices from provider '%s'",
                __FUNCTION__, mProviderName.c_str());
        return mapToStatusT(status);
    }

    sp<StatusListener> listener = mManager->getStatusListener();
    for (auto& device : devices) {
        std::string id;
        status_t res = addDevice(device,
                hardware::camera::common::V1_0::CameraDeviceStatus::PRESENT, &id);//新增device
        if (res != OK) {
            ALOGE("%s: Unable to enumerate camera device '%s': %s (%d)",
                    __FUNCTION__, device.c_str(), strerror(-res), res);
            continue;
        }
    }

    ALOGI("Camera provider %s ready with %zu camera devices",
            mProviderName.c_str(), mDevices.size());

    mInitialized = true;
    return OK;
}

8.3這裡主要關注上面的新增裝置這塊兒

status_t CameraProviderManager::ProviderInfo::addDevice(const std::string& name,
        CameraDeviceStatus initialStatus, /*out*/ std::string* parsedId) {

    ALOGI("Enumerating new camera device: %s", name.c_str());

    uint16_t major, minor;
    std::string type, id;

    status_t res = parseDeviceName(name, &major, &minor, &type, &id);
    if (res != OK) {
        return res;
    }
    if (type != mType) {
        ALOGE("%s: Device type %s does not match provider type %s", __FUNCTION__,
                type.c_str(), mType.c_str());
        return BAD_VALUE;
    }
    if (mManager->isValidDeviceLocked(id, major)) {
        ALOGE("%s: Device %s: ID %s is already in use for device major version %d", __FUNCTION__,
                name.c_str(), id.c_str(), major);
        return BAD_VALUE;
    }

    std::unique_ptr<DeviceInfo> deviceInfo;
    switch (major) {
    	//例項化
        case 1:
            deviceInfo = initializeDeviceInfo<DeviceInfo1>(name, mProviderTagid,
                    id, minor);
            break;
        case 3:
            deviceInfo = initializeDeviceInfo<DeviceInfo3>(name, mProviderTagid,
                    id, minor);
            break;
        default:
            ALOGE("%s: Device %s: Unknown HIDL device HAL major version %d:", __FUNCTION__,
                    name.c_str(), major);
            return BAD_VALUE;
    }
    if (deviceInfo == nullptr) return BAD_VALUE;
    deviceInfo->mStatus = initialStatus;
    bool isAPI1Compatible = deviceInfo->isAPI1Compatible();

    mDevices.push_back(std::move(deviceInfo));

    mUniqueCameraIds.insert(id);
    if (isAPI1Compatible) {
        mUniqueAPI1CompatibleCameraIds.push_back(id);
    }

    if (parsedId != nullptr) {
        *parsedId = id;
    }
    return OK;
}

8.5 例項化device程式碼如下:

template<class DeviceInfoT>
std::unique_ptr<CameraProviderManager::ProviderInfo::DeviceInfo>
    CameraProviderManager::ProviderInfo::initializeDeviceInfo(
        const std::string &name, const metadata_vendor_id_t tagId,
        const std::string &id, uint16_t minorVersion) const {
    Status status;

    auto cameraInterface =
            getDeviceInterface<typename DeviceInfoT::InterfaceT>(name); //獲取HAL層遠端介面
    if (cameraInterface == nullptr) return nullptr;

    CameraResourceCost resourceCost;
    cameraInterface->getResourceCost([&status, &resourceCost](
        Status s, CameraResourceCost cost) {
                status = s;
                resourceCost = cost;
            });
    if (status != Status::OK) {
        ALOGE("%s: Unable to obtain resource costs for camera device %s: %s", __FUNCTION__,
                name.c_str(), statusToString(status));
        return nullptr;
    }

    for (auto& conflictName : resourceCost.conflictingDevices) {
        uint16_t major, minor;
        std::string type, id;
        status_t res = parseDeviceName(conflictName, &major, &minor, &type, &id);
        if (res != OK) {
            ALOGE("%s: Failed to parse conflicting device %s", __FUNCTION__, conflictName.c_str());
            return nullptr;
        }
        conflictName = id;
    }

    return std::unique_ptr<DeviceInfo>(
        new DeviceInfoT(name, tagId, id, minorVersion, resourceCost,
                cameraInterface));
}

8.6 其中獲取HAL遠端介面程式碼如下:

template<>
sp<device::V3_2::ICameraDevice>
CameraProviderManager::ProviderInfo::getDeviceInterface
        <device::V3_2::ICameraDevice>(const std::string &name) const {
    Status status;
    sp<device::V3_2::ICameraDevice> cameraInterface;
    hardware::Return<void> ret;
    ret = mInterface->getCameraDeviceInterface_V3_x(name, [&status, &cameraInterface](
        Status s, sp<device::V3_2::ICameraDevice> interface) {
                status = s;
                cameraInterface = interface;
            });
    if (!ret.isOk()) {
        ALOGE("%s: Transaction error trying to obtain interface for camera device %s: %s",
                __FUNCTION__, name.c_str(), ret.description().c_str());
        return nullptr;
    }
    if (status != Status::OK) {
        ALOGE("%s: Unable to obtain interface for camera device %s: %s", __FUNCTION__,
                name.c_str(), statusToString(status));
        return nullptr;
    }
    return cameraInterface;
}

到了這裡,可以看出ICameraDevice關聯到了CameraDevice.cpp,那麼providerInfo->initialize()就分析得差不多了,下面的就到了硬體層,回頭來我們需要繼續分析CameraProvider.cpp這裡了,在這裡就關注其初始化就可以了。

9. CameraProvider.cpp

檔案路徑:***/hardware/interfaces/camera/provider/2.4/default/CameraProvider.cpp***
程式碼如下:

bool CameraProvider::initialize() {
    camera_module_t *rawModule;
    int err = hw_get_module(CAMERA_HARDWARE_MODULE_ID,
            (const hw_module_t **)&rawModule);
    if (err < 0) {
        ALOGE("Could not load camera HAL module: %d (%s)", err, strerror(-err));
        return true;
    }

    mModule = new CameraModule(rawModule);
    err = mModule->init();
    if (err != OK) {
        ALOGE("Could not initialize camera HAL module: %d (%s)", err, strerror(-err));
        mModule.clear();
        return true;
    }
    ALOGI("Loaded \"%s\" camera module", mModule->getModuleName());

    // Setup vendor tags here so HAL can setup vendor keys in camera characteristics
    VendorTagDescriptor::clearGlobalVendorTagDescriptor();
    if (!setUpVendorTags()) {
        ALOGE("%s: Vendor tag setup failed, will not be available.", __FUNCTION__);
    }

    // Setup callback now because we are going to try openLegacy next
    err = mModule->setCallbacks(this);
    if (err != OK) {
        ALOGE("Could not set camera module callback: %d (%s)", err, strerror(-err));
        mModule.clear();
        return true;
    }

    mPreferredHal3MinorVersion =
        property_get_int32("ro.vendor.camera.wrapper.hal3TrebleMinorVersion", 3);
    ALOGV("Preferred HAL 3 minor version is %d", mPreferredHal3MinorVersion);
    switch(mPreferredHal3MinorVersion) {
        case 2:
        case 3:
            // OK
            break;
        default:
            ALOGW("Unknown minor camera device HAL version %d in property "
                    "'camera.wrapper.hal3TrebleMinorVersion', defaulting to 3",
                    mPreferredHal3MinorVersion);
            mPreferredHal3MinorVersion = 3;
    }

    mNumberOfLegacyCameras = mModule->getNumberOfCameras();
    for (int i = 0; i < mNumberOfLegacyCameras; i++) {
        struct camera_info info;
        auto rc = mModule->getCameraInfo(i, &info);
        if (rc != NO_ERROR) {
            ALOGE("%s: Camera info query failed!", __func__);
            mModule.clear();
            return true;
        }

        if (checkCameraVersion(i, info) != OK) {
            ALOGE("%s: Camera version check failed!", __func__);
            mModule.clear();
            return true;
        }

        char cameraId[kMaxCameraIdLen];
        snprintf(cameraId, sizeof(cameraId), "%d", i);
        std::string cameraIdStr(cameraId);
        mCameraStatusMap[cameraIdStr] = CAMERA_DEVICE_STATUS_PRESENT;

        addDeviceNames(i);
    }

    return false; // mInitFailed
}

這裡就初始化了CameraMoudle。

CameraManagerGlobal.get().getCameraService()的實現

通過ServiceManager獲的cameraService,CameraManager通過CameraManagerGlobal訪問CameraService服務,並註冊監聽,CamreaService持有CameraServiceListener列表,並回撥結果給CameraManager。

frameworks/base/core/java/android/hardware/camera2/CameraManager.java
private static final class CameraManagerGlobal extends ICameraServiceListener.Stub {
         public ICameraService getCameraService() {
           //連線服務
            connectCameraServiceLocked();
            return mCameraService;
        }
}
private void connectCameraServiceLocked() {
        //查詢服務引用,CAMERA_SERVICE_BINDER_NAME="media.camera"
        IBinder cameraServiceBinder = ServiceManager.getService(CAMERA_SERVICE_BINDER_NAME);
        //轉換服務介面
        ICameraService cameraService = ICameraService.Stub.asInterface(cameraServiceBinder);
        //註冊回撥監聽,camerService可以通知CameraManagerGlobal狀態變化
        CameraStatus[] cameraStatuses = cameraService.addListener(this);
        //存副本
        mCameraService = cameraService;
}
frameworks/av/services/camera/libcameraservice/CameraService.h
static char const* getServiceName() { return "media.camera"; }

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

// Normal path: Get the camera characteristics directly from the camera service
CameraMetadataNative info = cameraService.getCameraCharacteristics(cameraId);
try {
	info.setCameraId(Integer.parseInt(cameraId));
} catch (NumberFormatException e) {
	Log.e(TAG, "Failed to parse camera Id " + cameraId + " to integer");
}
info.setDisplaySize(displaySize);

characteristics = new CameraCharacteristics(info);

DeviceInfo3

framework\av\services\camera\libcameraservice\common\CameraProviderManager.h

接下來分析Camera3Device的初始化,Camera3Device通過CameraService儲存的CameraProviderManager物件獲得mProviders,呼叫流程mProviders->DeviceInfo->CameraDevice3Impl->CameraDevice3SessionImpl,最終獲得CameraDevice3SessionImpl物件,其中CameraDevice3Impl和CameraDevice3SessionImpl由廠商來實現。

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
framework\av\camera\include\camera\CameraMetadata.h

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

framework\av\services\camera\libcameraservice\device3\Camera3Device.cpp
1.獲取ICameraDeviceSession例項
sp session;
status_t res = manager->openSession(mld.string,this,&session);

2.獲取RequestMetadataQueue>型別的queuemession->getCaptureRequestMetdataQueue([&queue])

3.建立HalInterface例項mInterface = new HalInterface(session,queue);

4.Common初始化initializeCommonLocked();

status_t Camera3Device::initialize(sp<CameraProviderManager> manager, const String8& monitorTags) {
    sp<ICameraDeviceSession> session;
    //通過CameraProviderManager開啟對應的會話,this為ICameraDeviceCallback型別
    status_t res = manager->openSession(mId.string(), this,
            /*out*/ &session);
    //獲得請求佇列
    std::shared_ptr<RequestMetadataQueue> queue;
    auto requestQueueRet = session->getCaptureRequestMetadataQueue(
        [&queue](const auto& descriptor) {
            queue = std::make_shared<RequestMetadataQueue>(descriptor);
            if (!queue->isValid() || queue->availableToWrite() <= 0) {
                queue = nullptr;
            }
        });
   //獲得結果佇列,最終儲存在mResultMetadataQueue物件中。
    std::unique_ptr<ResultMetadataQueue>& resQueue = mResultMetadataQueue;
    auto resultQueueRet = session->getCaptureResultMetadataQueue(
        [&resQueue](const auto& descriptor) {
            resQueue = std::make_unique<ResultMetadataQueue>(descriptor);
        });
    //封裝CameraDevice3SessionImpl物件,包括請求佇列
    mInterface = new HalInterface(session, queue);
}

我們關注其中的一個呼叫函式:
framework\av\services\camera\libcameraservice\common\CameraProviderManager.cpp

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

    // Find hidden physical camera characteristics
    for (auto& provider : mProviders) {
        for (auto& deviceInfo : provider->mDevices) {
            status_t res = deviceInfo->getPhysicalCameraCharacteristics(id, characteristics);
            if (res != NAME_NOT_FOUND) return res;
        }
    }

    return NAME_NOT_FOUND;
}

發現了呼叫了一個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新增的流程:

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:?: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();
}

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,底層的驅動層了,這是真正操作硬體的地方。

總結:

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

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

相關文章