MTK Camera學(xué)習(xí)第二篇(相機(jī)的初始化)

本篇所講主要是Camera的啟動(dòng)過(guò)程,我們從onCreate方法到Camera成功open完成作如下時(shí)序圖:


camera-open.png

上圖主要包括三個(gè)部分:從java到j(luò)ni、從jni/framework到hal、從hal到驅(qū)動(dòng)(不包括驅(qū)動(dòng))。
在第一部分中的應(yīng)用層中我們可以直接得到一個(gè)java里的Camera對(duì)象,這時(shí)對(duì)此對(duì)象進(jìn)行進(jìn)一步封裝,得到一個(gè)AndroidCamera對(duì)象:

    public static ICamera openCamera(int cameraId) {
            Camera camera = null;
            if (sTrySwitchToLegacyMode > 0) {
                   // choose legacy mode in order to enter cam hal 1.0
                   camera = Camera.openLegacy(cameraId, Camera.CAMERA_HAL_API_VERSION_1_0);
               } else {
                   camera = Camera.open(cameraId);
               }
            if (null == camera) {
                Log.e(TAG, "openCamera:got null hardware camera!");
                return null;
            }
            // wrap it with ICamera
            return new AndroidCamera(camera);
    }

ICamera接口內(nèi)定義了一系列針對(duì)Camera進(jìn)行操作的方法,而AndroidCamera則實(shí)現(xiàn)了這些方法:

public interface ICamera {
    Camera getInstance();

    void addCallbackBuffer(byte[] callbackBuffer);

    void addRawImageCallbackBuffer(byte[] callbackBuffer);

    void autoFocus(AutoFocusCallback cb);

    void cancelAutoFocus();

    void cancelContinuousShot();

    void stopSmileDetection();

    void lock();

    Parameters getParameters();

    void release();

    void reconnect() throws IOException;

    void setAsdCallback(AsdCallback cb);

    void setAutoFocusMoveCallback(AutoFocusMoveCallback cb);
    void setUncompressedImageCallback(PictureCallback cb);

    void setAutoRamaCallback(AutoRamaCallback cb);

    void setAutoRamaMoveCallback(AutoRamaMoveCallback cb);

    void setJpsCallback(StereoCameraJpsCallback cb);

    void setWarningCallback(StereoCameraWarningCallback cb);

    void setMaskCallback(StereoCameraMaskCallback cb);

    void setDistanceInfoCallback(DistanceInfoCallback cb);

    void setContext(Context context);

    void setContinuousShotCallback(ContinuousShotCallback callback);

    void setContinuousShotSpeed(int speed);

    void setDisplayOrientation(int degrees);

    void setErrorCallback(ErrorCallback cb);

    void setFaceDetectionListener(FaceDetectionListener listener);

    void setFbOriginalCallback(FbOriginalCallback cb);

    void setHdrOriginalCallback(HdrOriginalCallback cb);

    void setParameters(Parameters params);

    void setPreviewCallbackWithBuffer(PreviewCallback cb);

    void setPreviewDoneCallback(ZSDPreviewDone callback);

    void setPreviewTexture(SurfaceTexture surfaceTexture) throws IOException;

    void setPreviewDisplay(SurfaceHolder holder) throws IOException;

    void setSmileCallback(SmileCallback cb);

    void setZoomChangeListener(OnZoomChangeListener listener);

    // void slowdownContinuousShot();
    void startAutoRama(int num);

    void start3DSHOT(int num);

    void stop3DSHOT(int num);

    void setPreview3DModeForCamera(boolean enable);

    void startFaceDetection();

    void startObjectTracking(int x, int y);

    void stopObjectTracking();

    void setObjectTrackingListener(ObjectTrackingListener listener);

    void startPreview();

    void startSmoothZoom(int value);

    void startSmileDetection();

    void stopAutoRama(int isMerge);

    void stopFaceDetection();

    void stopPreview();

    void setGestureCallback(GestureCallback cb);

