SnapdragonCamera骁龙相机源码解析

骁龙相机是高通开发的一个测试系统摄像头的demo,代码完善,功能强大。可以配合Camera驱动进行功能联调。

很多逻辑代码在CaptureModule.java里。

CaptureModule有8000多行,包罗万象。

涉及到界面显示要结合CaptureUI.java 一起来实现。

CaptureActivity持有了 CaptureModule 和 CaptureUI 。

以上是主要的引用关系。

CameraActivity 中调用了以下代码

复制代码
            case ModuleSwitcher.CAPTURE_MODULE_INDEX:
                if(mCaptureModule == null) {
                    mCaptureModule = new CaptureModule();
                    //核心代码!!!
                    mCaptureModule.init(this, mCameraCaptureModuleRootView);
                } else {
                    mCaptureModule.reinit();
                }
                mCurrentModule = mCaptureModule;
                mCameraCaptureModuleRootView.setVisibility(View.VISIBLE);
                Log.e("CameraActity"," setModuleFromIndex =================== CAPTURE_MODULE_INDEX");
                break;

CaptureModule 里初始化代码:

复制代码
@Override
    public void init(CameraActivity activity, View parent) {
        mActivity = activity;
        mRootView = parent;
        mSettingsManager = SettingsManager.getInstance();
        mSettingsManager.createCaptureModule(this);
        mSettingsManager.registerListener(this);
        if (mSettingsManager.mIsHasOneCamera) {
            CURRENT_ID = 0;
        } else {
            if (isBackCameraId()) {
                CURRENT_ID = BACK_MODE;
            } else {
                CURRENT_ID = FRONT_MODE;
            }
        }
        mSettingsManager.init();
        mFirstPreviewLoaded = false;
        Log.d(TAG, "init");
        for (int i = 0; i < MAX_NUM_CAM; i++) {
            mCameraOpened[i] = false;
            mTakingPicture[i] = false;
        }
        for (int i = 0; i < MAX_NUM_CAM; i++) {
            mState[i] = STATE_PREVIEW;
        }
        SceneModule module;
        for (int i = 0; i < mSelectableModes.length + 2; i++) {
            module = new SceneModule();
            module.mode = CameraMode.values()[i];
            mSceneCameraIds.add(module);
        }
        mPostProcessor = new PostProcessor(mActivity, this);
        mFrameProcessor = new FrameProcessor(mActivity, this);

        mContentResolver = mActivity.getContentResolver();
        initModeByIntent();
        initCameraIds();
        mUI = new CaptureUI(activity, this, parent);
        mUI.initializeControlByIntent();

        mFocusStateListener = new FocusStateListener(mUI);
        mLocationManager = new LocationManager(mActivity, this);
    }

通过以下代码初始化CaptureUI

复制代码
 mUI = new CaptureUI(activity, this, parent);
        mUI.initializeControlByIntent();

介绍一个核心操作来,了解是如何切换拍照模式的。

首先,通过CaptureUI ,来对组件赋予监听回调。

复制代码
mFlashButton = (FlashToggleButton) mRootView.findViewById(R.id.flash_button);
        mModeSelectLayout = (RecyclerView) mRootView.findViewById(R.id.mode_select_layout);
        mModeSelectLayout.setLayoutManager(new LinearLayoutManager(mActivity,
                LinearLayoutManager.HORIZONTAL, false));
        mCameraModeAdapter = new Camera2ModeAdapter(mModule.getCameraModeList());

   //设置单击回调 
       mCameraModeAdapter.setOnItemClickListener(mModule.getModeItemClickListener());
        mModeSelectLayout.setAdapter(mCameraModeAdapter);
        mSettingsIcon = (ImageView) mRootView.findViewById(R.id.settings);
        mSettingsIcon.setImageResource(R.drawable.settings);
        mSettingsIcon.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                openSettingsMenu();
            }
        });

对应CaptureModule的处理。

复制代码
 public OnItemClickListener getModeItemClickListener() {
        return new OnItemClickListener() {
            @Override
            public int onItemClick(int mode) {
                if (showLog) Log.e(TAG, "mode >>> " + mode);
                if (!getCameraModeSwitcherAllowed()) {
                    return -1;
                }
                if (mode == CameraMode.VIDEO.ordinal()) {
                    videoCameraId = -1;
                    videoType = VIDEO_DEFAULT;
                } else {
                    if (mode == CameraMode.MACRO.ordinal() || mode == CameraMode.NIGHT.ordinal()) {
                        videoCameraId = -1;
                        videoType = -1;
                    }
                }
                return selectCameraMode(mode);
            }
        };
    }

