Camera2谷歌原生應用流程分析

源碼是8.0版本的,地址Android 8.0 Camera2坊罢。由于這不是一個AndroidStudio項目续担,無法直接導入AS,GitHub地址活孩。項目中包和類十分之多物遇,無法一眼看出入口Activity,所以先分析下manifest文件,找到入口Activity憾儒。

<activity
    android:name="com.android.camera.CameraActivity"
    android:clearTaskOnLaunch="true"
    android:configChanges="orientation|screenSize|keyboardHidden"
    android:label="@string/app_name"
    android:launchMode="singleTask"
    android:taskAffinity="com.android.camera.CameraActivity"
    android:theme="@style/Theme.Camera"
    android:windowSoftInputMode="stateAlwaysHidden|adjustPan">        
    <intent-filter>
        <action android:name="android.media.action.STILL_IMAGE_CAMERA" />

        <category android:name="android.intent.category.DEFAULT" />
    </intent-filter>
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />

        <category android:name="android.intent.category.DEFAULT" />
    </intent-filter>

    <meta-data
        android:name="com.android.keyguard.layout"
        android:resource="@layout/keyguard_widget" />
</activity>

<activity-alias
    android:name="com.android.camera.CameraLauncher"
    android:label="@string/app_name"
    android:targetActivity="com.android.camera.CameraActivity">
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />

        <category android:name="android.intent.category.DEFAULT" />
        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
</activity-alias>

<activity
    android:name="com.android.camera.PermissionsActivity"
    android:excludeFromRecents="true"
    android:label="@string/app_name"
    android:parentActivityName="com.android.camera.CameraActivity">
    <meta-data
        android:name="android.support.PARENT_ACTIVITY"
        android:value="com.android.camera.CameraActivity" />
</activity>

<activity
    android:name="com.android.camera.CaptureActivity"
    android:configChanges="orientation|screenSize|keyboardHidden"
    android:label="@string/app_name"
    android:theme="@style/Theme.Camera"
    android:windowSoftInputMode="stateAlwaysHidden|adjustPan">
    <intent-filter>
        <action android:name="android.media.action.IMAGE_CAPTURE" />

        <category android:name="android.intent.category.DEFAULT" />
    </intent-filter>
</activity> <!-- Video camera and capture use the Camcorder label and icon. -->

<activity-alias
    android:name="com.android.camera.VideoCamera"
    android:label="@string/video_camera_label"
    android:targetActivity="com.android.camera.CaptureActivity">
    <intent-filter>
        <action android:name="android.media.action.VIDEO_CAMERA" />

        <category android:name="android.intent.category.DEFAULT" />
    </intent-filter>
    <intent-filter>
        <action android:name="android.media.action.VIDEO_CAPTURE" />

        <category android:name="android.intent.category.DEFAULT" />
    </intent-filter>
</activity-alias>

<activity
    android:name="com.android.camera.SecureCameraActivity"
    android:clearTaskOnLaunch="true"
    android:configChanges="orientation|screenSize|keyboardHidden"
    android:excludeFromRecents="true"
    android:label="@string/app_name"
    android:taskAffinity="com.android.camera.SecureCameraActivity"
    android:theme="@style/Theme.SecureCamera"
    android:windowSoftInputMode="stateAlwaysHidden|adjustPan">
    <intent-filter>
        <action android:name="android.media.action.STILL_IMAGE_CAMERA_SECURE" />

        <category android:name="android.intent.category.DEFAULT" />
    </intent-filter>
    <intent-filter>
        <action android:name="android.media.action.IMAGE_CAPTURE_SECURE" />

        <category android:name="android.intent.category.DEFAULT" />
    </intent-filter>

    <meta-data
        android:name="com.android.keyguard.layout"
        android:resource="@layout/keyguard_widget" />
</activity>

<activity
    android:name="com.android.camera.settings.CameraSettingsActivity"
    android:configChanges="keyboardHidden|orientation|screenSize"
    android:label="@string/mode_settings"
    android:theme="@style/Theme.CameraSettings">
</activity>

從上我們可以知道應用的啟動Activity為CameraActivity询兴,PermissionsActivity用來做權限請求,CameraSettingsActivity用來做設置頁面起趾,而其它的Activity要么為CameraActivity的別名诗舰,要么就是直接繼承了CameraActivity且什么都沒做,也就是說這個應用的主要工作都是在CameraActivity中完成训裆。重點分析CameraActivity眶根。

public class CameraActivity extends QuickActivity
        implements AppController, CameraAgent.CameraOpenCallback,
        ShareActionProvider.OnShareTargetSelectedListener {
}

可以看到CameraActivity繼承并實現(xiàn)了很多東西蜀铲,先看它的父類QuickActivity。在QuickActivity中有句注釋:

The KeyguardManager service can be queried to determine which state we are in.
If started from the lock screen, the activity may be quickly started,
resumed, paused, stopped, and then started and resumed again. This is
problematic for launch time from the lock screen because we typically open the
camera in onResume() and close it in onPause(). These camera operations take
a long time to complete. To workaround it, this class filters out
high-frequency onResume()->onPause() sequences if the KeyguardManager
indicates that we have started from the lock screen.

大意就是說這個類是為了解決從鎖屏啟動相機會重復調用兩遍onResume()的bug属百。這個類是個虛擬類定義了以下方法給子類重寫记劝,一看就知道對應了Activity的生命周期。

/**
     * Subclasses should override this in place of {@link Activity#onNewIntent}.
     */
    protected void onNewIntentTasks(Intent newIntent) {
    }

    /**
     * Subclasses should override this in place of {@link Activity#onCreate}.
     */
    protected void onCreateTasks(Bundle savedInstanceState) {
    }

    /**
     * Subclasses should override this in place of {@link Activity#onStart}.
     */
    protected void onStartTasks() {
    }

    /**
     * Subclasses should override this in place of {@link Activity#onResume}.
     */
    protected void onResumeTasks() {
    }

    /**
     * Subclasses should override this in place of {@link Activity#onPause}.
     */
    protected void onPauseTasks() {
    }

    /**
     * Subclasses should override this in place of {@link Activity#onStop}.
     */
    protected void onStopTasks() {
    }

    /**
     * Subclasses should override this in place of {@link Activity#onDestroy}.
     */
    protected void onDestroyTasks() {
    }

接下來我們我們從CameraActivity的onCreateTasks()開始族扰,這也就是onCreate()(代碼有精簡)

1.mOneCameraOpener = OneCameraModule.provideOneCameraOpener(
                    mFeatureConfig,
                    mAppContext,
                    mActiveCameraDeviceTracker,
                    ResolutionUtil.getDisplayMetrics(this));
2.mOneCameraManager = OneCameraModule.provideOneCameraManager();

3.mModuleManager = new ModuleManagerImpl();

4.ModulesInfo.setupModules(mAppContext, mModuleManager, mFeatureConfig);

可以看到是一系列對象的新建隆夯,我們看看最后一句代碼干了什么