    void startGestureDetection();

    void stopGestureDetection();

    void takePicture(ShutterCallback shutter, PictureCallback raw, PictureCallback jpeg);

    void takePicture(ShutterCallback shutter, PictureCallback raw, PictureCallback postview,
            PictureCallback jpeg);

    void unlock();

    public void setOneShotPreviewCallback(PreviewCallback cb);
    public void setMainFaceCoordinate(int x, int y);
    public void cancelMainFaceInfo();
}
public class AndroidCamera implements ICamera {...}

另外還有兩個(gè)內(nèi)部類簡(jiǎn)單看一下關(guān)系


simpleuml.png

CameraHolder的內(nèi)部類持有CameraManager內(nèi)部類CameraProxy的對(duì)象,于是可以使用CamerHolder間接調(diào)用CameraProxy這個(gè)內(nèi)部類的方法。同時(shí)CamerManager還有另一個(gè)內(nèi)部類CameraHandler可以獲取CameraProxy發(fā)出的消息。

private class CameraHandler extends Handler {
        CameraHandler(Looper looper) {
            super(looper);
        }

        @Override
        public void handleMessage(final Message msg) {
            long now = SystemClock.uptimeMillis();
            if (mCamera == null) {
                Log.e(mSubTag, "[handleMessage] camera device is null,return! ");
                return;
            }
            Log.i(mSubTag, "[handleMessage]msg.what = " + getMsgLabel(msg.what)
                    + " pending time = " + (now - msg.getWhen()) + "ms.");
            try {
                switch (msg.what) {
                case RELEASE:
                    CameraPerformanceTracker.onEvent(TAG,
                            CameraPerformanceTracker.NAME_CAMERA_RELEASE,
                            CameraPerformanceTracker.ISBEGIN);
                    mCamera.release();
                    Log.i(mSubTag, "release camera device = " + mCamera);
                    CameraPerformanceTracker.onEvent(TAG,
                            CameraPerformanceTracker.NAME_CAMERA_RELEASE,
                            CameraPerformanceTracker.ISEND);
                    mCamera = null;
                    mCameraProxy = null;
                    mFaceDetectionRunning = false;
                    return;

                case RECONNECT:
                    mReconnectException = null;
                    try {
                        mCamera.reconnect();
                        Log.i(mSubTag, "reconnect camera device = " + mCamera);
                    } catch (IOException ex) {
                        mReconnectException = ex;
                    }
                    mFaceDetectionRunning = false;
                    return;

                case UNLOCK:
                    mCamera.unlock();
                    return;

                case LOCK:
                    mCamera.lock();
                    return;
                ...
            }
         }
 }

這個(gè)mCamera是一個(gè)ICamera對(duì)象,因此最終將調(diào)用AndroidCamera的相應(yīng)方法。
在第二部分中,我們看到本地的APP使用jni與CameraService進(jìn)行connect,然后會(huì)給APP創(chuàng)建一個(gè)客戶端,這也就是我們常說(shuō)的Camera采用的CS架構(gòu)的原因了:

status_t CameraService::makeClient(const sp<CameraService>& cameraService,
        const sp<IInterface>& 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<BasicClient>* client) {
    ...
            sp<ICameraClient> tmp = static_cast<ICameraClient*>(cameraCb.get());
            *client = new CameraClient(cameraService, tmp, packageName, id, facing,
                        clientPid, clientUid, getpid(), legacyMode);
    ...
}

那么代碼怎樣進(jìn)入到Hal層的呢?我們知道,開(kāi)機(jī)后系統(tǒng)會(huì)啟動(dòng)一個(gè)CameraService,然后會(huì)執(zhí)行到onFirstRef()方法,如下:

void CameraService::onFirstRef()
{
    ALOGI("CameraService process starting");

    BnCameraService::onFirstRef();

    // Update battery life tracking if service is restarting
    BatteryNotifier& notifier(BatteryNotifier::getInstance());
    notifier.noteResetCamera();
    notifier.noteResetFlashlight();

    camera_module_t *rawModule;
    int err = hw_get_module(CAMERA_HARDWARE_MODULE_ID,
            (const hw_module_t **)&rawModule);
    if (err < 0) {
        ALOGE("Could not load camera HAL module: %d (%s)", err, strerror(-err));
        logServiceError("Could not load camera HAL module", err);
        mNumberOfCameras = 0;
        return;
    }

    mModule = new CameraModule(rawModule);
    ALOGI("Loaded \"%s\" camera module", mModule->getModuleName());
    err = mModule->init();
    if (err != OK) {
        ALOGE("Could not initialize camera HAL module: %d (%s)", err,
            strerror(-err));
        logServiceError("Could not initialize camera HAL module", err);

        mNumberOfCameras = 0;
        delete mModule;
        mModule = nullptr;
        return;
        ...
    }
  ...
}

hw_get_module根據(jù)CAMERA_HARDWARE_MODULE_ID加載相應(yīng)的so文件,具體加載過(guò)程可查看hardware.c,這個(gè)module是什么樣子的呢?如下

static
camera_module
get_camera_module()
{
    camera_module module = {
        common:{
             tag                    : HARDWARE_MODULE_TAG,
             #if (PLATFORM_SDK_VERSION >= 21)
             module_api_version     : CAMERA_MODULE_API_VERSION_2_4,
             #else
             module_api_version     : CAMERA_DEVICE_API_VERSION_1_0,
             #endif
             hal_api_version        : HARDWARE_HAL_API_VERSION,
             id                     : CAMERA_HARDWARE_MODULE_ID,
             name                   : "MediaTek Camera Module",
             author                 : "MediaTek",
             methods                : get_module_methods(),
             dso                    : NULL,
             reserved               : {0},
        },
        get_number_of_cameras       : get_number_of_cameras,
        get_camera_info             : get_camera_info,
        set_callbacks               : set_callbacks,
        get_vendor_tag_ops          : get_vendor_tag_ops,
        #if (PLATFORM_SDK_VERSION >= 21)
        open_legacy                 : open_legacy,
        #endif
        set_torch_mode              : set_torch_mode,
        init                        : NULL,
        reserved                    : {0},
    };
    return  module;
};

而此module的open方法實(shí)際即為open_device方法:

static
hw_module_methods_t*
get_module_methods()
{
    static
    hw_module_methods_t
    _methods =
    {
        open: open_device
    };

    return  &_methods;
}

做了這么多僅僅只是打開(kāi)的相機(jī)嗎?我們回到j(luò)ni一開(kāi)始的入口方法setup:

static jint android_hardware_Camera_native_setup(JNIEnv *env, jobject thiz,
    jobject weak_this, jint cameraId, jint halVersion, jstring clientPackageName)
{
    // Convert jstring to String16
    const char16_t *rawClientName = reinterpret_cast<const char16_t*>(
        env->GetStringChars(clientPackageName, NULL));
    jsize rawClientNameLen = env->GetStringLength(clientPackageName);
    String16 clientName(rawClientName, rawClientNameLen);
    env->ReleaseStringChars(clientPackageName,
                            reinterpret_cast<const jchar*>(rawClientName));

    sp<Camera> camera;
    if (halVersion == CAMERA_HAL_API_VERSION_NORMAL_CONNECT) {
        // Default path: hal version is don't care, do normal camera connect.
        camera = Camera::connect(cameraId, clientName,
                Camera::USE_CALLING_UID);
    } else {
        jint status = Camera::connectLegacy(cameraId, halVersion, clientName,
                Camera::USE_CALLING_UID, camera);
        if (status != NO_ERROR) {
            return status;
        }
    }
    ...
}

可以看到,我們得到一個(gè)sp<Camera>對(duì)象,并且建立了客戶端到服務(wù)端的連接。
我們打開(kāi)相機(jī)后還可能需要對(duì)相機(jī)進(jìn)行各種參數(shù)設(shè)置,也就是說(shuō)需要一個(gè)Parameters對(duì)象:

