Camera2 OpenCamera流程
文章目錄
- 總結:
轉載連結: 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實現。此外在這裡我們還需要注意
- auto requestQueueRet = session->getCaptureRequestMetadataQueue(
- 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>
¬ification) = 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>
¬ification) 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 —> 開始捕獲圖片
相關文章
- Android camera2實現預覽Android
- Android使用Camera2獲取預覽資料Android
- 將 Google Camera2 遷移為 Gradle 編譯GoGradle編譯
- Android多媒體之Camera2的相關操作Android
- Android音視訊(一) Camera2 API採集資料AndroidAPI
- 使用 Camera2 API 實現 Android 手電筒應用APIAndroid
- Android Camera2獲取預覽尺寸和fps範圍Android
- Camera2錄製視訊(一):音訊的錄製及編碼音訊
- 主流流程引擎 flowable 啟動流程
- iOS上架流程iOS上架流程iOS
- http流程HTTP
- Zookeeper流程
- 支付流程
- mysqldump流程MySql
- 買房流程
- 流程圖流程圖
- 流程公司
- flowable流程引擎通過模型ID部署流程模型
- flowable流程引擎透過模型ID部署流程模型
- Python程式控制流程-三大流程Python
- 業務流程圖的繪製流程分享(一)流程圖
- 流程圖製作: BPMN流程圖線上繪製流程圖
- App Store上架流程/蘋果app釋出流程APP蘋果
- camunda如何實現流程跳轉和流程退回
- git rebase 流程Git
- 程式流程圖流程圖
- Java控制流程Java
- 前端打包流程前端
- DNS解析流程DNS
- 佈局流程
- 繪製流程
- Django基本流程Django
- 測量流程
- 流程控制
- git操作流程Git
- printk 流程分析
- printk流程分析
- SpringMVC 流程SpringMVC