/**ModulesInfo.java**/
public static void setupModules(Context context, ModuleManager moduleManager,
            OneCameraFeatureConfig config) {
        Resources res = context.getResources();
        int photoModuleId = context.getResources().getInteger(R.integer.camera_mode_photo);
        registerPhotoModule(moduleManager, photoModuleId, SettingsScopeNamespaces.PHOTO,
                config.isUsingCaptureModule());
        moduleManager.setDefaultModuleIndex(photoModuleId);
        registerVideoModule(moduleManager, res.getInteger(R.integer.camera_mode_video),
                SettingsScopeNamespaces.VIDEO);
        if (PhotoSphereHelper.hasLightCycleCapture(context)) {
            registerWideAngleModule(moduleManager, res.getInteger(R.integer.camera_mode_panorama),
                    SettingsScopeNamespaces.PANORAMA);
            registerPhotoSphereModule(moduleManager,
                    res.getInteger(R.integer.camera_mode_photosphere),
                    SettingsScopeNamespaces.PANORAMA);
        }
        if (RefocusHelper.hasRefocusCapture(context)) {
            registerRefocusModule(moduleManager, res.getInteger(R.integer.camera_mode_refocus),
                    SettingsScopeNamespaces.REFOCUS);
        }
        if (GcamHelper.hasGcamAsSeparateModule(config)) {
            registerGcamModule(moduleManager, res.getInteger(R.integer.camera_mode_gcam),
                    SettingsScopeNamespaces.PHOTO,
                    config.getHdrPlusSupportLevel(OneCamera.Facing.BACK));
        }
        int imageCaptureIntentModuleId = res.getInteger(R.integer.camera_mode_capture_intent);
        registerCaptureIntentModule(moduleManager, imageCaptureIntentModuleId,
                SettingsScopeNamespaces.PHOTO, config.isUsingCaptureModule());
    }
 private static void registerPhotoModule(ModuleManager moduleManager, final int moduleId,
            final String namespace, final boolean enableCaptureModule) {
        moduleManager.registerModule(new ModuleManager.ModuleAgent() {

            @Override
            public int getModuleId() {
                return moduleId;
            }

            @Override
            public boolean requestAppForCamera() {
                // The PhotoModule requests the old app camere, while the new
                // capture module is using OneCamera. At some point we'll
                // refactor all modules to use OneCamera, then the new module
                // doesn't have to manage it itself.
                return !enableCaptureModule;
            }

            @Override
            public String getScopeNamespace() {
                return namespace;
            }

            @Override
            public ModuleController createModule(AppController app, Intent intent) {
                Log.v(TAG, "EnableCaptureModule = " + enableCaptureModule);
                return enableCaptureModule ? new CaptureModule(app) : new PhotoModule(app);
            }
        });
    }

可以看到就是向moduleManager中注冊了很多Module,從名字看這些Module對應著不同的功能,比如拍照别伏、錄像蹄衷、廣角、全景厘肮、重聚焦愧口。看似是注冊各種Module类茂,但是moduleManager中并沒有持有這些Module的對象耍属,而是持有了ModuleManager.ModuleAgent這個回調」欤可以看到在registerPhotoModule()后就把這個Module設置為了默認厚骗。回到CameraActivity

/**CameraActivity.onCreateTasks()**/
 mCameraAppUI = new CameraAppUI(this,
                (MainActivityLayout) findViewById(R.id.activity_root_view), isCaptureIntent());
 setModuleFromModeIndex(getModeIndex());
 mCurrentModule.init(this, isSecureCamera(), isCaptureIntent());
 mCameraAppUI.prepareModuleUI();

這里第一句話去創(chuàng)建了UI兢哭,我們重點關心流程领舰,視圖暫且不討論。
getModeIndex()方法如下:

/**
     * Get the current mode index from the Intent or from persistent
     * settings.
     */
    private int getModeIndex() {
        int modeIndex = -1;
        int photoIndex = getResources().getInteger(R.integer.camera_mode_photo);
        int videoIndex = getResources().getInteger(R.integer.camera_mode_video);
        int gcamIndex = getResources().getInteger(R.integer.camera_mode_gcam);
        int captureIntentIndex =
                getResources().getInteger(R.integer.camera_mode_capture_intent);
        String intentAction = getIntent().getAction();
        if (MediaStore.INTENT_ACTION_VIDEO_CAMERA.equals(intentAction)
                || MediaStore.ACTION_VIDEO_CAPTURE.equals(intentAction)) {
            modeIndex = videoIndex;
        } else if (MediaStore.ACTION_IMAGE_CAPTURE.equals(intentAction)
                || MediaStore.ACTION_IMAGE_CAPTURE_SECURE.equals(intentAction)) {
            // Capture intent.
            modeIndex = captureIntentIndex;
        } else if (MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA.equals(intentAction)
                ||MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA_SECURE.equals(intentAction)
                || MediaStore.ACTION_IMAGE_CAPTURE_SECURE.equals(intentAction)) {
            modeIndex = mSettingsManager.getInteger(SettingsManager.SCOPE_GLOBAL,
                Keys.KEY_CAMERA_MODULE_LAST_USED);

            // For upgraders who have not seen the aspect ratio selection screen,
            // we need to drop them back in the photo module and have them select
            // aspect ratio.
            // TODO: Move this to SettingsManager as an upgrade procedure.
            if (!mSettingsManager.getBoolean(SettingsManager.SCOPE_GLOBAL,
                    Keys.KEY_USER_SELECTED_ASPECT_RATIO)) {
                modeIndex = photoIndex;
            }
        } else {
            // If the activity has not been started using an explicit intent,
            // read the module index from the last time the user changed modes
            modeIndex = mSettingsManager.getInteger(SettingsManager.SCOPE_GLOBAL,
                                                    Keys.KEY_STARTUP_MODULE_INDEX);
            if ((modeIndex == gcamIndex &&
                    !GcamHelper.hasGcamAsSeparateModule(mFeatureConfig)) || modeIndex < 0) {
                modeIndex = photoIndex;
            }
        }
        return modeIndex;
    }

這里如果CameraActivity如果沒有被一個明確的Intent啟動迟螺,則將打開上次的module冲秽。我們是第一次啟動,默認為photoIndex矩父。
再來看setModuleFromModeIndex()方法:

/**CameraActivity**/
private void setModuleFromModeIndex(int modeIndex) {
        ModuleAgent agent = mModuleManager.getModuleAgent(modeIndex);
        if (agent == null) {
            return;
        }
        if (!agent.requestAppForCamera()) {
            mCameraController.closeCamera(true);
        }
        mCurrentModeIndex = agent.getModuleId();
        mCurrentModule = (CameraModule) agent.createModule(this, getIntent());
    }

剛才我們已經(jīng)向mDoduleManager中注冊了很多ModuleAgent锉桑,這里我們的參數(shù)為上面默認的photoIndex,則得到的agent就是

ModuleManager.ModuleAgent() {

    @Override
    public int getModuleId() {
        return moduleId;
    }

    @Override
    public boolean requestAppForCamera() {
        // The PhotoModule requests the old app camere, while the new
        // capture module is using OneCamera. At some point we'll
        // refactor all modules to use OneCamera, then the new module
        // doesn't have to manage it itself.
        return !enableCaptureModule;
    }

    @Override
    public String getScopeNamespace() {
        return namespace;
    }

    @Override
    public ModuleController createModule(AppController app, Intent intent) {
        Log.v(TAG, "EnableCaptureModule = " + enableCaptureModule);
        return enableCaptureModule ? new CaptureModule(app) : new PhotoModule(app);
    }
}