CaptureModule 核心代码处理:

复制代码
public int selectCameraMode(int mode) {
        if (showLog) Log.e("CaptureModule", "  mode:: ============== " + mode);
        if (showLog)
            Log.e("CaptureModule", "  mCurrentSceneMode.mode:: =================== " + mCurrentSceneMode.mode);

        for (SceneModule sceneModule : mSceneCameraIds) {
            if (showLog) Log.e(TAG, " secenmode:: >> " + sceneModule.mode);
        }

        if (showLog)
            Log.e("CaptureModule", "  mSceneCameraIds.get(mode).mode:: =================== " + mSceneCameraIds.get(mode).mode);
        if (showLog) Log.e("CaptureModule", "  videoType:: =================== " + videoType);
        if (showLog)
            Log.e("CaptureModule", "  videoCameraId:: =================== " + videoCameraId);
        showCameraDevice();

        String value = mSettingsManager.getValue(SettingsManager.KEY_FRONT_REAR_SWITCHER_VALUE);
        boolean post = false;
        if (mode == CameraMode.VIDEO.ordinal()) {
            videoType = VIDEO_DEFAULT;
            videoCameraId = 0;
        } else if (mode == CameraMode.MACRO.ordinal()) {
            if (value != null && value.equals("front")) {
                post = true;
                if (!isBackCamera()) {
                    mUI.performCameraSwitchClick();
                }
            }
        } else if (mode == CameraMode.DEFAULT.ordinal()) {
            videoType = -1;
            videoCameraId = -1;
        } else if (mode == CameraMode.NIGHT.ordinal()) {
            if (value != null && value.equals("front")) {
                if (!isBackCamera()) {
                    post = true;
                    mUI.performCameraSwitchClick();
                }
            }
            if (showLog)
                Log.e("xxx", " mPreviewRequestBuilder.length ===========> " + mPreviewRequestBuilder.length);
            if (showLog)
                Log.e("xxx", " mPreviewRequestBuilder.length ===========> " + mPreviewRequestBuilder.length);
        } else if (mode == CameraMode.PRO_MODE.ordinal()) {
//            if (value != null && value.equals("front")) {
//                if (!isBackCamera()) {
//                    post = true;
//                    mUI.performCameraSwitchClick();
//                }
//            }
        } else if (mode == CameraMode.HFR.ordinal()) {
            if (value != null && value.equals("front")) {
                if (!isBackCamera()) {
                    post = true;
                    mUI.performCameraSwitchClick();
                }
            }
        }


        if (showLog)
            Log.e("CaptureModule", "  mode2:: ============== " + mode);
        if (showLog)
            Log.e("CaptureModule", "  mCurrentSceneMode.mode2 :: =================== " + mCurrentSceneMode.mode);
        if (showLog)
            Log.e("CaptureModule", "  mSceneCameraIds.get(mode).mode2 :: =================== " + mSceneCameraIds.get(mode).mode);
        showCameraDevice();

        nmode = mode;
        if (post) {
            mHandler.postDelayed(new Runnable() {
                @Override
                public void run() {
                    selectModle(nmode);
                }
            }, 1000);
        } else {
            selectModle(mode);
        }
        return 1;
    }

以上经过定制后的代码。代码逻辑更加复杂。因为要支持,夜视和微距摄像头效果。还要支持前摄。

再调用selectModle方法

复制代码
selectModle(int mode) 
复制代码
private int selectModle(int mode) {
//        if (!isVideoModel) {
//            if (mCurrentSceneMode.mode == mSceneCameraIds.get(mode).mode) {
//                return -1;
//            }
//        }
        showCameraDevice();
        setCameraModeSwitcherAllowed(false);
        setNextSceneMode(mode);
        SceneModule nextSceneMode = mSceneCameraIds.get(mode);
        String value = mSettingsManager.getValue(SettingsManager.KEY_FRONT_REAR_SWITCHER_VALUE);
        if (showLog)
            Log.e(TAG, " =============== current Mode is :::  " + mCurrentSceneMode.mode.ordinal());
        if (value != null && value.equals("front") &&
                (nextSceneMode.mode == CameraMode.RTB
                        || nextSceneMode.mode == CameraMode.SAT
                        || nextSceneMode.mode == CameraMode.PRO_MODE
                )) {
            if (showLog)
                Log.e(TAG, " selectModle begin set value KEY_FRONT_REAR_SWITCHER_VALUE  rear ==========   mode:: " + mode);
            mSettingsManager.setValue(SettingsManager.KEY_FRONT_REAR_SWITCHER_VALUE, "rear");
        } else {
            if (showLog) Log.e(TAG, " restartAll ==========   mode:: " + mode);
            restartAll();

        }
        updateZoomSeekBarVisible();
        return 1;
    }

