android camera2启动流程

本文详细梳理了Android原生Camera2应用的启动流程,从CameraActivity的onCreate开始,逐步讲解如何通过PhotoModule和CameraController初始化相机,并最终在CameraAgent中成功打开相机并回调onCameraOpened方法。整个流程从CameraActivity传递Callback到CameraController,再由CameraActivity新建CameraController,完成相机的启动操作。
AI助手已提取文章相关产品:

重构原生camera2 有3个月了,现在也算告一段落,这里总结一些原生APK流程以做记录。
camera2的所有主要操作都在一个activity中进行,那就是CameraActivity.java,所以现在先onCreate开始说起,由于我们现在主要讲启动流程,所以将与主流程无关的代码和UI界面相关的复杂代码删除,以便阅读。
CameraActivity.java

public void onCreate(Bundle state) {
    CameraPerformanceTracker.onEvent(CameraPerformanceTracker.ACTIVITY_START);
    super.onCreate(state);
    if (!Glide.isSetup()) {
        Glide.setup(new GlideBuilder(this)
            .setResizeService(new FifoPriorityThreadPoolExecutor(1)));
        Glide.get(this).setMemoryCategory(MemoryCategory.HIGH);
    }

    mOnCreateTime = System.currentTimeMillis();
    mAppContext = getApplicationContext();
    mSoundPlayer = new SoundPlayer(mAppContext);

    //获取cameramanager,在CaptureModule中使用,但是我们拍照用的是PhotoModule所以暂时无用
    mCameraManager = OneCameraManager.get(this);

    // TODO: Try to move all the resources allocation to happen as soon as
    // possible so we can call module.init() at the earliest time.
    mModuleManager = new ModuleManagerImpl();
    GcamHelper.init(getContentResolver());

    //初始化Modules,这里Module的作用相当于MVC模式中M的作用,它对camera进行操作。
    ModulesInfo.setupModules(mAppContext, mModuleManager);

    //SettingsManager保存camera配置
    mSettingsManager = getServices().getSettingsManager();
    AppUpgrader appUpgrader = new AppUpgrader(this);
    appUpgrader.upgrade(mSettingsManager);
    Keys.setDefaults(mSettingsManager, mAppContext);

    getWindow().requestFeature(Window.FEATURE_ACTION_BAR);
    setContentView(R.layout.activity_main);

    mActionBar = getActionBar();
    // set actionbar background to 100% or 50% transparent
    if (ApiHelper.isLOrHigher()) {
        mActionBar.setBackgroundDrawable(new ColorDrawable(0x00000000));
    } else {
        mActionBar.setBackgroundDrawable(new ColorDrawable(0x80000000));
    }
    mActionBar.addOnMenuVisibilityListener(mOnMenuVisibilityListener);

    mMainHandler = new MainHandler(this, getMainLooper());

    //创建camera的controll对象,通过CameraController来对framework的API接口进行控制,现在camera有2套API机制可以在CameraAgentFactory中看到,后续再进行说明。
    mCameraController = new CameraController(mAppContext, this, mMainHandler,
            CameraAgentFactory.getAndroidCameraAgent(this, CameraAgentFactory.CameraApi.API_1),
            CameraAgentFactory.getAndroidCameraAgent(this, CameraAgentFactory.CameraApi.AUTO));
    mCameraController.setCameraDefaultExceptionCallback(mCameraDefaultExceptionCallback,
            mMainHandler);

    .........


    //CameraAppUI来绘制camera总UI,不同module的UI在对应的module内再绘制,比如photomodule的ui由PhotoUI绘制
    mCameraAppUI = new CameraAppUI(this,
            (MainActivityLayout) findViewById(R.id.activity_root_view), isCaptureIntent());

    .........

    //设置当前module
    setModuleFromModeIndex(getModeIndex());

    //初始化UI
    mCameraAppUI.prepareModuleUI();

    //初始化当前Module
    mCurrentModule.init(this, isSecureCamera(), isCaptureIntent());

   .........
}

//这样oncreate完成,接下来看onStart,我们拍照界面用的是PhotoModule,所以后面module都用PhotoModule为列