mCurrentModule = (CameraModule) agent.createModule(this, getIntent());返回CaptureModule還是PhotoModule則取決于enableCaptureModule窍株,這個參數(shù)的實參為config.isUsingCaptureModule()民轴,而config來自于CameraActivity中的mFeatureConfig。我們向上看看這個參數(shù)

/**CameraActivity.java**/
mFeatureConfig = OneCameraFeatureConfigCreator.createDefault(getContentResolver(),
                getServices().getMemoryManager());

/**OneCameraFeatureConfigCreator.java**/
public static OneCameraFeatureConfig createDefault(ContentResolver contentResolver,
            MemoryManager memoryManager) {
        // Enable CaptureModule on all M devices.
        boolean useCaptureModule = true;
        Log.i(TAG, "CaptureModule? " + useCaptureModule);

        // HDR+ has multiple levels of support.
        HdrPlusSupportLevel hdrPlusSupportLevel =
                GcamHelper.determineHdrPlusSupportLevel(contentResolver, useCaptureModule);
        return new OneCameraFeatureConfig(useCaptureModule,
                buildCaptureModuleDetector(contentResolver),
                hdrPlusSupportLevel,
                memoryManager.getMaxAllowedNativeMemoryAllocation(),
                GservicesHelper.getMaxAllowedImageReaderCount(contentResolver));
    }

/**OneCameraFeatureConfig**/
OneCameraFeatureConfig(boolean useCaptureModule,
            Function<CameraCharacteristics, CaptureSupportLevel> captureModeDetector,
            HdrPlusSupportLevel hdrPlusSupportLevel,
            int maxMemoryMB,
            int maxAllowedImageReaderCount) {
        mUseCaptureModule = useCaptureModule;
        mCaptureModeDetector = captureModeDetector;
        mHdrPlusSupportLevel = hdrPlusSupportLevel;
        mMaxMemoryMB = maxMemoryMB;
        mMaxAllowedImageReaderCount = maxAllowedImageReaderCount;
    }
    public boolean isUsingCaptureModule() {
        return mUseCaptureModule;
    }

雖然經(jīng)過了層層包裝球订,但是我們可以看到默認是true后裸,我們依照默認分析下去。也就是最終返回的是CaptureModule對象辙售。簡化后就是mCurrentModule = new CaptureModule(CameraActivity.this);
這里會引起CaptureModule的初始化轻抱,我們來看看它的初始化。

public CaptureModule(AppController appController) {
        this(appController, false);
    }

    /** Constructs a new capture module. */
    public CaptureModule(AppController appController, boolean stickyHdr) {
        super(appController);
        Profile guard = mProfiler.create("new CaptureModule").start();
        mPaused = true;
        mMainThread = MainThread.create();
        mAppController = appController;
        mContext = mAppController.getAndroidContext();
        mSettingsManager = mAppController.getSettingsManager();
        mStickyGcamCamera = stickyHdr;
        mLocationManager = mAppController.getLocationManager();
        mPreviewTransformCalculator = new PreviewTransformCalculator(
                mAppController.getOrientationManager());

        mBurstController = BurstFacadeFactory.create(mContext,
                new OrientationLockController() {
                    @Override
                    public void unlockOrientation() {
                        mAppController.getOrientationManager().unlockOrientation();
                    }

                        @Override
                    public void lockOrientation() {
                        mAppController.getOrientationManager().lockOrientation();
                    }
                },
                new BurstReadyStateChangeListener() {
                   @Override
                    public void onBurstReadyStateChanged(boolean ready) {
                        // TODO: This needs to take into account the state of
                        // the whole system, not just burst.
                       onReadyStateChanged(false);
                    }
                });
        mMediaActionSound = new MediaActionSound();
        guard.stop();
    }

這里最重要的就是mAppController = appController旦部,在CaptureActivity中有一個AppController的引用指向了CameraActivity祈搜。
至此,我們成功的給CameraAcitivity中的mCurrentModule完成了初始化士八,它是一個CaptureModule對象容燕,而且mCurrentModule中又有一個指向CameraActivity的引用。
接下來我們返回到CameraActivity中婚度,來看下一句mCurrentModule.init(this, isSecureCamera(), isCaptureIntent());這里后兩個參數(shù)在方法中根本沒有用到蘸秘,不知道這里什么意思。方法實現(xiàn):

/**CaptureModule.init() 有精簡 **/
public void init(CameraActivity activity, boolean isSecureCamera, boolean isCaptureIntent) {
        mCameraHandler = new Handler(thread.getLooper());
        mOneCameraOpener = mAppController.getCameraOpener();
        mOneCameraManager = OneCameraModule.provideOneCameraManager();
        mUI = new CaptureModuleUI(activity, mAppController.getModuleLayoutRoot(), mUIListener);
        mAppController.setPreviewStatusListener(mPreviewStatusListener);
}

mAppController.setPreviewStatusListener(mPreviewStatusListener);這句話最為重要蝗茁,我們知道m(xù)AppController是CameraActivity的引用醋虏,來看CameraActivity的這個方法

/**CameraActivity**/
public void setPreviewStatusListener(PreviewStatusListener previewStatusListener) {
        mCameraAppUI.setPreviewStatusListener(previewStatusListener);
    }

也就是說這個PreviewStatusListener最終設置給了mCameraAppUI,這個Listener是在CaptureModule中新建的哮翘。

/**CaptureModule**/
private final PreviewStatusListener mPreviewStatusListener = new PreviewStatusListener() {
        @Override
        public void onPreviewLayoutChanged(View v, int left, int top, int right,
                int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) {
            int width = right - left;
            int height = bottom - top;
            updatePreviewTransform(width, height, false);
        }

        @Override
        public boolean shouldAutoAdjustTransformMatrixOnLayout() {
            return USE_AUTOTRANSFORM_UI_LAYOUT;
        }

        @Override
        public void onPreviewFlipped() {
            // Do nothing because when preview is flipped, TextureView will lay
            // itself out again, which will then trigger a transform matrix
            // update.
        }

        @Override
        public GestureDetector.OnGestureListener getGestureListener() {
            return new GestureDetector.SimpleOnGestureListener() {
                @Override
                public boolean onSingleTapUp(MotionEvent ev) {
                    Point tapPoint = new Point((int) ev.getX(), (int) ev.getY());
                    Log.v(TAG, "onSingleTapUpPreview location=" + tapPoint);
                    if (!mCameraCharacteristics.isAutoExposureSupported() &&
                          !mCameraCharacteristics.isAutoFocusSupported()) {
                        return false;
                    }
                    startActiveFocusAt(tapPoint.x, tapPoint.y);
                    return true;
                }
            };
        }

        @Override
        public View.OnTouchListener getTouchListener() {
            return null;
        }

        @Override
        public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
            Log.d(TAG, "onSurfaceTextureAvailable");
            // Force to re-apply transform matrix here as a workaround for
            // b/11168275
            updatePreviewTransform(width, height, true);
            synchronized (mSurfaceTextureLock) {
                mPreviewSurfaceTexture = surface;
            }
            reopenCamera();
        }

        @Override
        public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
            Log.d(TAG, "onSurfaceTextureDestroyed");
            synchronized (mSurfaceTextureLock) {
                mPreviewSurfaceTexture = null;
            }
            closeCamera();
            return true;
        }

        @Override
        public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
            Log.d(TAG, "onSurfaceTextureSizeChanged");
            updatePreviewBufferSize();
        }

        @Override
        public void onSurfaceTextureUpdated(SurfaceTexture surface) {
            if (mState == ModuleState.UPDATE_TRANSFORM_ON_NEXT_SURFACE_TEXTURE_UPDATE) {
                Log.d(TAG, "onSurfaceTextureUpdated --> updatePreviewTransform");
                mState = ModuleState.IDLE;
                CameraAppUI appUI = mAppController.getCameraAppUI();
                updatePreviewTransform(appUI.getSurfaceWidth(), appUI.getSurfaceHeight(), true);
            }
        }
    };