再调用 restartAll方法

复制代码
 public void restartAll() {
        showCameraDevice();
        int nextCameraId = getNextScreneModeId(mNextModeIndex);
        CURRENT_ID = getMainCameraId();
        Log.d(TAG, "restart all CURRENT_ID :" + CURRENT_ID + " nextCameraId :" + nextCameraId);


        if (CURRENT_ID == nextCameraId && mCameraDevice[nextCameraId] != null) {
            mIsCloseCamera = false;
        } else {
            mIsCloseCamera = true;
        }
        SceneModule nextSceneModule = mSceneCameraIds.get(mNextModeIndex);
        if (nextSceneModule.mode == CameraMode.DEFAULT
                || nextSceneModule.mode == CameraMode.PRO_MODE
                || nextSceneModule.mode == CameraMode.HFR
        ) {
            mIsCloseCamera = true;
        }
        if (mCameraDevice[nextCameraId] == null) {
            if (showLog) Log.e(TAG, "  mCameraDevice[nextCameraId] is null " + nextCameraId);
        } else {
            if (showLog) Log.e(TAG, "  mCameraDevice[nextCameraId] is not null " + nextCameraId);
        }

在restartAll中执行各种Camera的初始化操作。首先要关闭原来的摄像头资源,再打开新的摄像头资源。各种操作都封装在以下几个方法。

复制代码
onPauseBeforeSuper();
if (showLog) Log.e(TAG, " do onPauseBeforeSuper");
onPauseAfterSuper(false);
if (showLog) Log.e(TAG, " do onPauseAfterSuper false");
reinitSceneMode();
if (showLog) Log.e(TAG, " do reinitSceneMode ");
onResumeBeforeSuper(true);
if (showLog) Log.e(TAG, " do onResumeBeforeSuper ");
onResumeAfterSuper(true);
if (showLog) Log.e(TAG, " do onResumeAfterSuper ");
setRefocusLastTaken(false);
if (showLog) Log.e(TAG, " do setRefocusLastTaken ");

打开摄像头的操作。

复制代码
onResumeAfterSuper 方法里的
复制代码
 if (mIsCloseCamera) {
            Message msg = Message.obtain();
            msg.what = OPEN_CAMERA;
            msg.arg1 = mCurrentSceneMode.getCurrentId();
            Log.d(TAG, "open is " + msg.arg1);
            if (mCameraHandler != null) {
                mCameraHandler.sendMessage(msg);
            }
        }

对应Handle的操作

复制代码
private class MyCameraHandler extends Handler {

        public MyCameraHandler(Looper looper) {
            super(looper);
        }

        @Override
        public void handleMessage(Message msg) {
            int id = msg.arg1;
            switch (msg.what) {
                case OPEN_CAMERA:
                    openCamera(id);
                    break;
                case CANCEL_TOUCH_FOCUS:
                    cancelTouchFocus(id);
                    break;
            }
        }
    }

执行openCamra操作:

复制代码
private void openCamera(int id) {
        if (mPaused) {
            return;
        }
        if (showLog) Log.e(TAG, "openCamera  1111 " + id);
        CameraManager manager;
        try {
            manager = (CameraManager) mActivity.getSystemService(Context.CAMERA_SERVICE);
            mCameraId[id] = manager.getCameraIdList()[id];
            if (!mCameraOpenCloseLock.tryAcquire(5000, TimeUnit.MILLISECONDS)) {
                Log.d(TAG, "Time out waiting to lock camera opening.");
                throw new RuntimeException("Time out waiting to lock camera opening");
            }
            manager.openCamera(mCameraId[id], mStateCallback, mCameraHandler);
        } catch (CameraAccessException e) {
            e.printStackTrace();
            if (showLog) Log.d(TAG, "openCamera CameraAccessException  2222" + id);
        } catch (InterruptedException e) {
            e.printStackTrace();
            if (showLog) Log.d(TAG, "openCamera InterruptedException  3333 " + id);
        } catch (Exception e) {
            e.printStackTrace();
            if (showLog) Log.d(TAG, "openCamera Exception  44444 " + id);
        }
        if (showLog) Log.d(TAG, "openCamera  end  55555 " + id);
    }

回调mStateCallback 操作。

复制代码
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);
            mCameraOpenCloseLock.release();
            if (mPaused) {
                return;
            }
            showCameraDevice();
            if (showLog)
                Log.e(TAG, "mStateCallback  onOpened  ========== id:: " + id);
            mCameraDevice[id] = cameraDevice;
            mCameraOpened[id] = true;

            if (isBackCamera() && getCameraMode() == DUAL_MODE && id == BAYER_ID) {
                Message msg = mCameraHandler.obtainMessage(OPEN_CAMERA, MONO_ID, 0);
                mCameraHandler.sendMessage(msg);
            } else {
                mCamerasOpened = true;
                if (showLog)
                    Log.e(TAG, "mStateCallback  onOpened  ========== mCamerasOpened:: " + mCamerasOpened);
                mActivity.runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        if (showLog)
                            Log.e(TAG, "mStateCallback  onOpened  ========== mUI.onCameraOpened:: ");
                        mUI.onCameraOpened(mCurrentSceneMode.getCurrentId());
                        if (showLog)
                            Log.e(TAG, "mStateCallback  onOpened  ========== mUI.onCameraOpened:: end ");
                    }
                });
                showCameraDevice();
                createSessions();
            }
        }