    private int firstOpenCamera(){
       ...
            mParameters = (mCameraDevice == null) ? null : CameraHolder.instance()
                    .getOriginalParameters(mCameraId);
            if (mCameraDevice != null && mParameters != null) {
                mCurCameraDevice = new CameraDeviceExt(mCameraActivity, mCameraDevice, mParameters,
                        mCameraId, mPreferences);
            } else {
                Log.d(TAG, "[openCamera fail],mCameraDevice:" + mCameraDevice + ",mParameters:"
                        + mParameters);
            }    
        ...
    }

這個(gè)Parameters對(duì)象的獲取我們就不再?gòu)牡讓觼?lái)分析了,簡(jiǎn)單來(lái)說(shuō)只要Camera open成功了,這個(gè)參數(shù)就可以正常獲得,當(dāng)然一些基本的相機(jī)配置也可以從Hal層進(jìn)行初始化定義,我們從Log看下使用Client端設(shè)置后得到的結(jié)果:

01-01 06:14:08.574 D/CameraClient(  353): setParameters (pid 14933) (3dnr-mode=off;3dnr-mode-values=off;afeng-max-focus-step=1023;afeng-min-focus-step=0;antibanding=auto;antibanding-values=off,50hz,60hz,auto;auto-exposure-lock-supported=true;auto-whitebalance-lock-supported=true;brightness=middle;brightness-values=low,middle,high;brightness_value=0;cap-mode-values=normal,face_beauty;capfname=/sdcard/DCIM/cap00;contrast=middle;contrast-values=low,middle,high;cshot-indicator=true;cshot-indicator-supported=true;disp-rot-supported=true;disp-rot-supported-values=true;dynamic-frame-rate=true;dynamic-frame-rate-supported=true;edge=middle;edge-values=low,middle,high;effect=none;effect-values=none,mono,negative,sepia,aqua,whiteboard,blackboard,posterize,nashville,hefe,valencia,xproll,lofi,sierra,walden;eng-mfll-e=false;eng-mfll-s=true;eng-s-shad-t=0;eng-shad-t=0;exposure-compensation=0;exposure-compensation-step=1.0;fb-enlarge-eye-max=4;fb-enlarge-eye-min=-4;fb-extreme-beauty-supported=false;fb-face-pos=-2000:-2000;fb-sharp=0;fb-sharp-max=12;fb-sharp-max-val

我們看到相機(jī)可以設(shè)置的參數(shù)非常多,本篇暫不對(duì)各個(gè)參數(shù)做詳細(xì)解釋。open成功之后又做了如下操作:

    ...
        mCameraAppUi = new CameraAppUiImpl(this);
        mCameraAppUi.createCommonView();
        initializeCommonManagers();
        mCameraAppUi.initializeCommonView();
    ...
    // Here should be lightweight functions!!!
    private void initializeCommonManagers() {
        mModePicker = new ModePicker(this);
        mFileSaver = new FileSaver(this);
        mFrameManager = new FrameManager(this);
        mModePicker.setListener(mModeChangedListener);
        mCameraAppUi.setSettingListener(mSettingListener);
        mCameraAppUi.setPickerListener(mPickerListener);
        mCameraAppUi.addFileSaver(mFileSaver);
        mPowerManager = (PowerManager) getSystemService(Context.POWER_SERVICE);
        Log.v(TAG, "getSystemService,mPowerManager =" + mPowerManager);
        // For tablet
        if (FeatureSwitcher.isSubSettingEnabled()) {
            mCameraAppUi.setSubSettingListener(mSettingListener);
        }
    }

CameraAppUiImpl也就是對(duì)整個(gè)Camera UI的實(shí)現(xiàn),前面講過(guò)整個(gè)UI由多個(gè)ManagerView做了具體的實(shí)現(xiàn),也就是這個(gè)createCommonView方法,而后執(zhí)行initializeCommonView方法的就可以將分散的UI加入一個(gè)整體進(jìn)行統(tǒng)一管理:

    public void initializeCommonView() {
        mModePicker = mCameraActivity.getModePicker();

        mCameraViewArray.put(CommonUiType.SHUTTER, new CameraViewImpl(mShutterManager));
        mCameraViewArray.put(CommonUiType.MODE_PICKER, new CameraViewImpl(mModePicker));
        mCameraViewArray.put(CommonUiType.THUMBNAIL, new CameraViewImpl(mThumbnailManager));
        mCameraViewArray.put(CommonUiType.PICKER, new CameraViewImpl(mPickerManager));
        mCameraViewArray.put(CommonUiType.INDICATOR, new CameraViewImpl(mIndicatorManager));
        mCameraViewArray.put(CommonUiType.REMAINING, new CameraViewImpl(mRemainingManager));
        mCameraViewArray.put(CommonUiType.INFO, new CameraViewImpl(mInfoManager));
        mCameraViewArray.put(CommonUiType.REVIEW, new CameraViewImpl(mReviewManager));
        mCameraViewArray.put(CommonUiType.ROTATE_PROGRESS, new CameraViewImpl(mRotateProgress));
        mCameraViewArray.put(CommonUiType.ROTATE_DIALOG, new CameraViewImpl(mRotateDialog));
        mCameraViewArray.put(CommonUiType.ZOOM, new CameraViewImpl(mZoomManager));
        mCameraViewArray.put(CommonUiType.SETTING, new CameraViewImpl(mSettingManager));
        if (mFaceBeautyEntryView != null) {
            mCameraViewArray.put(CommonUiType.FACE_BEAUTY_ENTRY, new CameraViewImpl(
                    mFaceBeautyEntryView));
        }
    }

而后AppUiImpl加入DeviceCtrl:

mCameraDeviceCtrl.setCameraAppUi(mCameraAppUi);

我們從CameraDeviceCtrl的成員變更來(lái)看,它基本包含了Camera的一切要素,由此可見(jiàn)它非常重要:

    ...
    private CameraAppUiImpl mCameraAppUi;
    private ISettingCtrl mISettingCtrl;
    private ModuleManager mModuleManager;
    
    private ICameraDeviceExt mDummyCameraDevice = new DummyCameraDevice();
    private ICameraDeviceExt mCurCameraDevice = mDummyCameraDevice;
    private ICameraDeviceExt mTopCameraDevice = mDummyCameraDevice;
    private ICameraDeviceExt mOldTopCameraDevice = mDummyCameraDevice;
    
    private RotateLayout mFocusAreaIndicator;
    private FocusManager mFocusManager;
    private CamcorderProfile mProfile;
    private CameraActor mCameraActor;
    private SurfaceTexture mSurfaceTexture;
    private SurfaceTexture mTopCamSurfaceTexture;
    private PreviewSurfaceView mSurfaceView;
    private View               mSurfaceViewCover;
    private FrameLayout mCurSurfaceViewLayout;
    private FrameLayout mLastSurfaceViewLayout;
    private CameraStartUpThread mCameraStartUpThread;
    ...

而CameraDeviceCtrl的初始化非常早(在open之前),在它的構(gòu)造函數(shù)中直接啟動(dòng)了一個(gè)線程來(lái)開(kāi)啟預(yù)覽(open之后):

    public CameraDeviceCtrl(CameraActivity activity, ComboPreferences preferences) {
        mCameraActivity = activity;
        mPreferences = preferences;
        mIsFirstStartUp = true;
        mMainHandler = new MainHandler(mCameraActivity.getMainLooper());
        mCameraStartUpThread = new CameraStartUpThread();
        mCameraStartUpThread.start();
    }
private class CameraStartUpThread extends Thread {
    ...
        @Override
        public void run() {
            ...
            applyFirstParameters();
            ...
        }

前面說(shuō)的整個(gè)open過(guò)程也都是在該線程中完成的,然后就startpreview的過(guò)程:

    private void applyFirstParameters () {
        Log.i(TAG, "applyFirstParameters");
        CameraPerformanceTracker.onEvent(TAG,
                CameraPerformanceTracker.NAME_APPLY_FIRST_PARAMS,
                CameraPerformanceTracker.ISBEGIN);
        mIsFirstOpenCamera = false;
        mMainHandler.sendEmptyMessage(MSG_SET_PREVIEW_ASPECT_RATIO);
        switchCameraPreview();
        mCurCameraDevice.setJpegRotation(mOrientation);
        mCameraAppUi.setZoomParameter();
        mCurCameraDevice.setDisplayOrientation(true);
        mCurCameraDevice.setPreviewFormat(ImageFormat.YV12);
        // Camera do not open zsd mode launched by 3rd party.
        if (!mCameraActivity.isImageCaptureIntent() && !mCameraActivity.isVideoCaptureIntent()) {
            mCurCameraDevice.getParametersExt()
            .setZSDMode(SettingUtils.getPreferenceValue(mCameraActivity,
                    mPreferences,SettingConstants.ROW_SETTING_ZSD, Util.OFF));
        }

        mCurCameraDevice.getParametersExt().set(ParametersHelper.KEY_FIRST_PREVIEW_FRAME,
                Util.FIRST_PREVIEW_BLACK_ON);
        mCurCameraDevice.applyParametersToServer();
        // for launch performance
        mMainHandler.sendEmptyMessageDelayed(MSG_REMOVE_PREVIEW_COVER, 150);
        mCameraActor.onCameraParameterReady(true);
        mCurCameraDevice.setOneShotPreviewCallback(mOneShotPreviewCallback);
        mMainHandler.sendEmptyMessage(MSG_CAMERA_PARAMETERS_READY);
        mMainHandler.sendEmptyMessage(MSG_CAMERA_PREVIEW_DONE);
    }

設(shè)置各種屬性后通知PhotoActor:

    @Override
    public void onCameraParameterReady(boolean startPreview) {
        super.onCameraParameterReady(startPreview);
        Log.i(TAG, "[onCameraParameterReady]startPreview = " + startPreview);
        mModuleManager.onCameraParameterReady(startPreview);
        if (startPreview) {
            if (!mModuleManager.startPreview(true)) {
                startPreview(true);
            }
        } 
        if (mCameraActivity.getISettingCtrl() != null && mCameraActivity.getISettingCtrl()
                          .getSettingValue(SettingConstants.KEY_SELF_TIMER) != null) {
            String seflTimer = mCameraActivity.getISettingCtrl().getSettingValue(
                   SettingConstants.KEY_SELF_TIMER);
            mSelfTimerManager.setSelfTimerDuration(seflTimer);
        }
        mCameraActivity.setCameraState(CameraActivity.STATE_IDLE);
        mHandler.removeMessages(PARAMETER_CHANGE_DONE);
        mHandler.sendEmptyMessage(PARAMETER_CHANGE_DONE);
    }
    private void startPreview(boolean needStop) {
        Log.i(TAG, "[startPreview]needStop = " + needStop);
        mCameraActivity.runOnUiThread(new Runnable() {
            public void run() {
                mCameraActivity.getFocusManager().resetTouchFocus();
            }
        });
        // continuous shot neednot stop preview after capture
        if (needStop) {
            stopPreview();
        }
        
        if (!mIsSnapshotOnIdle) {
            // If the focus mode is continuous autofocus, call cancelAutoFocus
            // to
            // resume it because it may have been paused by autoFocus call.
            if (Parameters.FOCUS_MODE_CONTINUOUS_PICTURE.equals(mCameraActivity.getFocusManager()
                    .getFocusMode())) {
                mCameraActivity.getCameraDevice().cancelAutoFocus();
                mCameraActivity.getCameraDevice().setAutoFocusMoveCallback(mAutoFocusMoveCallback);
            }
            mCameraActivity.getFocusManager().setAeLock(false); // Unlock AE and
                                                                // AWB.
            mCameraActivity.getFocusManager().setAwbLock(false);
        }
        if (isPowerDebug()) {
            if (SettingUtils.isSupported(Parameters.FOCUS_MODE_INFINITY, mCameraActivity
                    .getParameters().getSupportedFocusModes())) {
                overrideFocusMode(Parameters.FOCUS_MODE_INFINITY);
                mCameraActivity.getParameters().setFocusMode(
                        mCameraActivity.getFocusManager().getFocusMode());
                //mCameraActivity.applyParametersToServer();
                Log.i(TAG, "set debug focus     FOCUS_MODE_INFINITY ");
            }
        } else {
            setFocusParameters();
            Log.i(TAG, "[startPreview]set setFocusParameters normal");
        }
        mCameraActivity.getCameraDevice().startPreviewAsync();
        mCameraActivity.getFocusManager().onPreviewStarted();
    }

然后CameraManager使用Handler發(fā)送消息,最后調(diào)用前面說(shuō)過(guò)的ICamera對(duì)象進(jìn)行相關(guān)操作

        public void startPreviewAsync() {
            mCameraHandler.sendEmptyMessage(START_PREVIEW_ASYNC);
            waitDone();
        }

繼承PhotoActor的初始化,在它的構(gòu)造函數(shù)中,根據(jù)參數(shù)確定mode類型:

    public PhotoActor(CameraActivity context, ModuleManager moduleManager, int mode) {...}
    private void prepareCurrentMode(int newMode) {
        Log.i(TAG, "[prepareCurrentMode] mCurrentMode:" + mCurrentMode + ",newMode:" + newMode);
        mCurrentMode = newMode;
        CameraModeType mode = getCameraModeType(mCurrentMode);
        if (mode == null) {
            mode = CameraModeType.EXT_MODE_PHOTO;
        }
        mModuleManager.createMode(mode);
    }

    public void createMode(CameraModeType newMode) {
        Log.i(TAG, "[createMode],newMode:" + newMode + ",mCurrentMode:" + mCurrentMode);

        if (mCurrentMode == newMode) {
            return;
        }
        mICameraMode.close();
        mCurrentMode = newMode;
        mICameraMode = ModeFactory.getInstance().createMode(newMode, mICameraContext);
        mAdditionManager.setCurrentMode(newMode);
        mICameraMode.open();
    }

ICameraMode是一個(gè)接口,定義了各種Mode類型、Action類型以及相關(guān)操作,它的實(shí)現(xiàn)是一個(gè)抽象類CameraMode,因此這里mICameraMode.open();的具體實(shí)現(xiàn)在PhotoActor中:

    @Override
    public boolean open() {
        mAdditionManager.setListener(this);
        mAdditionManager.open(true);
        return true;
    }

跟一下這個(gè)open(true)方法,在AdditionManager中:

    public void open(boolean isMode) {
        Log.i(TAG, "[open]isMode = " + isMode);
        Vector<ICameraAddition> curAddition = mModeAddition;
        if (!isMode) {
            curAddition = mNormalAddition;
        }
        for (ICameraAddition addition : curAddition) {
            if (addition.isSupport()) {
                addition.open();
            }
        }
    }

它的實(shí)現(xiàn)也是一個(gè)抽象類CameraAddition,看下它的子類RemoteCameraAddition:

    @Override
    public void open() {
        Log.i(TAG, "[open], mIsMtkCameraApServiceLaunched:" + mIsMtkCameraApServiceLaunched);
        if (mIsMtkCameraApServiceLaunched) {
            int cameraId = mICameraDeviceManager.getCurrentCameraId();
            ICameraDevice cameraDevice = mICameraDeviceManager.getCameraDevice(cameraId);
            if (cameraDevice == null) {
                Log.i(TAG, "cameraDevice is null, return.");
                return;
            }
            Parameters parameters = cameraDevice.getParameters();
            parameters.setPreviewFormat(ImageFormat.NV21);
            if (mCameraService == null) {
                bindCameraService();
            }
            mOpened = true;
        }
    }

我們看到這里綁定了一個(gè)service,在相機(jī)啟動(dòng)后緊接著啟動(dòng)了一個(gè)service:

 private void bindCameraService() {
        Log.i(TAG, "bindCameraService()");
        mHasNotifyParameterReady = false;
        Intent intent = new Intent(mActivity, MtkCameraService.class);
        mActivity.bindService(intent, mCameraConnection, Context.BIND_AUTO_CREATE);
    }

    private void unBindCameraService() {
        Log.i(TAG, "unBindCameraService()");
        mActivity.unbindService(mCameraConnection);
    }

    private ServiceConnection mCameraConnection = new ServiceConnection() {

        @Override
        public void onServiceDisconnected(ComponentName name) {
            // TODO Auto-generated method stub
            Log.i(TAG, "CameraConnection, onServiceDisconnected()");
            mCameraService = null;
        }

        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            // TODO Auto-generated method stub
            Log.i(TAG, "CameraConnection, onServiceConnected()");
            mCameraService = (IMtkCameraService.Stub) service;
        }
    };

這個(gè)Service有什么特別的要求呢?如果它是在子線程中啟動(dòng)的,那么它至少要支持跨進(jìn)程通信,來(lái)看下:

    @Override
    public IBinder onBind(Intent intent) {
        Log.i(TAG, "intent:" + intent.getAction());
        return new MtkCameraServiceImpl();
    }

而這個(gè)MtkCameraServiceImpl也很有講究

public class MtkCameraServiceImpl extends IMtkCameraService.Stub {...}

看到這個(gè)Stub存根,我們想到了aidl,沒(méi)錯(cuò),它是一個(gè)aidl文件定義的:

interface IMtkCameraService {
    void openCamera();
    void releaseCamera();
    void capture();
    void sendMessage(in Message msg);
    void registerCallback(ICameraClientCallback cb);
    void unregisterCallback(ICameraClientCallback cb);
    void setFrameRate(int frameRate);
    // add for release
    void cameraServerExit();
    String getSupportedFeatureList();
}

我們暫不論這個(gè)service是怎樣工作的?但記住它是在這里啟動(dòng)的。
最后補(bǔ)充一張圖來(lái)說(shuō)明各種Camera相關(guān)類之間的關(guān)系(菱形箭頭表示內(nèi)部持有該類的對(duì)象,圓內(nèi)十字表示內(nèi)部類):


camerdevice.jpeg

我們看到這個(gè)關(guān)系確實(shí)比較復(fù)雜,上邊的CameraManger和AndroidCamera內(nèi)部真正持有android.hardware.Camera的對(duì)象。而CameraDeviceCtrl持有多個(gè)ICameraDeviceExt的對(duì)象,ICameraDeviceExt的實(shí)現(xiàn)位于CameraDeviceExt,而CameraDeviceExt內(nèi)部持有CameraProxy這個(gè)內(nèi)部類的對(duì)象,所以通過(guò)CameraDeviceCtrl最終可以調(diào)節(jié)真正的相機(jī)。同理,如果我們有一個(gè)ICameraDeviceManger的對(duì)象,它的先一步實(shí)現(xiàn)在CameraDeviceManagerImpl中,而CameraDeviceManagerImpl持有ICameraDeviceManager的內(nèi)部類ICameraDevice的對(duì)象,而ICameraDevice的實(shí)現(xiàn)位于CameraDeviceImpl中,同樣,CameraDeviceImpl持有CameraProxy的對(duì)象,最終同樣調(diào)用了真正的Camera對(duì)象的方法。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容