注意這個回調颈嚼,很重要。我們還是回到CameraActivity饭寺,接下來的一句的是mCameraAppUI.prepareModuleUI();

/**CameraAppUI.prepareModuleUI() 有刪減**/
 public void prepareModuleUI() {
        mController.getSettingsManager().addListener(this);
        mModuleUI = (FrameLayout) mCameraRootView.findViewById(R.id.module_layout);
        mTextureView = (TextureView) mCameraRootView.findViewById(R.id.preview_content);
        mTextureViewHelper = new TextureViewHelper(mTextureView, mCaptureLayoutHelper,
                mController.getCameraProvider(), mController);
        mTextureViewHelper.setSurfaceTextureListener(this);
        mTextureViewHelper.setOnLayoutChangeListener(mPreviewLayoutChangeListener);
}

這里的TextureView便是我們用來預覽的界面阻课,然后包裝成了一個TextureViewHelper對象,并且給它設置了一個SurfaceTextureListener的監(jiān)聽事件,

/**CameraAppUI.surfaceTextureListener**/
@Override
    public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
        mSurface = surface;
        mSurfaceWidth = width;
        mSurfaceHeight = height;
        Log.v(TAG, "SurfaceTexture is available");
        if (mPreviewStatusListener != null) {
            mPreviewStatusListener.onSurfaceTextureAvailable(surface, width, height);
        }
        enableModeOptions();
    }

    @Override
    public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
        mSurface = surface;
        mSurfaceWidth = width;
        mSurfaceHeight = height;
        if (mPreviewStatusListener != null) {
            mPreviewStatusListener.onSurfaceTextureSizeChanged(surface, width, height);
        }
    }

    @Override
    public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
        mSurface = null;
        Log.v(TAG, "SurfaceTexture is destroyed");
        if (mPreviewStatusListener != null) {
            return mPreviewStatusListener.onSurfaceTextureDestroyed(surface);
        }
        return false;
    }

    @Override
    public void onSurfaceTextureUpdated(SurfaceTexture surface) {
        mSurface = surface;
        if (mPreviewStatusListener != null) {
            mPreviewStatusListener.onSurfaceTextureUpdated(surface);
        }
        // Do not show the first preview frame. Due to the bug b/20724126, we need to have
        // a WAR to request a preview frame followed by 5-frame ZSL burst before the repeating
        // preview and ZSL streams. Need to hide the first preview frame since it is janky.
        // We do this only for L, Nexus 6 and Haleakala.
        if (mModeCoverState == COVER_WILL_HIDE_AFTER_NEXT_TEXTURE_UPDATE) {
            mModeCoverState = COVER_WILL_HIDE_AT_NEXT_TEXTURE_UPDATE;
        } else if (mModeCoverState == COVER_WILL_HIDE_AT_NEXT_TEXTURE_UPDATE){
            Log.v(TAG, "hiding cover via onSurfaceTextureUpdated");
            CameraPerformanceTracker.onEvent(CameraPerformanceTracker.FIRST_PREVIEW_FRAME);
            hideModeCover();
        }
    }

進入TextureViewHelper我們可以知道到TextureView準備好了后會回調onSurfaceTextureAvailable()我們看看這個方法

/**TextureViewHelper**/
@Override
    public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
        // Workaround for b/11168275, see b/10981460 for more details
        if (mWidth != 0 && mHeight != 0) {
            // Re-apply transform matrix for new surface texture
            updateTransform();
        }
        if (mSurfaceTextureListener != null) {
            mSurfaceTextureListener.onSurfaceTextureAvailable(surface, width, height);
        }
    }

也就是說TextureView可用時艰匙,回調了mSurfaceTextureListener.onSurfaceTextureAvailable(surface, width, height);
而這個mSurfaceTextureListener便是上面那個CameraAppUI中實現(xiàn)的SurfaceTextureViewListener限煞,至此我們知道了到TextureView可用時回調了如下方法

/**CameraAppUI.surfaceTextureListener**/
@Override
public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
    mSurface = surface;
    mSurfaceWidth = width;
    mSurfaceHeight = height;
    Log.v(TAG, "SurfaceTexture is available");
    if (mPreviewStatusListener != null) {
        mPreviewStatusListener.onSurfaceTextureAvailable(surface, width, height);
    }
    enableModeOptions();
}

而這里的mPreviewStatusListener便是那個CaptureModule中的實現(xiàn),所以TextureView可用時员凝,接著會回調

/**CaptureModule**/
@Override
public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
    Log.d(TAG, "onSurfaceTextureAvailable");
    // Force to re-apply transform matrix here as a workaround for
    // b/11168275
    updatePreviewTransform(width, height, true);
    synchronized (mSurfaceTextureLock) {
        mPreviewSurfaceTexture = surface;
    }
    reopenCamera();
}

至此我們便清楚了署驻,當TextureView可用時最終調用了CaptureModule.reopenCamera()方法。一路調用下去直到mOneCameraOpener.open()健霹,我們看下這個方法

/**CaptureModule.openCameraAndStartPreview()-->mOneCameraOpener.open() (有刪減)**/
mOneCameraOpener.open(cameraId, captureSetting, mCameraHandler, mainThread,
  imageRotationCalculator, mBurstController, mSoundPlayer,
  new OpenCallback() {
      @Override
      public void onFailure() {
          
      }

      @Override
      public void onCameraClosed() {
         
      }

      @Override
      public void onCameraOpened(@Nonnull final OneCamera camera) {
          camera.startPreview(new Surface(getPreviewSurfaceTexture()),
                new CaptureReadyCallback() {
                    @Override
                    public void onSetupFailed() {
                        
                    }

                    @Override
                    public void onReadyForCapture() {
                        mCameraOpenCloseLock.release();
                        mMainThread.execute(new Runnable() {
                            @Override
                            public void run() {
                                Log.d(TAG, "Ready for capture.");
                                if (mCamera == null) {
                                    Log.d(TAG, "Camera closed, aborting.");
                                    return;
                                }
                                onPreviewStarted();
                                onReadyStateChanged(true);
                                mCamera.setReadyStateChangedListener(
                                      CaptureModule.this);                      
                                mUI.initializeZoom(mCamera.getMaxZoom());
                                mCamera.setFocusStateListener(CaptureModule.this);
                            }
                        });
                    }
                });
      }
  }, mAppController.getFatalErrorHandler());

記住這個OpenCallback()的回調我們來看看它在哪里被回調了硕舆。這個mOneCameraOpener是從CameraAcitvity中得到的,我們看看它的來歷