注意 mCameraDeviceid = cameraDevice; 和 mCameraOpenedid = true; 有几个摄像头就有几个mCameraDevice。id就是CameraId,一般就是其下标。

同样会有一个非常重要的函数 createSessions() ,有了 CameraDevice就要创建 CaptureSeesion。

复制代码
private void createSessions() {
        if (PersistUtil.isTraceEnable())
            Trace.beginSection("createSessions");
        if (mPaused || !mCamerasOpened || mTempHoldVideoInVideoIntent) return;
        int cameraId = mCurrentSceneMode.getCurrentId();
        if (showLog)
            Log.e(TAG, "createSessions : Current SceneMode is ==== " + mCurrentSceneMode.mode);
        Log.e(TAG, "createSessions : Current cameraId is ===== " + cameraId);
        showCameraDevice();
        switch (mCurrentSceneMode.mode) {
            case VIDEO:
            case VIDEO_NIGHT:
            case VIDEO_MACRO:
            case NIGHT:
                createSessionForVideo
                        (cameraId);
                break;
            case HFR:
                if (!HFR_RATE.equals("")) {
                    mSettingsManager.setValue(SettingsManager.KEY_VIDEO_HIGH_FRAME_RATE, HFR_RATE);
                }
                createSessionForVideo(cameraId);
                break;
            default:
                createSession(cameraId);
        }
        if (PersistUtil.isTraceEnable())
            Trace.endSection();
    }

对应的会执行2个方法,一个是创建Camera的Session createSession(cameraId) 一个是创建Video的Session createSessionForVideo(cameraId)

createSession()

