android sse 人脸识别,基于Android Camera2之openCamera 流程
簡介
frameworks\base\core\java\android\hardware\camera2
Camera2在Android 5.0上首次出現(xiàn),主要重新定義了一套Camera 的使用接口API,設(shè)計(jì)思想出現(xiàn)了變化,具體的可自行搜索,此處主要介紹下Camera2的常見類以及使用流程。
CameraCaptureSession 類 會(huì)話類,即用戶發(fā)起操作Camera設(shè)備的動(dòng)作類,如錄像拍照等
CaptureRequest類 請求類,用戶對Camera發(fā)起請求的抽象封裝類
CameraDevice類 Camera抽象類,類似于Camaera的一個(gè)客戶端
CameraCharacteristics類 相機(jī)參數(shù)類,比如相機(jī)支持哪些特性,如分辨率集合等
除此之外這些類中還會(huì)存在內(nèi)部類,內(nèi)部類的作用是Camera Framework 層完成配置異步返回結(jié)果的抽象類
以上幾個(gè)主要的類都在base/core下面,在對外發(fā)布API的時(shí)候App均可使用
frameworks\base\media
ImageReader類 相機(jī)采集回來的數(shù)據(jù)承載類,即相機(jī)的YUV元數(shù)據(jù)承載類
在APP層使用相機(jī)拍照 錄制視頻 等過程中上述主要類均離不開,本系列主要圍繞關(guān)鍵類,介紹其關(guān)鍵流程,本文主要介紹openCamera流程
1: openCamera 基本流程
Framework層流程也是針對上訴幾個(gè)關(guān)鍵步驟進(jìn)行分析的,我們逐個(gè)往下分析
首先看下App層在openCamera的時(shí)候Framework層發(fā)生了什么,做了什么
frameworks\base\core\java\android\hardware\camera2\CameraManager.java
@RequiresPermission(android.Manifest.permission.CAMERA)
public void openCamera(@NonNull String cameraId,
@NonNull final CameraDevice.StateCallback callback, @Nullable Handler handler)
throws CameraAccessException {
openCameraForUid(cameraId, callback, handler, USE_CALLING_UID);
}
檢查參數(shù)
public void openCameraForUid(@NonNull String cameraId,
@NonNull final CameraDevice.StateCallback callback, @Nullable Handler handler,
int clientUid)
throws CameraAccessException {
if(TdDeviceManager.disallowOp(TdDeviceManager.DISABLED_CAMERA)) {
throw new IllegalArgumentException("camera is disabled by MDM");
}
if (cameraId == null) {
throw new IllegalArgumentException("cameraId was null");
} else if (callback == null) {
throw new IllegalArgumentException("callback was null");
} else if (handler == null) {
if (Looper.myLooper() != null) {
handler = new Handler();
} else {
throw new IllegalArgumentException(
"Handler argument is null, but no looper exists in the calling thread");
}
}
openCameraDeviceUserAsync(cameraId, callback, handler, clientUid);
}
關(guān)鍵方法
/**
* Helper for opening a connection to a camera with the given ID.
*
* @param cameraId The unique identifier of the camera device to open
* @param callback The callback for the camera. Must not be null.
* @param handler The handler to invoke the callback on. Must not be null.
* @param uid The UID of the application actually opening the camera.
* Must be USE_CALLING_UID unless the caller is a service
* that is trusted to open the device on behalf of an
* application and to forward the real UID.
*
* @throws CameraAccessException if the camera is disabled by device policy,
* too many camera devices are already open, or the cameraId does not match
* any currently available camera device.
*
* @throws SecurityException if the application does not have permission to
* access the camera
* @throws IllegalArgumentException if callback or handler is null.
* @return A handle to the newly-created camera device.
*
* @see #getCameraIdList
* @see android.app.admin.DevicePolicyManager#setCameraDisabled
*/
private CameraDevice openCameraDeviceUserAsync(String cameraId,
CameraDevice.StateCallback callback, Handler handler, final int uid)
throws CameraAccessException {
CameraCharacteristics characteristics = getCameraCharacteristics(cameraId);
CameraDevice device = null;
synchronized (mLock) {
ICameraDeviceUser cameraUser = null;
android.hardware.camera2.impl.CameraDeviceImpl deviceImpl =
new android.hardware.camera2.impl.CameraDeviceImpl(
cameraId,
callback,
handler,
characteristics,
mContext.getApplicationInfo().targetSdkVersion);
ICameraDeviceCallbacks callbacks = deviceImpl.getCallbacks();
try {
if (supportsCamera2ApiLocked(cameraId)) {
// Use cameraservice's cameradeviceclient implementation for HAL3.2+ devices
//[HSM]
if(!HwSystemManager.allowOp(HwSystemManager.PERMISSION_CAMERA)) {
ServiceSpecificException e = new ServiceSpecificException(ICameraService.ERROR_DISABLED);
throwAsPublicException(e);
}
Log.i(TAG, "open camera: " + cameraId + ", package name: " + mContext.getOpPackageName());
HwSystemManager.notifyBackgroundMgr(mContext.getOpPackageName(),
Binder.getCallingPid(),
Binder.getCallingUid(),
HwSystemManager.CAMARA_SERVICE_NOTIFY,
HwSystemManager.BACKGROUND_POLICY_OPEN);
ICameraService cameraService = CameraManagerGlobal.get().getCameraService();
if (cameraService == null) {
throw new ServiceSpecificException(
ICameraService.ERROR_DISCONNECTED,
"Camera service is currently unavailable");
}
cameraUser = cameraService.connectDevice(callbacks, cameraId,
mContext.getOpPackageName(), uid);
} 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);
}
} catch (ServiceSpecificException e) {
if (e.errorCode == ICameraService.ERROR_DEPRECATED_HAL) {
throw new AssertionError("Should've gone down the shim path");
} else if (e.errorCode == ICameraService.ERROR_CAMERA_IN_USE ||
e.errorCode == ICameraService.ERROR_MAX_CAMERAS_IN_USE ||
e.errorCode == ICameraService.ERROR_DISABLED ||
e.errorCode == ICameraService.ERROR_DISCONNECTED ||
e.errorCode == ICameraService.ERROR_INVALID_OPERATION) {
// Received one of the known connection errors
// The remote camera device cannot be connected to, so
// set the local camera to the startup error state
deviceImpl.setRemoteFailure(e);
if (e.errorCode == ICameraService.ERROR_DISABLED ||
e.errorCode == ICameraService.ERROR_DISCONNECTED ||
e.errorCode == ICameraService.ERROR_CAMERA_IN_USE) {
// Per API docs, these failures call onError and throw
throwAsPublicException(e);
}
} else {
// Unexpected failure - rethrow
throwAsPublicException(e);
}
} catch (RemoteException e) {
// Camera service died - act as if it's a CAMERA_DISCONNECTED case
ServiceSpecificException sse = new ServiceSpecificException(
ICameraService.ERROR_DISCONNECTED,
"Camera service is currently unavailable");
deviceImpl.setRemoteFailure(sse);
throwAsPublicException(sse);
}
// TODO: factor out callback to be non-nested, then move setter to constructor
// For now, calling setRemoteDevice will fire initial
// onOpened/onUnconfigured callbacks.
// This function call may post onDisconnected and throw CAMERA_DISCONNECTED if
// cameraUser dies during setup.
deviceImpl.setRemoteDevice(cameraUser);
device = deviceImpl;
}
return device;
}
關(guān)鍵部分代碼如上,主要干了什么了?
1:創(chuàng)建了Camera Client 即 deviceImpl,此對象也就是返回APP進(jìn)程中的對象
android.hardware.camera2.impl.CameraDeviceImpl deviceImpl =new android.hardware.camera2.impl.CameraDeviceImpl(cameraId, callback,handler,characteristics,mContext.getApplicationInfo().targetSdkVersion);
2:將第一步創(chuàng)建的Client 和Framework 的Camera Service 聯(lián)系起來,并且注冊了一個(gè)回調(diào),在物理Camera實(shí)際有什么狀態(tài)時(shí),及時(shí)通知到App層
cameraUser = cameraService.connectDevice(callbacks, cameraId,
mContext.getOpPackageName(), uid);
3:將deviceImpl 和ICameraDeviceUser cameraUser聯(lián)系起來,即App用戶提過deviceImpl下發(fā)指令,deviceImpl 通過cameraUser 操作Framework層的 Camera,并且將Framework層的Camera的客戶端返回給高層
deviceImpl.setRemoteDevice(cameraUser);
2:openCamera關(guān)鍵步驟
關(guān)鍵步驟1:
在CameraManager openCamera的時(shí)候就創(chuàng)建了給APP 用的Client,此Client初始化的參數(shù)關(guān)注下即可,主要是傳了camera 的id(哪個(gè)攝像頭),攝像頭的回調(diào)接口callback,此接口在Camera創(chuàng)建完成就返回給APP進(jìn)程了,handler是App處理相機(jī)打卡回調(diào)的接收者,此處關(guān)鍵就是Framework 返回App的是CameraDeviceImpl 對象,但是實(shí)際接口返回的要求是一個(gè)CameraDevice對象,如下:
/**
* The method called when a camera device has finished opening.
*
*
At this point, the camera device is ready to use, and
* {@link CameraDevice#createCaptureSession} can be called to set up the first capture
* session.
*
* @param camera the camera device that has become opened
*/
public abstract void onOpened(@NonNull CameraDevice camera); // Must implement
關(guān)鍵步驟2:
此步驟是打開Camera的最關(guān)鍵的一步,首先是獲取Framework層的Camera Service,即
ICameraService cameraService
ICameraService cameraService = CameraManagerGlobal.get().getCameraService();
然后就通過 cameraService
cameraUser = cameraService.connectDevice(callbacks, cameraId,
mContext.getOpPackageName(), uid);
主要傳了 callback(Cameraservice 回調(diào)App的接口),Camera的id 進(jìn)程號(hào) 和包名(下面代碼刪除了部分,主要說明此回調(diào)作用)
public class CameraDeviceCallbacks extends ICameraDeviceCallbacks.Stub {
@Override
public IBinder asBinder() {
return this;
}
@Override
public void onDeviceError(final int errorCode, CaptureResultExtras resultExtras) {
}
@Override
public void onRepeatingRequestError(long lastFrameNumber) {
}
@Override
public void onDeviceIdle() {
}
@Override
public void onCaptureStarted(final CaptureResultExtras resultExtras, final long timestamp) {
}
@Override
public void onResultReceived(CameraMetadataNative result,
}
@Override
public void onPrepared(int streamId) {
}
@Override
public void onRequestQueueEmpty() {
}
}
Callback對象,根據(jù)此對象定義可知是通過Binder傳遞過來的
通過Binder 調(diào)用Camera Service的connectDevice,Camera Service是Camera 進(jìn)程初始化注冊到ServicesManager中的,服務(wù)的承載代碼即CameraService.cpp,因此查看下:
Status CameraService::connectDevice(
const sp<:camera2::icameradevicecallbacks>& cameraCb,
const String16& cameraId,
const String16& clientPackageName,
int clientUid,
/*out*/
sp<:camera2::icameradeviceuser>* device) {
ATRACE_CALL();
Status ret = Status::ok();
String8 id = String8(cameraId);
sp client = nullptr;
ret = connectHelper<:camera2::icameradevicecallbacks>(cameraCb, id,
CAMERA_HAL_API_VERSION_UNSPECIFIED, clientPackageName,
clientUid, USE_CALLING_PID, API_2,
/*legacyMode*/ false, /*shimUpdateOnly*/ false,
/*out*/client);
if(!ret.isOk()) {
logRejected(id, getCallingPid(), String8(clientPackageName),
ret.toString8());
return ret;
}
String8 pid = String8::format("%d", getCallingPid());
POWERPUSH(129, clientName8.string(), id.string(), pid.string());//define in LogPower.java, 129 stand for camera start now
*device = client;
//add for send msg to nfc
char needSendMsg[255];
property_get("ro.config.hw_camera_nfc_switch",needSendMsg,"");
ALOGI("NFC polling %s", needSendMsg);
if (0 == strcmp(needSendMsg, "true")) {
String8 isOpen = String8::format("false");
android::allowNfcPolling(isOpen);
}
ALOGI("%s(), exit.", __FUNCTION__);
return ret;
}
關(guān)鍵函數(shù)connectHelper
template
Status CameraService::connectHelper(const sp& cameraCb, const String8& cameraId,
int halVersion, const String16& clientPackageName, int clientUid, int clientPid,
apiLevel effectiveApiLevel, bool legacyMode, bool shimUpdateOnly,
/*out*/sp& device) {
binder::Status ret = binder::Status::ok();
String8 clientName8(clientPackageName);
int originalClientPid = 0;
ALOGI("CameraService::connect call (PID %d \"%s\", camera ID %s) for HAL version %s and "
"Camera API version %d", clientPid, clientName8.string(), cameraId.string(),
(halVersion == -1) ? "default" : std::to_string(halVersion).c_str(),
static_cast(effectiveApiLevel));
sp client = nullptr;
{
// Acquire mServiceLock and prevent other clients from connecting
std::unique_ptr lock =
AutoConditionLock::waitAndAcquire(mServiceLockWrapper, DEFAULT_CONNECT_TIMEOUT_NS);
if (lock == nullptr) {
ALOGE("CameraService::connect (PID %d) rejected (too many other clients connecting)."
, clientPid);
return STATUS_ERROR_FMT(ERROR_MAX_CAMERAS_IN_USE,
"Cannot open camera %s for \"%s\" (PID %d): Too many other clients connecting",
cameraId.string(), clientName8.string(), clientPid);
}
// Enforce client permissions and do basic sanity checks
if(!(ret = validateConnectLocked(cameraId, clientName8,
/*inout*/clientUid, /*inout*/clientPid, /*out*/originalClientPid)).isOk()) {
return ret;
}
// Check the shim parameters after acquiring lock, if they have already been updated and
// we were doing a shim update, return immediately
if (shimUpdateOnly) {
auto cameraState = getCameraState(cameraId);
if (cameraState != nullptr) {
if (!cameraState->getShimParams().isEmpty()) return ret;
}
}
status_t err;
sp clientTmp = nullptr;
std::shared_ptr<:clientdescriptor sp>>> partial;
if ((err = handleEvictionsLocked(cameraId, originalClientPid, effectiveApiLevel,
IInterface::asBinder(cameraCb), clientName8, /*out*/&clientTmp,
/*out*/&partial)) != NO_ERROR) {
switch (err) {
case -ENODEV:
return STATUS_ERROR_FMT(ERROR_DISCONNECTED,
"No camera device with ID \"%s\" currently available",
cameraId.string());
case -EBUSY:
return STATUS_ERROR_FMT(ERROR_CAMERA_IN_USE,
"Higher-priority client using camera, ID \"%s\" currently unavailable",
cameraId.string());
default:
return STATUS_ERROR_FMT(ERROR_INVALID_OPERATION,
"Unexpected error %s (%d) opening camera \"%s\"",
strerror(-err), err, cameraId.string());
}
}
if (clientTmp.get() != nullptr) {
// Handle special case for API1 MediaRecorder where the existing client is returned
device = static_cast(clientTmp.get());
return ret;
}
// give flashlight a chance to close devices if necessary.
mFlashlight->prepareDeviceOpen(cameraId);
int facing = -1;
int deviceVersion = getDeviceVersion(cameraId, /*out*/&facing);
if (facing == -1) {
ALOGE("%s: Unable to get camera device \"%s\" facing", __FUNCTION__, cameraId.string());
return STATUS_ERROR_FMT(ERROR_INVALID_OPERATION,
"Unable to get camera device \"%s\" facing", cameraId.string());
}
sp tmp = nullptr;
if(!(ret = makeClient(this, cameraCb, clientPackageName, cameraId, facing, clientPid,
clientUid, getpid(), legacyMode, halVersion, deviceVersion, effectiveApiLevel,
/*out*/&tmp)).isOk()) {
return ret;
}
client = static_cast(tmp.get());
ALOGI("%s(), make client for '%s'.", __FUNCTION__, String8{clientPackageName}.string());
LOG_ALWAYS_FATAL_IF(client.get() == nullptr, "%s: CameraService in invalid state",
__FUNCTION__);
err = client->initialize(mCameraProviderManager);
if (err != OK) {
ALOGE("%s: Could not initialize client from HAL.", __FUNCTION__);
// Errors could be from the HAL module open call or from AppOpsManager
switch(err) {
case BAD_VALUE:
return STATUS_ERROR_FMT(ERROR_ILLEGAL_ARGUMENT,
"Illegal argument to HAL module for camera \"%s\"", cameraId.string());
case -EBUSY:
return STATUS_ERROR_FMT(ERROR_CAMERA_IN_USE,
"Camera \"%s\" is already open", cameraId.string());
case -EUSERS:
return STATUS_ERROR_FMT(ERROR_MAX_CAMERAS_IN_USE,
"Too many cameras already open, cannot open camera \"%s\"",
cameraId.string());
case PERMISSION_DENIED:
return STATUS_ERROR_FMT(ERROR_PERMISSION_DENIED,
"No permission to open camera \"%s\"", cameraId.string());
case -EACCES:
return STATUS_ERROR_FMT(ERROR_DISABLED,
"Camera \"%s\" disabled by policy", cameraId.string());
case -ENODEV:
default:
return STATUS_ERROR_FMT(ERROR_INVALID_OPERATION,
"Failed to initialize camera \"%s\": %s (%d)", cameraId.string(),
strerror(-err), err);
}
}
// Update shim paremeters for legacy clients
if (effectiveApiLevel == API_1) {
// Assume we have always received a Client subclass for API1
sp shimClient = reinterpret_cast(client.get());
String8 rawParams = shimClient->getParameters();
CameraParameters params(rawParams);
auto cameraState = getCameraState(cameraId);
if (cameraState != nullptr) {
cameraState->setShimParams(params);
} else {
ALOGE("%s: Cannot update shim parameters for camera %s, no such device exists.",
__FUNCTION__, cameraId.string());
}
}
if (shimUpdateOnly) {
// If only updating legacy shim parameters, immediately disconnect client
mServiceLock.unlock();
client->disconnect();
mServiceLock.lock();
} else {
// Otherwise, add client to active clients list
finishConnectLocked(client, partial);
}
} // lock is destroyed, allow further connect calls
device = client;
return ret;
}
關(guān)鍵函數(shù)makeClient
Status CameraService::makeClient(const sp& cameraService,
const sp& cameraCb, const String16& packageName, const String8& cameraId,
int facing, int clientPid, uid_t clientUid, int servicePid, bool legacyMode,
int halVersion, int deviceVersion, apiLevel effectiveApiLevel,
/*out*/sp* client) {
if (halVersion < 0 || halVersion == deviceVersion) {
// Default path: HAL version is unspecified by caller, create CameraClient
// based on device version reported by the HAL.
switch(deviceVersion) {
case CAMERA_DEVICE_API_VERSION_1_0:
if (effectiveApiLevel == API_1) { // Camera1 API route
sp tmp = static_cast(cameraCb.get());
*client = new CameraClient(cameraService, tmp, packageName, cameraIdToInt(cameraId),
facing, clientPid, clientUid, getpid(), legacyMode);
} else { // Camera2 API route
ALOGW("Camera using old HAL version: %d", deviceVersion);
return STATUS_ERROR_FMT(ERROR_DEPRECATED_HAL,
"Camera device \"%s\" HAL version %d does not support camera2 API",
cameraId.string(), deviceVersion);
}
break;
case CAMERA_DEVICE_API_VERSION_3_0:
case CAMERA_DEVICE_API_VERSION_3_1:
case CAMERA_DEVICE_API_VERSION_3_2:
case CAMERA_DEVICE_API_VERSION_3_3:
case CAMERA_DEVICE_API_VERSION_3_4:
if (effectiveApiLevel == API_1) { // Camera1 API route
sp tmp = static_cast(cameraCb.get());
*client = new Camera2Client(cameraService, tmp, packageName, cameraIdToInt(cameraId),
facing, clientPid, clientUid, servicePid, legacyMode);
} else { // Camera2 API route
sp<:camera2::icameradevicecallbacks> tmp =
static_cast<:camera2::icameradevicecallbacks>(cameraCb.get());
*client = new CameraDeviceClient(cameraService, tmp, packageName, cameraId,
facing, clientPid, clientUid, servicePid);
}
break;
default:
// Should not be reachable
ALOGE("Unknown camera device HAL version: %d", deviceVersion);
return STATUS_ERROR_FMT(ERROR_INVALID_OPERATION,
"Camera device \"%s\" has unknown HAL version %d",
cameraId.string(), deviceVersion);
}
} else {
// A particular HAL version is requested by caller. Create CameraClient
// based on the requested HAL version.
if (deviceVersion > CAMERA_DEVICE_API_VERSION_1_0 &&
halVersion == CAMERA_DEVICE_API_VERSION_1_0) {
// Only support higher HAL version device opened as HAL1.0 device.
sp tmp = static_cast(cameraCb.get());
*client = new CameraClient(cameraService, tmp, packageName, cameraIdToInt(cameraId),
facing, clientPid, clientUid, servicePid, legacyMode);
} else {
// Other combinations (e.g. HAL3.x open as HAL2.x) are not supported yet.
ALOGE("Invalid camera HAL version %x: HAL %x device can only be"
" opened as HAL %x device", halVersion, deviceVersion,
CAMERA_DEVICE_API_VERSION_1_0);
return STATUS_ERROR_FMT(ERROR_ILLEGAL_ARGUMENT,
"Camera device \"%s\" (HAL version %d) cannot be opened as HAL version %d",
cameraId.string(), deviceVersion, halVersion);
}
}
return Status::ok();
}
在此處有2 個(gè)關(guān)鍵步驟
步驟1:創(chuàng)建Camera 的客戶端 Client,根據(jù)調(diào)用出可知是 CameraDeviceClient,創(chuàng)建時(shí)同時(shí)傳入了一個(gè)Hal層回調(diào)的狀態(tài)對象,為ICameraDeviceCallbacks 分別對應(yīng)上面2個(gè)函數(shù)
makeClient 函數(shù) 會(huì)根據(jù)傳入的HAL版本號(hào)halVersion 和設(shè)備版本號(hào)deviceVersion 進(jìn)行初始化以及API的版本號(hào),初始化了一個(gè)CamDeviceClien對象
查看構(gòu)造函數(shù)發(fā)現(xiàn)初始化了父類Camera2ClientBase
CameraDeviceClient::CameraDeviceClient(const sp& cameraService,
const sp<:camera2::icameradevicecallbacks>& remoteCallback,
const String16& clientPackageName,
const String8& cameraId,
int cameraFacing,
int clientPid,
uid_t clientUid,
int servicePid) :
Camera2ClientBase(cameraService, remoteCallback, clientPackageName,
cameraId, cameraFacing, clientPid, clientUid, servicePid),
mInputStream(),
mStreamingRequestId(REQUEST_ID_NONE),
mRequestIdCounter(0) {
ATRACE_CALL();
ALOGI("CameraDeviceClient %s: Opened", cameraId.string());
}
繼續(xù)查看最終發(fā)現(xiàn)是初始化了一個(gè) Camera3Device對象,這個(gè)就是java APP
在打開 Cmaera 時(shí)真正創(chuàng)建的Frameowok 層對象,屬于真正干活的
template
Camera2ClientBase::Camera2ClientBase(
const sp& cameraService,
const sp& remoteCallback,
const String16& clientPackageName,
const String8& cameraId,
int cameraFacing,
int clientPid,
uid_t clientUid,
int servicePid):
TClientBase(cameraService, remoteCallback, clientPackageName,
cameraId, cameraFacing, clientPid, clientUid, servicePid),
mSharedCameraCallbacks(remoteCallback),
mDeviceVersion(cameraService->getDeviceVersion(TClientBase::mCameraIdStr)),
mDeviceActive(false)
{
ALOGI("Camera %s: Opened. Client: %s (PID %d, UID %d)", cameraId.string(),
String8(clientPackageName).string(), clientPid, clientUid);
mInitialClientPid = clientPid;
mDevice = new Camera3Device(cameraId);
LOG_ALWAYS_FATAL_IF(mDevice == 0, "Device should never be NULL here.");
}
步驟二:
對此CameraDeviceClient 進(jìn)行初始化,初始化的時(shí)候傳入了mCameraProviderManager,即
client = static_cast(tmp.get());
ALOGI("%s(), make client for '%s'.", __FUNCTION__, String8{clientPackageName}.string());
LOG_ALWAYS_FATAL_IF(client.get() == nullptr, "%s: CameraService in invalid state",
__FUNCTION__);
err = client->initialize(mCameraProviderManager);
sp mCameraProviderManager,此對象在CameraService 初始化的時(shí)候就構(gòu)造出來了,主要工作之一也是連接HAI層
mCameraProviderManager 是CameraServics 構(gòu)造函數(shù)初始化的時(shí)候賦值的
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;
}
}
3:通知APP層Camera狀態(tài)
frameworks\base\core\java\android\hardware\camera2\impl\CameraDeviceImpl.java
通知到APP Camera 已經(jīng)打開,即在nataive 創(chuàng)建了CameraClient 完成之后CameraManager將native camera device設(shè)到j(luò)ava 的CameraDevice 之后即通知了APP,Camera創(chuàng)建好了
deviceImpl.setRemoteDevice(cameraUser);
device = deviceImpl;
/**
* Set remote device, which triggers initial onOpened/onUnconfigured callbacks
*
*
This function may post onDisconnected and throw CAMERA_DISCONNECTED if remoteDevice dies
* during setup.
*
*/
public void setRemoteDevice(ICameraDeviceUser remoteDevice) throws CameraAccessException {
synchronized(mInterfaceLock) {
// TODO: Move from decorator to direct binder-mediated exceptions
// If setRemoteFailure already called, do nothing
if (mInError) return;
mRemoteDevice = new ICameraDeviceUserWrapper(remoteDevice);
IBinder remoteDeviceBinder = remoteDevice.asBinder();
// For legacy camera device, remoteDevice is in the same process, and
// asBinder returns NULL.
if (remoteDeviceBinder != null) {
try {
remoteDeviceBinder.linkToDeath(this, /*flag*/ 0);
} catch (RemoteException e) {
CameraDeviceImpl.this.mDeviceHandler.post(mCallOnDisconnected);
throw new CameraAccessException(CameraAccessException.CAMERA_DISCONNECTED,
"The camera device has encountered a serious error");
}
}
mDeviceHandler.post(mCallOnOpened);
mDeviceHandler.post(mCallOnUnconfigured);
}
}
private final Runnable mCallOnOpened = new Runnable() {
@Override
public void run() {
StateCallbackKK sessionCallback = null;
synchronized(mInterfaceLock) {
if (mRemoteDevice == null) return; // Camera already closed
sessionCallback = mSessionStateCallback;
}
if (sessionCallback != null) {
sessionCallback.onOpened(CameraDeviceImpl.this);
}
mDeviceCallback.onOpened(CameraDeviceImpl.this);
}
};
此處是在App層定義了AIDL 接口,但是服務(wù)是native層的,為了雙方能通信,Aidl的調(diào)用客戶端是使用java 實(shí)現(xiàn),服務(wù)端采用c++實(shí)現(xiàn)的,確保了binder通信正常,此處用到的Binder服務(wù)關(guān)鍵函數(shù)為
connectDevice,因此connectDevice 的通信方式再此跟蹤下:
frameworks\av\camera\aidl\android\hardware\ICameraService.aidl
/**
* Open a camera device through the new camera API
* Only supported for device HAL versions >= 3.2
*/
ICameraDeviceUser connectDevice(ICameraDeviceCallbacks callbacks,
String cameraId,
String opPackageName,
int clientUid);
aidl_java.png
aidl_java2.png
服務(wù)端實(shí)現(xiàn)此函數(shù)收到函數(shù)請求,如下:
class BpCameraService : public ::android::BpInterface {
public:
explicit BpCameraService(const ::android::sp<::android::ibinder>& _aidl_impl);
virtual ~BpCameraService() = default;
::android::binder::Status getNumberOfCameras(int32_t type, int32_t* _aidl_return) override;
::android::binder::Status getCameraInfo(int32_t cameraId, ::android::hardware::CameraInfo* _aidl_return) override;
::android::binder::Status connect(const ::android::sp<::android::hardware::icameraclient>& client, int32_t cameraId, const ::android::String16& opPackageName, int32_t cl
::android::binder::Status connectDevice(const ::android::sp<::android::hardware::camera2::icameradevicecallbacks>& callbacks, const ::android::String16& cameraId, const
::android::binder::Status connectLegacy(const ::android::sp<::android::hardware::icameraclient>& client, int32_t cameraId, int32_t halVersion, const ::android::String16&
::android::binder::Status addListener(const ::android::sp<::android::hardware::icameraservicelistener>& listener, ::std::vector<::android::hardware::camerastatus>* _aidl
::android::binder::Status removeListener(const ::android::sp<::android::hardware::icameraservicelistener>& listener) override;
::android::binder::Status getCameraCharacteristics(const ::android::String16& cameraId, ::android::hardware::camera2::impl::CameraMetadataNative* _aidl_return) override;
::android::binder::Status getCameraVendorTagDescriptor(::android::hardware::camera2::params::VendorTagDescriptor* _aidl_return) override;
::android::binder::Status getCameraVendorTagCache(::android::hardware::camera2::params::VendorTagDescriptorCache* _aidl_return) override;
::android::binder::Status getLegacyParameters(int32_t cameraId, ::android::String16* _aidl_return) override;
::android::binder::Status supportsCameraApi(const ::android::String16& cameraId, int32_t apiVersion, bool* _aidl_return) override;
::android::binder::Status setTorchMode(const ::android::String16& cameraId, bool enabled, const ::android::sp<::android::ibinder>& clientBinder) override;
::android::binder::Status notifySystemEvent(int32_t eventId, const ::std::vector& args) override;
}; // class BpCameraService
}
services2.png
Status CameraService::connectDevice(
const sp<:camera2::icameradevicecallbacks>& cameraCb,
const String16& cameraId,
const String16& clientPackageName,
int clientUid,
/*out*/
sp<:camera2::icameradeviceuser>* device) {
ATRACE_CALL();
Status ret = Status::ok();
String8 id = String8(cameraId);
sp client = nullptr;
ret = connectHelper<:camera2::icameradevicecallbacks>(cameraCb, id,
CAMERA_HAL_API_VERSION_UNSPECIFIED, clientPackageName,
clientUid, USE_CALLING_PID, API_2,
/*legacyMode*/ false, /*shimUpdateOnly*/ false,
/*out*/client);
if(!ret.isOk()) {
logRejected(id, getCallingPid(), String8(clientPackageName),
ret.toString8());
return ret;
}
String8 pid = String8::format("%d", getCallingPid());
POWERPUSH(129, clientName8.string(), id.string(), pid.string());//define in LogPower.java, 129 stand for camera start now
*device = client;
//add for send msg to nfc
char needSendMsg[255];
property_get("ro.config.hw_camera_nfc_switch",needSendMsg,"");
ALOGI("NFC polling %s", needSendMsg);
if (0 == strcmp(needSendMsg, "true")) {
String8 isOpen = String8::format("false");
android::allowNfcPolling(isOpen);
}
ALOGI("%s(), exit.", __FUNCTION__);
return ret;
}
簡單捋順下調(diào)用過程:
CameraManager.Java的connectDevice ? ICameraService.java(系統(tǒng)編譯)的onTransact-?
ICameraService.cpp(系統(tǒng)編譯)的BpCameraService::connectDevice()?ICameraService.cpp(系統(tǒng)編譯)的::android::status_t BnCameraService::onTransact-?
CameraService.cpp的CameraService::connectDevice()
APP 進(jìn)程在打開之后就等待nataive 層運(yùn)行結(jié)束,native層直到上節(jié)分析的創(chuàng)建成功
CameraDevice對象之后由CameraManager進(jìn)行給java層的CameraDeviceIml 設(shè)置
setRemoteDevice,APP進(jìn)程打開設(shè)備成功,得到了framework給到的CameraDeviceIml對象,可以后續(xù)通過此對Camera進(jìn)行操作
總結(jié)
以上是生活随笔為你收集整理的android sse 人脸识别,基于Android Camera2之openCamera 流程的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: mysql修改主从复制id_mysql主
- 下一篇: android listview高级,A