/** CameraActivity**/
mOneCameraOpener = OneCameraModule.provideOneCameraOpener(
                    mFeatureConfig,
                    mAppContext,
                    mActiveCameraDeviceTracker,
                    ResolutionUtil.getDisplayMetrics(this));

這里一路跟蹤下去骤公,我們很容易看到mOneCameraOpener就是Camera2OneCameraOpenerImpl類的一個對象抚官,我們看看他的open方法

/**Camera2OneCameraOpenerImpl.open()**/
@Override
@Override
public void open(
    final CameraId cameraKey,
    final OneCameraCaptureSetting captureSetting,
    final Handler handler,
    final MainThread mainThread,
    final ImageRotationCalculator imageRotationCalculator,
    final BurstFacade burstController,
    final SoundPlayer soundPlayer,
    final OpenCallback openCallback,
    final FatalErrorHandler fatalErrorHandler) {
    
    mCameraManager.openCamera(cameraKey.getValue(), new CameraDevice.StateCallback() {
        private boolean isFirstCallback = true;

        @Override
        public void onDisconnected(CameraDevice device) {
        
        }

        @Override
        public void onClosed(CameraDevice device) {
            
        }

        @Override
        public void onError(CameraDevice device, int error) {
            
        }

        @Override
        public void onOpened(CameraDevice device) {
            if (isFirstCallback) {
                isFirstCallback = false;
                try {
                    CameraCharacteristics characteristics = mCameraManager
                            .getCameraCharacteristics(device.getId());
                    OneCamera oneCamera = OneCameraCreator.create(
                                        device,
                                        characteristics,
                                        mFeatureConfig,
                                        captureSetting,
                                        mDisplayMetrics,
                                        mContext,
                                        mainThread,
                                        imageRotationCalculator,
                                        burstController,
                                        soundPlayer, fatalErrorHandler);

                    if (oneCamera != null) {
                        openCallback.onCameraOpened(oneCamera);
                    } else {
                        Log.d(TAG, "Could not construct a OneCamera object!");
                        openCallback.onFailure();
                    }
                } catch (CameraAccessException e) {
                    Log.d(TAG, "Could not get camera characteristics", e);
                    openCallback.onFailure();
                } catch (OneCameraAccessException e) {
                    Log.d(TAG, "Could not create OneCamera", e);
                    openCallback.onFailure();
                }
            }
        }
    }, handler);
}

到這里德崭,我們終于看到了相機的打開哮洽,這一段的時序圖如下
應用打開相機時序圖.jpg

相機打開后會回調onOpened(),可以看到這里首先拿到了打開的相機的屬性值亚隅,然后創(chuàng)建了一個OneCamera對象洒试,我們先研究下oneCamera對象的創(chuàng)建過程倍奢。創(chuàng)建的時候我們傳入了很多參數(shù),這些參數(shù)有的來自于Camera2OneCameraOpenerImpl對象創(chuàng)建時傳入的垒棋,有的來自于調用方法時傳入卒煞。Camera2OneCameraOpenerImpl的對象創(chuàng)建于CameraActivity,而調用方是CaptureModule叼架。oneCamera的創(chuàng)建一路看下去畔裕,我們會發(fā)現(xiàn)它經(jīng)過了OneCameraCreator衣撬、SimpleOneCameraFactory、InitializedOneCameraFactory扮饶、GenericOneCameraImpl具练,每一個類或是對前面?zhèn)鬟f下來的參數(shù)進行了一層包裝、或是新建了一些新的對象傳遞下去甜无,我們需要注意的參數(shù)有下幾個

/**InitializedOneCameraFactory**/
final CaptureSessionCreator captureSessionCreator = new CaptureSessionCreator(device,
        cameraHandler);

PreviewStarter mPreviewStarter = new PreviewStarter(outputSurfaces,
        captureSessionCreator,
        new PreviewStarter.CameraCaptureSessionCreatedListener() {
            @Override
            public void onCameraCaptureSessionCreated(CameraCaptureSessionProxy session,
                    Surface previewSurface) {
                CameraStarter.CameraControls controls = cameraStarter.startCamera(
                        new Lifetime(lifetime),
                        session, previewSurface,
                        zoomState, metadataCallback, readyState);
                mPictureTaker.set(controls.getPictureTaker());
                mManualAutoFocus.set(controls.getManualAutoFocus());
            }
        });
/**SimpleOneCameraFactory**/
CameraStarter cameraStarter = new CameraStarter() {
    @Override
    public CameraControls startCamera(Lifetime cameraLifetime,
            CameraCaptureSessionProxy cameraCaptureSession,
            Surface previewSurface,
            Observable<Float> zoomState,
            Updatable<TotalCaptureResultProxy> metadataCallback,
            Updatable<Boolean> readyState) {
        // Create the FrameServer from the CaptureSession.
        FrameServerFactory frameServerComponent = new FrameServerFactory(
                new Lifetime(cameraLifetime), cameraCaptureSession, new HandlerFactory());

        CameraCommandExecutor cameraCommandExecutor = new CameraCommandExecutor(
                Loggers.tagFactory(),
                new Provider<ExecutorService>() {
                    @Override
                    public ExecutorService get() {
                        // Use a dynamically-expanding thread pool to
                        // allow any number of commands to execute
                        // simultaneously.
                        return Executors.newCachedThreadPool();
                    }
                });

        // Create the shared image reader.
        SharedImageReaderFactory sharedImageReaderFactory =
                new SharedImageReaderFactory(new Lifetime(cameraLifetime), imageReader,
                        new HandlerFactory());
        Updatable<Long> globalTimestampCallback =
                sharedImageReaderFactory.provideGlobalTimestampQueue();
        ManagedImageReader managedImageReader =
                sharedImageReaderFactory.provideSharedImageReader();

        // Create the request builder used by all camera operations.
        // Streams, ResponseListeners, and Parameters added to
        // this will be applied to *all* requests sent to the camera.
        RequestTemplate rootBuilder = new RequestTemplate
                (new CameraDeviceRequestBuilderFactory(device));
        // The shared image reader must be wired to receive every
        // timestamp for every image (including the preview).
        rootBuilder.addResponseListener(
                ResponseListeners.forTimestamps(globalTimestampCallback));
        rootBuilder.addStream(new SimpleCaptureStream(previewSurface));
        rootBuilder.addResponseListener(ResponseListeners.forFinalMetadata(
                metadataCallback));

        FrameServer ephemeralFrameServer =
              frameServerComponent.provideEphemeralFrameServer();

        // Create basic functionality (zoom, AE, AF).
        BasicCameraFactory basicCameraFactory = new BasicCameraFactory(new Lifetime
                (cameraLifetime),
                characteristics,
                ephemeralFrameServer,
                rootBuilder,
                cameraCommandExecutor,
                new BasicPreviewCommandFactory(ephemeralFrameServer),
                flashSetting,
                exposureSetting,
                zoomState,
                hdrSceneSetting,
                CameraDevice.TEMPLATE_PREVIEW);

        // Register the dynamic updater via orientation supplier
        rootBuilder.setParam(CaptureRequest.JPEG_ORIENTATION,
                mImageRotationCalculator.getSupplier());

        if (GservicesHelper.isJankStatisticsEnabled(AndroidContext.instance().get()
              .getContentResolver())) {
            rootBuilder.addResponseListener(
                  new FramerateJankDetector(Loggers.tagFactory(),
                        UsageStatistics.instance()));
        }

        RequestBuilder.Factory meteredZoomedRequestBuilder =
                basicCameraFactory.provideMeteredZoomedRequestBuilder();

        // Create the picture-taker.
        PictureTaker pictureTaker;
        if (supportLevel == OneCameraFeatureConfig.CaptureSupportLevel.LEGACY_JPEG) {
            pictureTaker = new LegacyPictureTakerFactory(imageSaverBuilder,
                    cameraCommandExecutor, mainExecutor,
                    frameServerComponent.provideFrameServer(),
                    meteredZoomedRequestBuilder, managedImageReader).providePictureTaker();
        } else {
            pictureTaker = PictureTakerFactory.create(Loggers.tagFactory(), mainExecutor,
                    cameraCommandExecutor, imageSaverBuilder,
                    frameServerComponent.provideFrameServer(),
                    meteredZoomedRequestBuilder, managedImageReader, flashSetting)
                    .providePictureTaker();
        }

        // Wire-together ready-state.
        final Observable<Integer> availableImageCount = sharedImageReaderFactory
                .provideAvailableImageCount();
        final Observable<Boolean> frameServerAvailability = frameServerComponent
                .provideReadyState();
        Observable<Boolean> ready = Observables.transform(
                Arrays.asList(availableImageCount, frameServerAvailability),
                new Supplier<Boolean>() {
                    @Override
                    public Boolean get() {
                        boolean atLeastOneImageAvailable = availableImageCount.get() >= 1;
                        boolean frameServerAvailable = frameServerAvailability.get();
                        return atLeastOneImageAvailable && frameServerAvailable;
                    }
                });

        lifetime.add(Observables.addThreadSafeCallback(ready, readyState));

        basicCameraFactory.providePreviewUpdater().run();

        return new CameraControls(
                pictureTaker,
                basicCameraFactory.provideManualAutoFocus());
    }
};