复制代码
if (mChosenImageFormat == ImageFormat.YUV_420_888 || mChosenImageFormat == ImageFormat.PRIVATE) {
                    if (mPostProcessor.isZSLEnabled()) {
                        mPreviewRequestBuilder[id].addTarget(mImageReader[id].getSurface());
                        list.add(mPostProcessor.getZSLReprocessImageReader().getSurface());
                        if (mSaveRaw) {
                            mPreviewRequestBuilder[id].addTarget(mRawImageReader[id].getSurface());
                        }
                        mCameraDevice[id].createReprocessableCaptureSession(new InputConfiguration(mImageReader[id].getWidth(),
                                mImageReader[id].getHeight(), mImageReader[id].getImageFormat()), list, captureSessionCallback, mCameraHandler);
                    } else {
                        if (mSettingsManager.isHeifWriterEncoding() && outputConfigurations != null) {
                            mCameraDevice[id].createCaptureSessionByOutputConfigurations(outputConfigurations,
                                    captureSessionCallback, mCameraHandler);
                        } else {
                            mCameraDevice[id].createCaptureSession(list, captureSessionCallback, mCameraHandler);
                        }
                    }
                } else {
                    outputConfigurations = null;
                    if (ApiHelper.isAndroidPOrHigher() && outputConfigurations != null) {
                        Log.i(TAG, "list size:" + list.size());
                        Log.i(TAG, "create session 111 ");

                        createCameraSessionWithSessionConfiguration(id, outputConfigurations,
                                captureSessionCallback, mCameraHandler, mPreviewRequestBuilder[id]);

//                        mCameraDevice[id].createCaptureSession(list, captureSessionCallback, mCameraHandler);
                    } else {
                        Log.i(TAG, "create session 222 ");

                        mCameraDevice[id].createCaptureSession(list, captureSessionCallback, mCameraHandler);

                    }

captureSessionCallback 的操作

复制代码
CameraCaptureSession.StateCallback captureSessionCallback =
                    new CameraCaptureSession.StateCallback() {

                        @Override
                        public void onConfigured(CameraCaptureSession cameraCaptureSession) {
                            if (mPaused || null == mCameraDevice[id] ||
                                    cameraCaptureSession == null) {
                                return;
                            }
                            Log.i(TAG, "cameracapturesession - onConfigured " + id);
                            setCameraModeSwitcherAllowed(true);
                            // When the session is ready, we start displaying the preview.
                            mCaptureSession[id] = cameraCaptureSession;
                            if (id == getMainCameraId()) {
                                mCurrentSession = cameraCaptureSession;
                            }
                            initializePreviewConfiguration(id);
                            setDisplayOrientation();
                            updateFaceDetection();
                            mFirstPreviewLoaded = false;
                            try {
                                if (isBackCamera() && getCameraMode() == DUAL_MODE) {
                                    linkBayerMono(id);
                                    mIsLinked = true;
                                }
                                // Finally, we start displaying the camera preview.
                                // for cases where we are in dual mode with mono preview off,
                                // don't set repeating request for mono
                                if (mCaptureSession[id] == null) {
                                    return;
                                }
//                                if (id == NIGHT_CAMRA_ID) { //Night模式
//                                    mPreviewRequestBuilder[id].set(CaptureRequest.FLASH_MODE, CaptureRequest.FLASH_MODE_TORCH);
//                                }
                                if (id == MONO_ID && !canStartMonoPreview()
                                        && getCameraMode() == DUAL_MODE) {
                                    mCaptureSession[id].capture(mPreviewRequestBuilder[id]
                                            .build(), mCaptureCallback, mCameraHandler);
                                } else {
                                    if (id == NIGHT_CAMRA_ID) { //Night模式
                                        mPreviewRequestBuilder[id].set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON);
//                                        mPreviewRequestBuilder[id].set(CaptureRequest.FLASH_MODE, CaptureRequest.FLASH_MODE_TORCH);
                                        Log.d(TAG, "createSession : mPreviewRequestBuilder FLASH_MODE_TORCH ===== ");
                                    }
                                    mCaptureSession[id].setRepeatingRequest(mPreviewRequestBuilder[id]
                                            .build(), mCaptureCallback, mCameraHandler);
                                }
                                if (mIntentMode == INTENT_MODE_STILL_IMAGE_CAMERA &&
                                        mIsVoiceTakePhote) {
                                    mHandler.sendEmptyMessageDelayed(VOICE_INTERACTION_CAPTURE, 500);
                                }
                                if (isClearSightOn()) {
                                    ClearSightImageProcessor.getInstance().onCaptureSessionConfigured(id == BAYER_ID, cameraCaptureSession);
                                } else if (mChosenImageFormat == ImageFormat.PRIVATE && id == getMainCameraId()) {
                                    mPostProcessor.onSessionConfigured(mCameraDevice[id], mCaptureSession[id]);
                                }

                            } catch (CameraAccessException e) {
                                e.printStackTrace();
                            } catch (IllegalStateException e) {
                                e.printStackTrace();
                            } catch (IllegalArgumentException e) {
                                e.printStackTrace();
                            }
                            mCurrentSessionClosed = false;

                        }

                        @Override
                        public void onConfigureFailed(CameraCaptureSession cameraCaptureSession) {
                            if (showLog)
                                Log.e(TAG, "cameracapturesession - onConfigureFailed " + id);
                            setCameraModeSwitcherAllowed(true);
                            if (mActivity.isFinishing()) {
                                return;
                            }
//                            Toast.makeText(mActivity, "Camera Initialization Failed",
//                                    Toast.LENGTH_SHORT).show();
                        }

                        @Override
                        public void onClosed(CameraCaptureSession session) {
                            Log.d(TAG, "cameracapturesession - onClosed");
                            setCameraModeSwitcherAllowed(true);
                        }
                    };

createSessionForVideo()