public void onStart() {
    super.onStart();
    mIsActivityRunning = true;
    mPanoramaViewHelper.onStart();

    //获取当前所用moduleID
    int modeIndex = getModeIndex();
    if (!isCaptureIntent() && mCurrentModeIndex != modeIndex) {
    //切换modeIndex所代表的module
        onModeSelected(modeIndex);
    }

    if (mResetToPreviewOnResume) {
        mCameraAppUI.resume();
        mResetToPreviewOnResume = false;
    }
}


public void onModeSelected(int modeIndex) {
    if (mCurrentModeIndex == modeIndex) {
        return;
    }

    CameraPerformanceTracker.onEvent(CameraPerformanceTracker.MODE_SWITCH_START);
    // Record last used camera mode for quick switching
    if (modeIndex == getResources().getInteger(R.integer.camera_mode_photo)
            || modeIndex == getResources().getInteger(R.integer.camera_mode_gcam)) {
        mSettingsManager.set(SettingsManager.SCOPE_GLOBAL,
                             Keys.KEY_CAMERA_MODULE_LAST_USED,
                             modeIndex);
    }

    //关闭之前module
    closeModule(mCurrentModule);

    // Select the correct module index from the mode switcher index.
    modeIndex = getPreferredChildModeIndex(modeIndex);
    setModuleFromModeIndex(modeIndex);

    mCameraAppUI.resetBottomControls(mCurrentModule, modeIndex);
    mCameraAppUI.addShutterListener(mCurrentModule);
    mCameraAppUI.hideLetterboxing();
    //打开所选module
    openModule(mCurrentModule);
    mCurrentModule.onOrientationChanged(mLastRawOrientation);
    // Store the module index so we can use it the next time the Camera
    // starts up.
    //保存当前module值到sharePreference
    mSettingsManager.set(SettingsManager.SCOPE_GLOBAL,
                         Keys.KEY_STARTUP_MODULE_INDEX, modeIndex);
}


private void openModule(CameraModule module) {
    module.init(this, isSecureCamera(), isCaptureIntent());
    module.hardResetSettings(mSettingsManager);
    module.resume();
    UsageStatistics.instance().changeScreen(currentUserInterfaceMode(),
            NavigationChange.InteractionCause.BUTTON);
    updatePreviewVisibility();
}

private void closeModule(CameraModule module) {
    module.pause();
    mCameraAppUI.clearModuleUI();
}

//现在在PhotoModule中查看对应init,resum,epause
PhotoModule.java

public void init(CameraActivity activity, boolean isSecureCamera, boolean isCaptureIntent) {
    mActivity = activity;
    // TODO: Need to look at the controller interface to see if we can get
    // rid of passing in the activity directly.
    mAppController = mActivity;

    //控制UI
    mUI = new PhotoUI(mActivity, this, mActivity.getModuleLayoutRoot());
    mActivity.setPreviewStatusListener(mUI);

    SettingsManager settingsManager = mActivity.getSettingsManager();
    //获取当前cameraID,一般后摄为0,前摄为1
    mCameraId = settingsManager.getInteger(mAppController.getModuleScope(),
                                           Keys.KEY_CAMERA_ID);

    .........
}


public void resume() {
    mPaused = false;

    // Add delay on resume from lock screen only, in order to to speed up
    // the onResume --> onPause --> onResume cycle from lock screen.
    // Don't do always because letting go of thread can cause delay.
    if (isResumeFromLockscreen()) {
        Log.v(TAG, "On resume, from lock screen.");
        // Note: onPauseAfterSuper() will delete this runnable, so we will
        // at most have 1 copy queued up.
        mHandler.postDelayed(mResumeTaskRunnable, ON_RESUME_TASKS_DELAY_MSEC);
    } else {
        Log.v(TAG, "On resume.");
        onResumeTasks();
    }
}

private void onResumeTasks() {
    if (mPaused) {
        return;
    }
    Log.v(TAG, "Executing onResumeTasks.");

    mCountdownSoundPlayer.loadSound(R.raw.timer_final_second);
    mCountdownSoundPlayer.loadSound(R.raw.timer_increment);
    if (mFocusManager != null) {
        // If camera is not open when resume is called, focus manager will
        // not be initialized yet, in which case it will start listening to
        // preview area size change later in the initialization.
        mAppController.addPreviewAreaSizeChangedListener(mFocusManager);
    }
    mAppController.addPreviewAreaSizeChangedListener(mUI);

    CameraProvider camProvider = mActivity.getCameraProvider();
    if (camProvider == null) {
        // No camera provider, the Activity is destroyed already.
        return;
    }
    //打开camera
    requestCameraOpen();

    .........
}

