? ? ? ? 高通SnapdragonCamera相机研究一系列OpenCamer相关的流程,以及比较重要的需要check的Error状态的捕捉和监听。
?1.应用层OpenCamera?
????????CameraActivity::onCreate ->?cameraAPICheck();这边会走一下openCamera的流程,不过有返回就给release,这边open一下的目的怕是仅仅虚晃一枪,试试API1的接口还能不能走了吧。
private boolean cameraAPICheck() {
boolean support = true;
try {
//使用Method方法通过调用android.hardware.Camera的openLegacy方法打开Camera
Method openMethod = Class.forName("android.hardware.Camera").getMethod(
"openLegacy", int.class, int.class);
//这边用来接收的是FrameWork层Camera的实例
Camera camera = (android.hardware.Camera) openMethod.invoke(
null, 0, CAMERA_HAL_API_VERSION_1_0);
//这里就有点那个啥了,好不容易打开了,然后又给release了,不着急后面切换到具体mode时候还要openLegacy
camera.release();
} catch (ReflectiveOperationException e) {
e.printStackTrace();
if (e.getCause().getLocalizedMessage().indexOf("Unknown camera error") != -1) {
support = false;
}
} finally {
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
SharedPreferences.Editor editor = preferences.edit();
editor.putBoolean(CAMERA_API_1_SUPPORT,support);
editor.commit();
return support;
}
}
? ? ? ? CameraActivity::onCreate->setModuleFromIndex(moduleIndex);真正的openCamera流程是在每一个module里面的,下面以PhotoModule为例研究一下。
private void setModuleFromIndex(int moduleIndex) {
mCameraPhotoModuleRootView.setVisibility(View.GONE);
mCameraVideoModuleRootView.setVisibility(View.GONE);
mCameraPanoModuleRootView.setVisibility(View.GONE);
mCameraCaptureModuleRootView.setVisibility(View.GONE);
mCurrentModuleIndex = moduleIndex;
switch (moduleIndex) {
case ModuleSwitcher.VIDEO_MODULE_INDEX:
if(mVideoModule == null) {
mVideoModule = new VideoModule();
mVideoModule.init(this, mCameraVideoModuleRootView);
} else {
mVideoModule.reinit();
}
mCurrentModule = mVideoModule;
mCameraVideoModuleRootView.setVisibility(View.VISIBLE);
break;
case ModuleSwitcher.PHOTO_MODULE_INDEX:
if(mPhotoModule == null) {
mPhotoModule = new PhotoModule();
//init里面添加了openCamera的功能
mPhotoModule.init(this, mCameraPhotoModuleRootView);
} else {
mPhotoModule.reinit();
}
mCurrentModule = mPhotoModule;
mCameraPhotoModuleRootView.setVisibility(View.VISIBLE);
break;
...
}
?LA.UM.8.6.2/LINUX/android/packages/apps/SnapdragonCamera/src/com/android/camera/PhotoModule.java
@Override
public void init(CameraActivity activity, View parent) {
mActivity = activity;
mRootView = parent;
mPreferences = ComboPreferences.get(mActivity);
if (mPreferences == null) {
mPreferences = new ComboPreferences(mActivity);
}
CameraSettings.upgradeGlobalPreferences(mPreferences.getGlobal(), activity);
mCameraId = getPreferredCameraId(mPreferences);
mContentResolver = mActivity.getContentResolver();
// Surface texture is from camera screen nail and startPreview needs it.
// This must be done before startPreview.
mIsImageCaptureIntent = isImageCaptureIntent();
mPreferences.setLocalId(mActivity, mCameraId);
CameraSettings.upgradeLocalPreferences(mPreferences.getLocal());
mUI = new PhotoUI(activity, this, parent);
if (mOpenCameraThread == null) {
//这边重新开了一个线程去做openCamera的流程
mOpenCameraThread = new OpenCameraThread();
mOpenCameraThread.start();
}
...
}
private class OpenCameraThread extends Thread {
@Override
public void run() {
openCamera();
startPreview();
}
}
private OpenCameraThread mOpenCameraThread = null;
private void openCamera() {
if (mPaused) {
return;
}
Log.v(TAG, "Open camera device.");
//这边的mCameraDevice是应用层用来接收的CameraProxy
mCameraDevice = CameraUtil.openCamera(
mActivity, mCameraId, mHandler,
mActivity.getCameraOpenErrorCallback());
if (mCameraDevice == null) {
Log.e(TAG, "Failed to open camera:" + mCameraId);
mHandler.sendEmptyMessage(OPEN_CAMERA_FAIL);
return;
}
mParameters = mCameraDevice.getParameters();
mCameraPreviewParamsReady = true;
initializeCapabilities();
mHandler.sendEmptyMessageDelayed(CAMERA_OPEN_DONE, 100);
return;
}
?LA.UM.8.6.2/LINUX/android/packages/apps/SnapdragonCamera/src/com/android/camera/util/CameraUtil.java
public static CameraManager.CameraProxy openCamera(
Activity activity, final int cameraId,
Handler handler, final CameraManager.CameraOpenErrorCallback cb) {
try {
throwIfCameraDisabled(activity);
return CameraHolder.instance().open(handler, cameraId, cb);
} catch (CameraDisabledException ex) {
handler.post(new Runnable() {
@Override
public void run() {
cb.onCameraDisabled(cameraId);
}
});
}
return null;
}
?LA.UM.8.6.2/LINUX/android/packages/apps/SnapdragonCamera/src/com/android/camera/CameraHolder.java
public synchronized CameraProxy open(
Handler handler, int cameraId,
CameraManager.CameraOpenErrorCallback cb) {
if (DEBUG_OPEN_RELEASE) {
collectState(cameraId, mCameraDevice);
if (mCameraOpened) {
Log.e(TAG, "double open");
dumpStates();
}
}
Assert(!mCameraOpened);
if (mCameraDevice != null && mCameraId != cameraId) {
mCameraDevice.release();
mCameraDevice = null;
mCameraId = -1;
}
if (mCameraDevice == null) {
Log.v(TAG, "open camera " + cameraId);
if (mMockCameraInfo == null) {
mCameraDevice = CameraManagerFactory
.getAndroidCameraManager().cameraOpen(handler, cameraId, cb);
} else {
if (mMockCamera != null) {
mCameraDevice = mMockCamera[cameraId];
} else {
Log.e(TAG, "MockCameraInfo found, but no MockCamera provided.");
mCameraDevice = null;
}
}
...
}
?LA.UM.8.6.2/LINUX/android/packages/apps/SnapdragonCamera/src/com/android/camera/AndroidCameraManagerImpl.java
@Override
public CameraManager.CameraProxy cameraOpen(
Handler handler, int cameraId, CameraOpenErrorCallback callback) {
mCameraHandler.errorCbInstance = CameraOpenErrorCallbackForward
.getNewInstance(handler, callback);
mCameraHandler.obtainMessage(OPEN_CAMERA, cameraId, 0, mCameraHandler.errorCbInstance)
.sendToTarget();
mCameraHandler.waitDone();
if (mCamera != null) {
//AndroidCameraProxyImpl继承的CameraProxy,通过这个应用层代理可以做所有的流的管理
return new AndroidCameraProxyImpl();
} else {
return null;
}
}
@Override
public void handleMessage(final Message msg) {
try {
switch (msg.what) {
case OPEN_CAMERA:
try {
Method openMethod = Class.forName("android.hardware.Camera").getMethod(
"openLegacy", int.class, int.class);
//与CameraActivity一样的OpenCamera方法
mCamera = (android.hardware.Camera) openMethod.invoke(
null, msg.arg1, CAMERA_HAL_API_VERSION_1_0);
} catch (Exception e) {
/* Retry with open if openLegacy doesn't exist/fails */
Log.v(TAG, "openLegacy failed due to " + e.getMessage()
+ ", using open instead");
//调用了高通另一个openCamera的方法
mCamera = android.hardware.Camera.open(msg.arg1);
}
if (mCamera != null) {
mParametersIsDirty = true;
// Get a instance of Camera.Parameters for later use.
if (mParamsToSet == null) {
mParamsToSet = mCamera.getParameters();
}
} else {
if (msg.obj != null) {
((CameraOpenErrorCallback) msg.obj).onDeviceOpenFailure(msg.arg1);
}
}
return;
...
}
? ? ? ? 应用层OpenCamera流程到现在就走完了,但是真正接触项目时,光知道流程是不够的,必须要监控这个流程的状态,有没有正常走完,open是否成功,这一部分的监控是必不可少的。高通SnapdragonCamera CameraOpenErrorCallback是在应用层通过一些抛出的异常做监控的,而MTK Camera是在底层会有onOpend或onError的回调来处理的。
LA.UM.8.6.2/LINUX/android/packages/apps/SnapdragonCamera/src/com/android/camera/CameraManager.java
public interface CameraOpenErrorCallback {
/**
* Callback when {@link com.android.camera.CameraDisabledException} is
* caught.
*
* @param cameraId The disabled camera.
*/
//CameraUtil OpenCamera时抛出
public void onCameraDisabled(int cameraId);
/**
* Callback when {@link com.android.camera.CameraHardwareException} is
* caught.
*
* @param cameraId The camera with the hardware failure.
*/
//AndroidCameraManagerImpl时没有获得FrameWork返回时抛出
public void onDeviceOpenFailure(int cameraId);
/**
* Callback when {@link java.io.IOException} is caught during
* {@link android.hardware.Camera#reconnect()}.
*
* @param mgr The {@link com.android.camera.CameraManager}
* with the reconnect failure.
*/
public void onReconnectionFailure(CameraManager mgr);
/**
* Callback when startPreview failure runtime exception is
* caught.
*
* @param cameraId The camera with the hardware failure.
*/
//PhotoModule里面通过应用层代理CameraProxy去SetPreviewDisplay、startPreview时有异常会抛出
public void onStartPreviewFailure(int cameraId);
}
? ? ?
2.应用层对CameraDevice整个状态的监控??
????????高通晓龙相机在应用层还需要check一个底层绑定的error的回调,用来check整个device的状态是否正常。
public class CameraErrorCallback
implements android.hardware.Camera.ErrorCallback {
public CameraActivity mActivity = null;
//custom error code for thermal shutdown. This should be in sync
//with HAL.
private static final int THERMAL_SHUTDOWN = 50;
public void setActivity(CameraActivity activity) {
mActivity = activity;
}
@Override
public void onError(int error, android.hardware.Camera camera) {
Log.e(TAG, "Got camera error callback. error=" + error);
if (mActivity != null) {
final int resId;
switch (error) {
case android.hardware.Camera.CAMERA_ERROR_SERVER_DIED:
resId = R.string.camera_server_died;
break;
case THERMAL_SHUTDOWN:
resId = R.string.camera_thermal_shutdown;
break;
case android.hardware.Camera.CAMERA_ERROR_UNKNOWN:
default:
resId = R.string.camera_unknown_error;
break;
}
mActivity.runOnUiThread(new Runnable() {
public void run() {
RotateTextToast.makeText(mActivity, resId, Toast.LENGTH_LONG).show();
mActivity.finish();
}
});
} else {
throw new RuntimeException("Unknown error");
}
}
}
? ? ? ? PhotoModule里面将继承自FrameWork Camera的errorCallback?绑定起来.
private void startPreview() {
if (mPaused || mCameraDevice == null || mParameters == null) {
return;
}
synchronized (mCameraDevice) {
SurfaceHolder sh = null;
Log.v(TAG, "startPreview: SurfaceHolder (MDP path)");
if (mUI != null) {
sh = mUI.getSurfaceHolder();
}
// Let UI set its expected aspect ratio
mCameraDevice.setPreviewDisplay(sh);
}
if (!mCameraPreviewParamsReady) {
Log.w(TAG, "startPreview: parameters for preview are not ready.");
return;
}
//Error在openCamera之后,startPreview之前设置
mErrorCallback.setActivity(mActivity);
//mCameraDevice为应用层代理CameraProxy
mCameraDevice.setErrorCallback(mErrorCallback);
...
}
? ? ? ? 下面就详细研究一下HAL捕获到sensor异常,2.5s之后没有数据传输抛出异常之后,一直传给应用层,应用层做相关的规避处理的过程。
LA.UM.8.6.2/LINUX/android/vendor/qcom/proprietary/mm-camera/mm-camera2/media-controller/mct/controller/mct_controller.c
boolean mct_controller_send_cb(mct_pipeline_t *pipeline,
mct_bus_msg_type_t type)
{
boolean rc = FALSE;
mct_pipeline_get_stream_info_t info;
mct_stream_t *parm_stream = NULL;
switch (type) {
case MCT_BUS_MSG_SEND_HW_ERROR: {
CLOGE(CAM_MCT_MODULE, "FATAL: Sending HW_Error");
//捕获到HW异常,发送了CAM_EVENT_TYPE_DAEMON_DIED信号
rc = mct_controller_notify_hal_internal_event(pipeline,
CAM_EVENT_TYPE_DAEMON_DIED);
info.check_type = CHECK_INDEX;
info.stream_index = MCT_SESSION_STREAM_ID;
parm_stream = mct_pipeline_get_stream(pipeline, &info);
if (!parm_stream) {
CLOGE(CAM_MCT_MODULE, "Couldn't find session stream");
rc = FALSE;
break;
}
parm_stream->state = MCT_ST_STATE_BAD;
}
...
}
?LA.UM.8.6.2/LINUX/android/hardware/qcom/camera/QCamera2/HAL/QCameraStateMachine.cpp
case QCAMERA_SM_EVT_EVT_NOTIFY:
{
mm_camera_event_t *cam_evt = (mm_camera_event_t *)payload;
switch (cam_evt->server_event_type) {
case CAM_EVENT_TYPE_DAEMON_DIED:
{
//发送CAMERA_ERROR_SERVER_DIED信号
m_parent->sendEvtNotify(CAMERA_MSG_ERROR,
CAMERA_ERROR_SERVER_DIED,
0);
}
break;
default:
LOGE("Invalid internal event %d in state(%d)",
cam_evt->server_event_type, m_state);
break;
}
}
break;
?LA.UM.8.6.2/LINUX/android/frameworks/av/services/camera/libcameraservice/api1/Camera2Client.cpp
void Camera2Client::notifyError(int32_t errorCode,
const CaptureResultExtras& resultExtras) {
int32_t err = CAMERA_ERROR_UNKNOWN;
switch(errorCode) {
case hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_DISCONNECTED:
err = CAMERA_ERROR_RELEASED;
break;
case hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_DEVICE:
err = CAMERA_ERROR_UNKNOWN;
break;
case hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_SERVICE:
err = CAMERA_ERROR_SERVER_DIED;
break;
case hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_REQUEST:
case hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_RESULT:
case hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_BUFFER:
ALOGW("%s: Received recoverable error %d from HAL - ignoring, requestId %" PRId32,
__FUNCTION__, errorCode, resultExtras.requestId);
mCaptureSequencer->notifyError(errorCode, resultExtras);
return;
default:
err = CAMERA_ERROR_UNKNOWN;
break;
}
ALOGE("%s: Error condition %d reported by HAL, requestId %" PRId32, __FUNCTION__, errorCode,
resultExtras.requestId);
SharedCameraCallbacks::Lock l(mSharedCameraCallbacks);
if (l.mRemoteCallback != nullptr) {
l.mRemoteCallback->notifyCallback(CAMERA_MSG_ERROR, err, 0);
}
}
?LA.UM.8.6.2/LINUX/android/frameworks/base/core/java/android/hardware/Camera.java
case CAMERA_MSG_ERROR :
Log.e(TAG, "Error " + msg.arg1);
if (mDetailedErrorCallback != null) {
mDetailedErrorCallback.onError(msg.arg1, mCamera);
} else if (mErrorCallback != null) {
if (msg.arg1 == CAMERA_ERROR_DISABLED) {
mErrorCallback.onError(CAMERA_ERROR_EVICTED, mCamera);
} else {
mErrorCallback.onError(msg.arg1, mCamera);
}
}
return;
? ? ? ? ?剩下的Error信息通过应用层的CameraErrorCallBack来接收就好了,下图是用来追踪、定位问题的log。

小结:
? ? ? ? 本篇从应用层角度check了晓龙相机openCamera的阶段,重点放在了项目中遇到异常之后的监控、获取机制上,便于项目开展之后的问题分析。
|