oneCamera創(chuàng)建成功了扛点,接著會回調openCallback.oneCameraOpened(oneCamera)這里的openCallback便是調用mOneCameraOpener.open()時傳入的。在這個回調里我們用傳入的oneCamera對象oneCamera.startPreview開啟了預覽岂丘。我們知道oneCamera是一個GenericOneCameraImpl對象陵究,我們來看看這個對象的startPreview()方法。

/***GenericOneCameraImpl***/
@Override
    public void startPreview(Surface surface, final CaptureReadyCallback listener) {
        ListenableFuture<Void> result = mPreviewStarter.startPreview(surface);
        Futures.addCallback(result, new FutureCallback<Void>() {
            @Override
            public void onSuccess(@Nonnull Void aVoid) {
                listener.onReadyForCapture();
            }

            @Override
            public void onFailure(@Nonnull Throwable throwable) {
                listener.onSetupFailed();
            }
        });
    }

這里mPreviewStarter創(chuàng)建于InitializedOneCameraFactory奥帘,并接收了一個PreviewStarter.CameraCaptureSessionCreatedListener()的回調铜邮。我們看看這個方法mPreviewStarter.startPreview(surface);

/**PreviewStarter.startPreview(有刪減)**/
public ListenableFuture<Void> startPreview(final Surface surface) {
    List<Surface> surfaceList = new ArrayList<>();
    final ListenableFuture<CameraCaptureSessionProxy> sessionFuture =
            mCaptureSessionCreator.createCaptureSession(surfaceList);
    return Futures.transform(sessionFuture,
            new AsyncFunction<CameraCaptureSessionProxy, Void>() {
                @Override
                public ListenableFuture<Void> apply(
                        CameraCaptureSessionProxy captureSession) throws Exception {
                    mSessionListener.onCameraCaptureSessionCreated(captureSession, surface);
                    return Futures.immediateFuture(null);
                }
            });
}

mCaptureSessionCreator創(chuàng)建于InitializedOneCameraFactory,我們看看mCaptureSessionCreator.createCaptureSession

/**CaptureSessionCreator**/
public ListenableFuture<CameraCaptureSessionProxy> createCaptureSession(
            List<Surface> surfaces) {
    final SettableFuture<CameraCaptureSessionProxy> sessionFuture = SettableFuture.create();
    try {
        mDevice.createCaptureSession(surfaces, new CameraCaptureSessionProxy.StateCallback() {
            @Override
            public void onActive(CameraCaptureSessionProxy session) {
            }

            @Override
            public void onConfigureFailed(CameraCaptureSessionProxy session) {
                sessionFuture.cancel(true);
                session.close();
            }

            @Override
            public void onConfigured(CameraCaptureSessionProxy session) {
                boolean valueSet = sessionFuture.set(session);
                if (!valueSet) {
                    session.close();
                }
            }

            @Override
            public void onReady(CameraCaptureSessionProxy session) {
            }

            @Override
            public void onClosed(CameraCaptureSessionProxy session) {
                sessionFuture.cancel(true);
                session.close();
            }
        }, mCameraHandler);
    } catch (CameraAccessException e) {
        sessionFuture.setException(e);
    }
    return sessionFuture;
}

到這里我們終于開始了一次CaptureSession的會話翩概,并且把sessionFuture返回了,接著程序會把sessionFuture轉換為CameraCaptureSessionProxy類型的capureSession牲距,然后回調mSessionListener.onCameraCaptureSessionCreated(captureSession, surface);這個mSessionListener就是創(chuàng)建mPreviewStarter傳入的回調

public void onCameraCaptureSessionCreated(CameraCaptureSessionProxy session,
        Surface previewSurface) {
    CameraStarter.CameraControls controls = cameraStarter.startCamera(
            new Lifetime(lifetime),
            session, previewSurface,
            zoomState, metadataCallback, readyState);
    mPictureTaker.set(controls.getPictureTaker());
    mManualAutoFocus.set(controls.getManualAutoFocus());
}

cameraStarter是在SimpleOneCameraFactory中創(chuàng)建傳遞下來的