复制代码
 if (showLog)
                Log.e(TAG, "createSessionForVideo   66666666666666 ");
            if (isHighSpeedRateCapture()) {
                int optionMode = isSSMEnabled() ? STREAM_CONFIG_SSM : SESSION_HIGH_SPEED;
                if (showLog)
                    Log.e("TAG", " buildConstrainedCameraSession in ");
                buildConstrainedCameraSession(mCameraDevice[cameraId], optionMode,
                        surfaces, mSessionListener, mCameraHandler, mVideoRecordRequestBuilder);
                if (showLog)
                    Log.e(TAG, "createSessionForVideo    77777777777777777");
            } else {
                if (showLog)
                    Log.e("TAG", " configureCameraSessionWithParameters in  cameraId :: " + cameraId);
                configureCameraSessionWithParameters(cameraId, surfaces,
                        mSessionListener, mCameraHandler, mVideoRecordRequestBuilder);
                if (showLog)
                    Log.e(TAG, "createSessionForVideo    888888888888");
            }

创建CameraSession和VideoSession的主要区别。

复制代码
CameraSession 使用了 mVideoRecordRequestBuilder 和  mPreviewRequestBuilder。
VideoSession 使用了 mVideoPreviewSurface 和 mMediaRecorderSurface。

CameraSession 通过拍照操作,来使用ImageReader获取图片数据。对应CameraSession有ImageReader实现的地方。

复制代码
 mCurrentSession.setRepeatingRequest(mVideoRecordRequestBuilder.build(),
                                mCaptureCallback, mCameraHandler);

执行以上操作后,就可以预览看到的内容了。

对应的,还有关闭Camera的操作。

复制代码
closeCamera()
复制代码
/**
     * Closes the current {@link CameraDevice}.
     */
    private void closeCamera() {
        Log.d(TAG, "closeCamera ============== begin");

        closeProcessors();

        /* no need to set this in the callback and handle asynchronously. This is the same
        reason as why we release the semaphore here, not in camera close callback function
        as we don't have to protect the case where camera open() gets called during camera
        close(). The low level framework/HAL handles the synchronization for open()
        happens after close() */

        try {
            // Close camera starting with AUX first
            for (int i = MAX_NUM_CAM - 1; i >= 0; i--) {
                if (null != mCameraDevice[i]) {
                    try {
                        if (!mCameraOpenCloseLock.tryAcquire(2000, TimeUnit.MILLISECONDS)) {
                            Log.d(TAG, "Time out waiting to lock camera closing.");
//                            throw new RuntimeException("Time out waiting to lock camera closing");
                        }
                    } catch (Exception e) {
                        mCameraOpenCloseLock.release();
                        e.printStackTrace();
                    }

                    Log.d(TAG, "Closing camera: " + mCameraDevice[i].getId());

                    // session was closed here if intentMode is INTENT_MODE_VIDEO
                    if (mIntentMode != INTENT_MODE_VIDEO) {
                        try {
                            if (isAbortCapturesEnable() && mCaptureSession[i] != null) {
                                mCaptureSession[i].abortCaptures();
                                Log.d(TAG, "Closing camera call abortCaptures ");
                            }
                            if (isSendRequestAfterFlushEnable() && mCaptureSession[i] != null) {
                                Log.v(TAG, "Closing camera call setRepeatingRequest");
                                mCaptureSession[i].setRepeatingRequest(mPreviewRequestBuilder[i].build(),
                                        mCaptureCallback, mCameraHandler);
                            }
                        } catch (IllegalStateException | CameraAccessException e) {
                            e.printStackTrace();
                        }
                    }
                    mCameraDevice[i].close();
                    mCameraDevice[i] = null;
                    mCameraOpened[i] = false;
                    mCaptureSession[i] = null;
                }
            }

            mIsLinked = false;

            if (null != mMediaRecorder) {
                mMediaRecorder.release();
                mMediaRecorder = null;
            }
        } catch (RuntimeException e) {
            mCameraOpenCloseLock.release();
//            throw new RuntimeException("Interrupted while trying to lock camera closing.", e);
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            mCurrentSessionClosed = true;
            mCameraOpenCloseLock.release();
        }
        Log.d(TAG, "closeCamera ============== end");
    }
复制代码
closeImageReader()的操作
复制代码
private void closeImageReader() {
        for (int i = MAX_NUM_CAM - 1; i >= 0; i--) {
            if (null != mImageReader[i]) {
                mImageReader[i].close();
                mImageReader[i] = null;
            }
            if (null != mRawImageReader[i]) {
                mRawImageReader[i].close();
                mRawImageReader[i] = null;
            }
        }
        for (int i = mYUVCount - 1; i >= 0; i--) {
            if (null != mYUVImageReader[i]) {
                mYUVImageReader[i].close();
                mYUVImageReader[i] = null;
            }
        }
        if (null != mVideoSnapshotImageReader) {
            mVideoSnapshotImageReader.close();
            mVideoSnapshotImageReader = null;
        }
    }