private void requestCameraOpen() {
    Log.v(TAG, "requestCameraOpen");
    //GservicesHelper.useCamera2ApiThroughPortabilityLayer(mActivity)默认为true
    //getCameraProvider()获得的对象就是在CameraActivity中new出来的CameraController
    mActivity.getCameraProvider().requestCamera(mCameraId,
            GservicesHelper.useCamera2ApiThroughPortabilityLayer(mActivity));
}

下面看CameraController.java

public class CameraController implements CameraAgent.CameraOpenCallback, CameraProvider {
    private final CameraAgent mCameraAgent;
    private final CameraAgent mCameraAgentNg;

    //CameraActivity oncreate时NEW的对象
    public CameraController(Context context, CameraAgent.CameraOpenCallback callbackReceiver,
            Handler handler, CameraAgent cameraManager, CameraAgent cameraManagerNg) {
        mContext = context;
    //将CameraActivity中复写的CameraAgent.CameraOpenCallback传入
        mCallbackReceiver = callbackReceiver;
        mCallbackHandler = handler;

    //看CameraActivity中初始化的时候可以看到cameraManager传入的是AndroidCameraAgentImpl.java对象
        mCameraAgent = cameraManager;
        // If the new implementation is the same as the old, the
        // CameraAgentFactory decided this device doesn't support the new API.
    //这里如果用的是camera_api2则会是AndroidCamera2AgentImpl.java对象 否则也是AndroidCameraAgentImpl.java对象
        mCameraAgentNg = cameraManagerNg != cameraManager ? cameraManagerNg : null;
        mInfo = mCameraAgent.getCameraDeviceInfo();
        if (mInfo == null && mCallbackReceiver != null) {
            mCallbackReceiver.onDeviceOpenFailure(-1, "GETTING_CAMERA_INFO");
        }
    }