/**SimpleOneCameraFactory**/
CameraStarter cameraStarter = new CameraStarter() {
    @Override
    public CameraControls startCamera(Lifetime cameraLifetime,
            CameraCaptureSessionProxy cameraCaptureSession,
            Surface previewSurface,
            Observable<Float> zoomState,
            Updatable<TotalCaptureResultProxy> metadataCallback,
            Updatable<Boolean> readyState) {
        // Create the FrameServer from the CaptureSession.
        FrameServerFactory frameServerComponent = new FrameServerFactory(
                new Lifetime(cameraLifetime), cameraCaptureSession, new HandlerFactory());

        CameraCommandExecutor cameraCommandExecutor = new CameraCommandExecutor(
                Loggers.tagFactory(),
                new Provider<ExecutorService>() {
                    @Override
                    public ExecutorService get() {
                        // Use a dynamically-expanding thread pool to
                        // allow any number of commands to execute
                        // simultaneously.
                        return Executors.newCachedThreadPool();
                    }
                });

        // Create the shared image reader.
        SharedImageReaderFactory sharedImageReaderFactory =
                new SharedImageReaderFactory(new Lifetime(cameraLifetime), imageReader,
                        new HandlerFactory());
        Updatable<Long> globalTimestampCallback =
                sharedImageReaderFactory.provideGlobalTimestampQueue();
        ManagedImageReader managedImageReader =
                sharedImageReaderFactory.provideSharedImageReader();

        // Create the request builder used by all camera operations.
        // Streams, ResponseListeners, and Parameters added to
        // this will be applied to *all* requests sent to the camera.
        RequestTemplate rootBuilder = new RequestTemplate
                (new CameraDeviceRequestBuilderFactory(device));
        // The shared image reader must be wired to receive every
        // timestamp for every image (including the preview).
        rootBuilder.addResponseListener(
                ResponseListeners.forTimestamps(globalTimestampCallback));
        rootBuilder.addStream(new SimpleCaptureStream(previewSurface));
        rootBuilder.addResponseListener(ResponseListeners.forFinalMetadata(
                metadataCallback));

        FrameServer ephemeralFrameServer =
              frameServerComponent.provideEphemeralFrameServer();

        // Create basic functionality (zoom, AE, AF).
        BasicCameraFactory basicCameraFactory = new BasicCameraFactory(new Lifetime
                (cameraLifetime),
                characteristics,
                ephemeralFrameServer,
                rootBuilder,
                cameraCommandExecutor,
                new BasicPreviewCommandFactory(ephemeralFrameServer),
                flashSetting,
                exposureSetting,
                zoomState,
                hdrSceneSetting,
                CameraDevice.TEMPLATE_PREVIEW);

        // Register the dynamic updater via orientation supplier
        rootBuilder.setParam(CaptureRequest.JPEG_ORIENTATION,
                mImageRotationCalculator.getSupplier());

        if (GservicesHelper.isJankStatisticsEnabled(AndroidContext.instance().get()
              .getContentResolver())) {
            rootBuilder.addResponseListener(
                  new FramerateJankDetector(Loggers.tagFactory(),
                        UsageStatistics.instance()));
        }

        RequestBuilder.Factory meteredZoomedRequestBuilder =
                basicCameraFactory.provideMeteredZoomedRequestBuilder();

        // Create the picture-taker.
        PictureTaker pictureTaker;
        if (supportLevel == OneCameraFeatureConfig.CaptureSupportLevel.LEGACY_JPEG) {
            pictureTaker = new LegacyPictureTakerFactory(imageSaverBuilder,
                    cameraCommandExecutor, mainExecutor,
                    frameServerComponent.provideFrameServer(),
                    meteredZoomedRequestBuilder, managedImageReader).providePictureTaker();
        } else {
            pictureTaker = PictureTakerFactory.create(Loggers.tagFactory(), mainExecutor,
                    cameraCommandExecutor, imageSaverBuilder,
                    frameServerComponent.provideFrameServer(),
                    meteredZoomedRequestBuilder, managedImageReader, flashSetting)
                    .providePictureTaker();
        }

        // Wire-together ready-state.
        final Observable<Integer> availableImageCount = sharedImageReaderFactory
                .provideAvailableImageCount();
        final Observable<Boolean> frameServerAvailability = frameServerComponent
                .provideReadyState();
        Observable<Boolean> ready = Observables.transform(
                Arrays.asList(availableImageCount, frameServerAvailability),
                new Supplier<Boolean>() {
                    @Override
                    public Boolean get() {
                        boolean atLeastOneImageAvailable = availableImageCount.get() >= 1;
                        boolean frameServerAvailable = frameServerAvailability.get();
                        return atLeastOneImageAvailable && frameServerAvailable;
                    }
                });

        lifetime.add(Observables.addThreadSafeCallback(ready, readyState));

        basicCameraFactory.providePreviewUpdater().run();

        return new CameraControls(
                pictureTaker,
                basicCameraFactory.provideManualAutoFocus());
    }
};

這段代碼有非常多的對象新建,非常復雜钥庇。我們上面創(chuàng)建了一次會話后便把session傳入了這里牍鞠,但是我們一直沒有看到重復的請求也就不能一直預覽。我們從basicCameraFactory.providePreviewUpdater().run();看起评姨,推測它和重復預覽有關难述。

/**BasicCameraFactory**/
public Runnable providePreviewUpdater() {
        return mPreviewUpdater;
    }
mPreviewUpdater = new ResettingRunnableCameraCommand(cameraCommandExecutor,
              previewUpdaterCommand);
CameraCommand previewUpdaterCommand =
              previewCommandFactory.get(requestTemplate, templateType);

ResettingRunnableCameraCommand中執(zhí)行了previewUpdaterCommand。這里創(chuàng)建previewUpdaterCommand的兩個參數(shù)吐句,requestTemplate來自于BasicCameraFactory胁后,而templateType則是在SimpleOneCameraFactory中創(chuàng)建basicCameraFactory時傳入的值為CameraDevice.TEMPLATE_PREVIEW
而這里的previewCommandFactory是創(chuàng)建BasicCameraFactory時傳進來的參數(shù)new BasicPreviewCommandFactory(ephemeralFrameServer)嗦枢。

/**BasicPreviewCommandFactory**/
@Override
public CameraCommand get(RequestBuilder.Factory previewRequestBuilder, int templateType) {
    return new PreviewCommand(mFrameServer, previewRequestBuilder, templateType);
}

所以我們可以看到最終被執(zhí)行的就是這個PreviewCommand攀芯,而這個mFrameServer就是ephemeralFrameServer,它創(chuàng)建于SimpleOneCameraFactory.cameraStarter
通過上面很容易看到這個mFrameServer就是SimpleOneCameraFactory.cameraStarter中的ephemeralFrameServer

/**SimpleOneCameraFactory**/
FrameServerFactory frameServerComponent = new FrameServerFactory(
                new Lifetime(cameraLifetime), cameraCaptureSession, new HandlerFactory());
FrameServer ephemeralFrameServer =
              frameServerComponent.provideEphemeralFrameServer();
/**FrameServerFactory**/
public FrameServerFactory(Lifetime lifetime, CameraCaptureSessionProxy cameraCaptureSession,
        HandlerFactory handlerFactory) {
   
    mEphemeralFrameServer = new FrameServerImpl(new TagDispatchCaptureSession
            (cameraCaptureSession, cameraHandler));
}

public FrameServer provideEphemeralFrameServer() {
    return mEphemeralFrameServer;
}

mFrameServer = new FrameServerImpl(new TagDispatchCaptureSession (cameraCaptureSession, cameraHandler));
現(xiàn)在創(chuàng)建PreviewCommand對象PreviewCommand(mFrameServer, previewRequestBuilder, templateType);時傳入的三個參數(shù)我們都知道了,mFrameServer是一個FrameServerImpl的對象文虏,previewRequestBuilder創(chuàng)建于BasicCameraFactory中是一個RequestTemplate對象侣诺,templateType的值為CameraDevice.TEMPLATE_PREVIEW
接下來我們回到PreviewCammandrun()方法氧秘,

/**PreviewCommand**/
public void run() throws InterruptedException, CameraAccessException,
        CameraCaptureSessionClosedException, ResourceAcquisitionFailedException {
    try (FrameServer.Session session = mFrameServer.createExclusiveSession()) {
        RequestBuilder photoRequest = mBuilderFactory.create(mRequestType);
        session.submitRequest(Arrays.asList(photoRequest.build()),
                FrameServer.RequestType.REPEATING);
    }
}