closeProcessors()

复制代码
private void closeProcessors() {
        if (mPostProcessor != null) {
            mPostProcessor.onClose();
        }

        if (mFrameProcessor != null) {
            mFrameProcessor.onClose();
        }
    }

closeSessions()

复制代码
private void closeSessions() {
        for (int i = MAX_NUM_CAM - 1; i >= 0; i--) {
            if (null != mCaptureSession[i]) {
                if (mCamerasOpened) {
                    try {
                        if (mCurrentSession instanceof CameraConstrainedHighSpeedCaptureSession) {
                            List requestList = ((CameraConstrainedHighSpeedCaptureSession)
                                    mCurrentSession).createHighSpeedRequestList(
                                    mVideoRecordRequestBuilder.build());
                            mCurrentSession.captureBurst(requestList, null, mCameraHandler);
                        } else {
                            mCaptureSession[i].capture(mPreviewRequestBuilder[i].build(), null,
                                    mCameraHandler);
                        }
                    } catch (CameraAccessException e) {
                        e.printStackTrace();
                    } catch (IllegalStateException e) {
                        e.printStackTrace();
                    } catch (IllegalArgumentException e) {
                        e.printStackTrace();
                    }
                }
                mCaptureSession[i].close();
                mCaptureSession[i] = null;
            }
        }
    }

以上是Camera的初始化流程,很复杂。这里单纯的是CaptureModule的逻辑。其中还要涉及到

复制代码
CaptureUI的逻辑交互。

其中主要调用 showRelatedIcons(CaptureModule.CameraMode mode),根据显示模式显示不同的界面。

复制代码
public void showRelatedIcons(CaptureModule.CameraMode mode) {
        //common settings
        mShutterButton.setVisibility(View.VISIBLE);
        mFrontBackSwitcher.setVisibility(View.VISIBLE);
        photoVideoSwitcher.setVisibility(View.INVISIBLE);
        txt_macro_advice.setVisibility(View.INVISIBLE);
        mMakeupButton.setVisibility(View.INVISIBLE);
        mSceneModeSwitcher.setVisibility(View.INVISIBLE);
        //settings for each mode
        switch (mode) {
            case DEFAULT:
                mFilterModeSwitcher.setVisibility(View.VISIBLE);
                mSceneModeSwitcher.setVisibility(View.VISIBLE);
                mVideoButton.setVisibility(View.INVISIBLE);
                mMuteButton.setVisibility(View.INVISIBLE);
                mPauseButton.setVisibility(View.INVISIBLE);
                break;
            case RTB:
            case SAT:
                mFilterModeSwitcher.setVisibility(View.VISIBLE);
                mSceneModeSwitcher.setVisibility(View.VISIBLE);
                mVideoButton.setVisibility(View.INVISIBLE);
                mFlashButton.setVisibility(View.INVISIBLE);
                mMuteButton.setVisibility(View.INVISIBLE);
                mPauseButton.setVisibility(View.INVISIBLE);
                if (!DEV_LEVEL_ALL) {
                    mFrontBackSwitcher.setVisibility(View.INVISIBLE);
                }
                break;
            case VIDEO:
            case HFR:
                mFrontBackSwitcher.setVisibility(View.VISIBLE);
                photoVideoSwitcher.setVisibility(View.INVISIBLE);
                mVideoButton.setVisibility(View.VISIBLE);
                mFilterModeSwitcher.setVisibility(View.VISIBLE);
                if (mModule.isBackCamera()) {
                    mFlashButton.setVisibility(View.INVISIBLE);
                } else {
                    mFlashButton.setVisibility(View.VISIBLE);
                }
                mShutterButton.setVisibility(View.INVISIBLE);

                break;
            case PRO_MODE:
                mFilterModeSwitcher.setVisibility(View.INVISIBLE);
                mVideoButton.setVisibility(View.INVISIBLE);
                mFrontBackSwitcher.setVisibility(View.INVISIBLE);
                mMuteButton.setVisibility(View.INVISIBLE);
                mPauseButton.setVisibility(View.INVISIBLE);
//                if (mModule.isBackCamera()) {
//                    mFlashButton.setVisibility(View.VISIBLE);
//                } else {
                mFlashButton.setVisibility(View.INVISIBLE);
//                }
                break;
            case MACRO:
                mFrontBackSwitcher.setVisibility(View.INVISIBLE);
                photoVideoSwitcher.setVisibility(View.VISIBLE);
                ((RotateImageView) photoVideoSwitcher).setImageResource(R.drawable.video_switch);
                mVideoButton.setVisibility(View.INVISIBLE);
                mFilterModeSwitcher.setVisibility(View.INVISIBLE);
                txt_macro_advice.setVisibility(View.VISIBLE);
                break;
            case VIDEO_MACRO:
                mFrontBackSwitcher.setVisibility(View.INVISIBLE);
                photoVideoSwitcher.setVisibility(View.VISIBLE);
                ((RotateImageView) photoVideoSwitcher).setImageResource(R.drawable.photo_switch);
                mVideoButton.setVisibility(View.VISIBLE);
                mFilterModeSwitcher.setVisibility(View.INVISIBLE);
                mShutterButton.setVisibility(View.INVISIBLE);
                txt_macro_advice.setVisibility(View.VISIBLE);
                break;
            case VIDEO_NIGHT:
                mFlashButton.setVisibility(View.VISIBLE);
                mFrontBackSwitcher.setVisibility(View.INVISIBLE);
                photoVideoSwitcher.setVisibility(View.VISIBLE);
                ((RotateImageView) photoVideoSwitcher).setImageResource(R.drawable.photo_switch);
                mFilterModeSwitcher.setVisibility(View.INVISIBLE);
                mShutterButton.setVisibility(View.INVISIBLE);
                mVideoButton.setVisibility(View.VISIBLE);
                break;
            case NIGHT:
                mFlashButton.setVisibility(View.INVISIBLE);
                mFrontBackSwitcher.setVisibility(View.INVISIBLE);
                photoVideoSwitcher.setVisibility(View.VISIBLE);
                ((RotateImageView) photoVideoSwitcher).setImageResource(R.drawable.video_switch);
                mVideoButton.setVisibility(View.INVISIBLE);
                mFilterModeSwitcher.setVisibility(View.INVISIBLE);
                break;
            default:
                break;
        }

        String value = mSettingsManager.getValue(SettingsManager.KEY_FRONT_REAR_SWITCHER_VALUE);

        if (value == null) {
            mFrontBackSwitcher.setVisibility(View.INVISIBLE);
        }
        if (mModule.getVideoType() == CaptureModule.VIDEO_DEFAULT || mModule.getCurrenCameraMode() == CaptureModule.CameraMode.HFR) {
            photoVideoSwitcher.setVisibility(View.INVISIBLE);
            if (mModule.getCurrenCameraMode() == CaptureModule.CameraMode.HFR) {
                if (mModule.isBackCamera()) {
                    mFlashButton.setVisibility(View.VISIBLE);
                } else {
                    mFlashButton.setVisibility(View.INVISIBLE);
                }
            }
        }

        if (mModule.mMFNREnable && mModule.getMainCameraId() == android.hardware.Camera.CameraInfo.CAMERA_FACING_FRONT) {
            mFilterModeSwitcher.setVisibility(View.INVISIBLE);
        }
    }