    @Override
    public void requestCamera(int id, boolean useNewApi) {
    //如果打开的是相同的cameraId则返回
        if (mRequestingCameraId != EMPTY_REQUEST || mRequestingCameraId == id) {
            return;
        }
        if (mInfo == null) {
            return;
        }
        mRequestingCameraId = id;

        // Only actually use the new API if it's supported on this device.
    //useNewApi为true时,说明走API2
        useNewApi = mCameraAgentNg != null && useNewApi;
        CameraAgent cameraManager = useNewApi ? mCameraAgentNg : mCameraAgent;

        if (mCameraProxy == null) {
            // No camera yet.
        //第一次启动camera时会走这里
            checkAndOpenCamera(mContext, cameraManager, id, mCallbackHandler, this);
        } else if (mCameraProxy.getCameraId() != id || mUsingNewApi != useNewApi) {
        //切换camera时会走这先关闭camera再重启
            boolean syncClose = GservicesHelper.useCamera2ApiThroughPortabilityLayer(mContext);
            Log.v(TAG, "different camera already opened, closing then reopening");
            // Already has camera opened, and is switching cameras and/or APIs.
            if (mUsingNewApi) {
                mCameraAgentNg.closeCamera(mCameraProxy, true);
            } else {
                // if using API2 ensure API1 usage is also synced
                mCameraAgent.closeCamera(mCameraProxy, syncClose);
            }
            checkAndOpenCamera(mContext, cameraManager, id, mCallbackHandler, this);
        } else {
            // The same camera, just do a reconnect.
            Log.v(TAG, "reconnecting to use the existing camera");
            mCameraProxy.reconnect(mCallbackHandler, this);
            mCameraProxy = null;
        }

    private static void checkAndOpenCamera(Context context, CameraAgent cameraManager,
            final int cameraId, Handler handler, final CameraAgent.CameraOpenCallback cb) {
        Log.v(TAG, "checkAndOpenCamera");
        try {
            CameraUtil.throwIfCameraDisabled(context);
        //这里调用CameraAgent的openCamera
            cameraManager.openCamera(handler, cameraId, cb);
        } catch (CameraDisabledException ex) {
            handler.post(new Runnable() {
                @Override
                public void run() {
                    cb.onCameraDisabled(cameraId);
                }
            });
        }
    }
}

CameraAgent.java

public void openCamera(final Handler handler, final int cameraId,
                       final CameraOpenCallback callback) {
    getDispatchThread().runJob(new Runnable() {
        @Override
        public void run() {
        //这里发送CameraActions.OPEN_CAMERA消息,假设我们走的是API1,那AndroidCameraAgentImpl接收消息
            getCameraHandler().obtainMessage(CameraActions.OPEN_CAMERA, cameraId, 0,
                    CameraOpenCallbackForward.getNewInstance(handler, callback)).sendToTarget();
        }});
}


AndroidCameraAgentImpl.java
    case CameraActions.OPEN_CAMERA: {
        final CameraOpenCallback openCallback = (CameraOpenCallback) msg.obj;
        final int cameraId = msg.arg1;
    //如果camera已经打开则回调onDeviceOpenedAlready
        if (mCameraState.getState() != AndroidCameraStateHolder.CAMERA_UNOPENED) {
            openCallback.onDeviceOpenedAlready(cameraId, generateHistoryString(cameraId));
            break;
        }

        Log.i(TAG, "Opening camera " + cameraId + " with camera1 API");
    //API1中通过camera.java来设置camera,这里通过JNI方法native_setup来启动camera并获取mCamera对象
        mCamera = android.hardware.Camera.open(cameraId);
        if (mCamera != null) {
            mCameraId = cameraId;
        //私有类 用来获取Camera.getParameters()
            mParameterCache = new ParametersCache(mCamera);

            mCharacteristics =
                    AndroidCameraDeviceInfo.create().getCharacteristics(cameraId);
        //初始化camrea设置相关的信息,如果支持功能则加载到AndroidCameraCapabilities的列表中
            mCapabilities = new AndroidCameraCapabilities(
                    mParameterCache.getBlocking());

            mCameraState.setState(AndroidCameraStateHolder.CAMERA_IDLE);

        //回调onCameraOpened方法,通知camera已经open,并传递参数
            if (openCallback != null) {
                openCallback.onCameraOpened(
                        new AndroidCameraProxyImpl(cameraId, mCamera,
                                mCharacteristics, mCapabilities));
            }
        } else {
        //打开camera失败则回调onDeviceOpenFailure
            if (openCallback != null) {
                openCallback.onDeviceOpenFailure(cameraId, generateHistoryString(cameraId));
            }
        }
        break;
    }

至此camea已经成功打开,并回调Callback的onCameraOpened方法通知上层,我们前面知道Callback是在CameraController.java中传递下来的,
而又是在CameraActivity.java中new的CameraController,所以这个Callback最初是在CameraActivity中传递下去的,现在回头看
CameraActivity.java

public void onCameraOpened(CameraAgent.CameraProxy camera) {
    Log.v(TAG, "onCameraOpened");
    //界面未显示的话关闭camera
    if (mPaused) {

        Log.v(TAG, "received onCameraOpened but activity is paused, closing Camera");
        mCameraController.closeCamera(false);
        return;
    }

    //这里设置界面上方的一些控件
    if (!mSettingsManager.isSet(SettingsManager.SCOPE_GLOBAL,
                                Keys.KEY_FLASH_SUPPORTED_BACK_CAMERA)) {
        HardwareSpec hardware =
                new HardwareSpecImpl(getCameraProvider(), camera.getCapabilities());
        mSettingsManager.set(SettingsManager.SCOPE_GLOBAL,
                             Keys.KEY_FLASH_SUPPORTED_BACK_CAMERA,
                             hardware.isFlashSupported());
    }

    //此模式不支持camera时关闭camera,一般默认都写成支持
    if (!mModuleManager.getModuleAgent(mCurrentModeIndex).requestAppForCamera()) {
        // We shouldn't be here. Just close the camera and leave.
        mCameraController.closeCamera(false);
        throw new IllegalStateException("Camera opened but the module shouldn't be " +
                "requesting");
    }

    //我们这里以PhotoModule为例所以mCurrentModule为PhotoModule
    if (mCurrentModule != null) {
    //这里将配置写入camera
        resetExposureCompensationToDefault(camera);
    //调用PhotoModule的onCameraAvailable方法
        mCurrentModule.onCameraAvailable(camera);
    } else {
        Log.v(TAG, "mCurrentModule null, not invoking onCameraAvailable");
    }
    Log.v(TAG, "invoking onChangeCamera");
    mCameraAppUI.onChangeCamera();
}

//对camera进行操作的所有配置最后都会保存在CameraSettings中,在API1中最后通过camera.applySettings(cameraSettings);
//来将CameraSettings中的配置写入camera中。
private void resetExposureCompensationToDefault(CameraAgent.CameraProxy camera) {
    // Reset the exposure compensation before handing the camera to module.
    CameraSettings cameraSettings = camera.getSettings();
    cameraSettings.setExposureCompensationIndex(0);
    camera.applySettings(cameraSettings);
}

PhotoModule.java

public void onCameraAvailable(CameraProxy cameraProxy) {
    Log.i(TAG, "onCameraAvailable");
    if (mPaused) {
        return;
    }
    mCameraDevice = cameraProxy;

    //获取一些必要功能是否支持
    initializeCapabilities();

    // Reset zoom value index.
    mZoomValue = 1.0f;
    //对焦功能
    if (mFocusManager == null) {
        initializeFocusManager();
    }
    mFocusManager.updateCapabilities(mCameraCapabilities);

    // Do camera parameter dependent initialization.
    mCameraSettings = mCameraDevice.getSettings();

    setCameraParameters(UPDATE_PARAM_ALL);
    // Set a listener which updates camera parameters based
    // on changed settings.
    SettingsManager settingsManager = mActivity.getSettingsManager();
    settingsManager.addListener(this);
    mCameraPreviewParamsReady = true;

    //开启预览界面,预览相关流程我会在下篇文章另作分析
    startPreview();

    onCameraOpened();
}

private void onCameraOpened() {
    openCameraCommon();
    initializeControlByIntent();
}

private void openCameraCommon() {
    //调用PhotoUI的onCameraOpened,主要是设置焦距,这里不展开
    mUI.onCameraOpened(mCameraCapabilities, mCameraSettings);
    if (mIsImageCaptureIntent) {
        // Set hdr plus to default: off.
        SettingsManager settingsManager = mActivity.getSettingsManager();
        settingsManager.setToDefault(SettingsManager.SCOPE_GLOBAL,
                                     Keys.KEY_CAMERA_HDR_PLUS);
    }
    //更新拍照模式
    updateSceneMode();
}

至此camera的启动流程结束。

您可能感兴趣的与本文相关内容

### Android Camera 组件启动流程详解 #### 1. 系统初始化阶段 在Linux内核启动之后,Android系统会进入用户空间并执行`init`进程。此进程中包含了多个重要步骤用于启动各种必要的守护进程和服务。对于Camera模块而言,其依赖的服务会在这一时期被创建和配置[^4]。 #### 2. Service Manager 启动 CameraService 当Zygote孵化完毕后,SystemServer开始运行,并负责加载核心应用框架以及启动关键性的后台服务。其中包括了CameraService的实例化与注册到ServiceManager中去。这一步骤确保了后续其他组件能够通过Binder机制访问Camera HAL层所提供的能力[^1]。 #### 3. 应用程序请求开启摄像头 开发者通常利用 `CameraManager` 类来获取有关可用摄像机的信息及其状态变化通知。具体来说就是调用了如下所示的方法: ```java CameraManager cameraManager = (CameraManager) context.getSystemService(Context.CAMERA_SERVICE); ``` 这段代码的作用是从系统的service manager那里取得camera service的一个代理对象,从而可以进一步操作具体的相机设备[^2]。 #### 4. 打开指定ID的物理相机设备 一旦获得了CameraManager实例,就可以尝试打开特定编号的相机单元。这里涉及到的实际API调用可能是这样的形式: ```java public static Camera openCamera(int cameraId) { try{ return Camera.open(cameraId); } catch(Exception e){ Log.e("OpenCameraError", "Failed to open camera with id:" + String.valueOf(cameraId)); return null; } } ``` 上述方法内部实现了对底层硬件抽象层(HAL)接口的调用逻辑,最终实现的是向驱动发送指令以激活相应的图像传感器和其他关联部件[^3]。 #### 5. 完成CameraSession建立 成功打开了目标相机之后,则进入了设置参数、预览流构建等一系列准备工作当中。此时已经建立了完整的从上至下的通信链路——即由Java API经JNI到达native库再到底层HAL直至实际的硬件控制层面;同时也意味着应用程序现在拥有了对该相机资源的有效使用权直到显式释放为止。
评论 3
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值