這里mBuilderFactory就是之前的previewRequestBuilder,mRequestType就是templateType年鸳。

/**FrameServerImpl**/
 public Session createExclusiveSession() throws InterruptedException {
    checkState(!mCameraLock.isHeldByCurrentThread(), "Cannot acquire another " +
            "FrameServer.Session on the same thread.");
    mCameraLock.lockInterruptibly();
    return new Session();
}

這里返回了一個FrameServerImpl中的內部類FrameServerImpl.Session

/**RequestTemplate**/
 @Override
    public RequestBuilder create(int templateType) throws CameraAccessException {
        RequestBuilder builder = mRequestBuilderFactory.create(templateType);
        for (Parameter param : mParameters) {
            param.addToBuilder(builder);
        }
        for (ResponseListener listener : mResponseListeners) {
            builder.addResponseListener(listener);
        }
        for (CaptureStream stream : mCaptureStreams) {
            builder.addStream(stream);
        }
        return builder;
    }

這里mRequestBuilderFactory是在RequestTemplat創(chuàng)建時傳入的,而RequestTemplat是在BasicCameraFactory中創(chuàng)建的丸相,mRequestBuilderFactory就是BasicCameraFactory中的rootTemplate搔确,而rootTemplate又是在SimpleOneCameraFactory中創(chuàng)建BasicCameraFactory時傳入的,最終mRequestBuilderFactorySimpleOneCameraFactory中的rootBuilderRequestTemplate rootBuilder = new RequestTemplate (new CameraDeviceRequestBuilderFactory(device));就是說mRequestBuilderFactory = rootBuilder膳算,所以mRequestBuilderFactory.create(templateType);就是rootBuilder.create(templateType)座硕,最終調用了new CameraDeviceRequestBuilderFactory(device).create(templateType);

/**CameraDeviceRequestBuilderFactory**/
@Override
    public RequestBuilder create(int templateType) throws CameraAccessException {
        return new RequestBuilder(new CaptureRequestBuilderProxy(
                mCameraDevice.createCaptureRequest(templateType)));
    }

這里我們創(chuàng)建了一個CaptureRequest以此來控制圖像的輸出,并把它包裝成了一個RequestBuilder對象向上返回畦幢。

/**FrameServerImpl.Session**/
@Override
public void submitRequest(List<Request> burstRequests, RequestType type)
        throws CameraAccessException, InterruptedException,
        CameraCaptureSessionClosedException, ResourceAcquisitionFailedException {
    synchronized (mLock) {
        try {
            if (mClosed) {
                throw new SessionClosedException();
            }

            mCaptureSession.submitRequest(burstRequests, type);
        } catch (Exception e) {
            for (Request r : burstRequests) {
                r.abort();
            }
            throw e;
        }
    }
}

這里的mCaptureSession是我們創(chuàng)建FrameServerImpl時給的參數(shù)new TagDispatchCaptureSession (cameraCaptureSession, cameraHandler)

/**TagDispatchCaptureSession**/
public void submitRequest(List<Request> burstRequests, FrameServer.RequestType requestType)
        throws
        CameraAccessException, InterruptedException, CameraCaptureSessionClosedException,
        ResourceAcquisitionFailedException {
    try {
        Map<Object, ResponseListener> tagListenerMap = new HashMap<Object, ResponseListener>();
        List<CaptureRequest> captureRequests = new ArrayList<>(burstRequests.size());

        for (Request request : burstRequests) {
            Object tag = generateTag();

            tagListenerMap.put(tag, request.getResponseListener());

            CaptureRequestBuilderProxy builder = request.allocateCaptureRequest();
            builder.setTag(tag);
            captureRequests.add(builder.build());
        }

        if (requestType == FrameServer.RequestType.REPEATING) {
            mCaptureSession.setRepeatingBurst(captureRequests, new
                    CaptureCallback(tagListenerMap), mCameraHandler);
        } else {
            mCaptureSession.captureBurst(captureRequests, new
                    CaptureCallback(tagListenerMap), mCameraHandler);
        }
    } catch (Exception e) {
        for (Request r : burstRequests) {
            r.abort();
        }
        throw e;
    }
}

在這里我們終于看到了mCaptureSession.setRepeatingBurst()這里就可以不斷的重復請求畫面坎吻,從而實現(xiàn)預覽缆蝉。
預覽時序圖如下:

預覽流程.png

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末宇葱,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子刊头,更是在濱河造成了極大的恐慌黍瞧,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,884評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件原杂,死亡現(xiàn)場離奇詭異印颤,居然都是意外死亡,警方通過查閱死者的電腦和手機穿肄,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,347評論 3 385
  • 文/潘曉璐 我一進店門年局,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人咸产,你說我怎么就攤上這事矢否。” “怎么了脑溢?”我有些...
    開封第一講書人閱讀 157,435評論 0 348
  • 文/不壞的土叔 我叫張陵僵朗,是天一觀的道長。 經(jīng)常有香客問我屑彻,道長验庙,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,509評論 1 284
  • 正文 為了忘掉前任社牲,我火速辦了婚禮粪薛,結果婚禮上,老公的妹妹穿的比我還像新娘搏恤。我一直安慰自己违寿,他們只是感情好,可當我...
    茶點故事閱讀 65,611評論 6 386
  • 文/花漫 我一把揭開白布挑社。 她就那樣靜靜地躺著陨界,像睡著了一般。 火紅的嫁衣襯著肌膚如雪痛阻。 梳的紋絲不亂的頭發(fā)上菌瘪,一...
    開封第一講書人閱讀 49,837評論 1 290
  • 那天,我揣著相機與錄音,去河邊找鬼俏扩。 笑死糜工,一個胖子當著我的面吹牛,可吹牛的內容都是我干的录淡。 我是一名探鬼主播捌木,決...
    沈念sama閱讀 38,987評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼嫉戚!你這毒婦竟也來了刨裆?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 37,730評論 0 267
  • 序言:老撾萬榮一對情侶失蹤彬檀,失蹤者是張志新(化名)和其女友劉穎帆啃,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體窍帝,經(jīng)...
    沈念sama閱讀 44,194評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡努潘,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 36,525評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了坤学。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片疯坤。...
    茶點故事閱讀 38,664評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖深浮,靈堂內的尸體忽然破棺而出压怠,到底是詐尸還是另有隱情,我是刑警寧澤略号,帶...
    沈念sama閱讀 34,334評論 4 330
  • 正文 年R本政府宣布刑峡,位于F島的核電站,受9級特大地震影響玄柠,放射性物質發(fā)生泄漏突梦。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,944評論 3 313
  • 文/蒙蒙 一羽利、第九天 我趴在偏房一處隱蔽的房頂上張望宫患。 院中可真熱鬧,春花似錦这弧、人聲如沸娃闲。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,764評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽皇帮。三九已至,卻和暖如春蛋辈,著一層夾襖步出監(jiān)牢的瞬間属拾,已是汗流浹背将谊。 一陣腳步聲響...
    開封第一講書人閱讀 31,997評論 1 266
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留渐白,地道東北人尊浓。 一個月前我還...
    沈念sama閱讀 46,389評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像纯衍,于是被迫代替她去往敵國和親栋齿。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 43,554評論 2 349

推薦閱讀更多精彩內容