源码多读,多多比较思考和跟踪代码的流程。

如何编译 在SnapdragonCamera工程呢?

执行

source ./build/envsetup.sh

执行

lunch

选择正确的配置

在SnapdragonCamera工程下,执行 ,

mm

编译即可。

执行

adb install -r ../../../../SnapdragonCamera.apk

安装即可。

相关推荐
y = xⁿ3 小时前
DeepSeek Harness 学习日记:关于Agent接口,工具调用的底层实现
android·java·学习
2601_962066495 小时前
【Sql Server】Update中的From语句,以及常见更新操作方式
android·java·数据库
用户693717500138411 小时前
曾经安卓开发人手一个的 EventBus,为什么现在没人爱用了?
android·android studio
九皇叔叔13 小时前
MySQL ORDER BY 性能优化详解:Using filesort、联合索引、ASC/DESC 与覆盖索引
android·adb
OriginCoding13 小时前
用 AI Agent 协作完成一个 Android TOTP 应用:从需求边界到 v1.0.0
android·ai编程
杉氧16 小时前
React 灵魂:深入剖析 Hooks 与副作用(Side Effects)陷阱
android·前端·react native
又见情义16 小时前
RK3568 + RTL8211F 网络唤醒(WOL)功能适配全记录
android·网络·驱动开发
用户09340777351417 小时前
HarmonyOS WPS Open SDK 实践:registerApp 鉴权与就绪门禁
android·typescript·harmonyos
jike_202617 小时前
会议离线录音APP:无网络记录能力对比
android·智能手机·语音识别
挽安学长17 小时前
浅谈一下,伟财工程水印相机的特点及优势!
数码相机