源碼是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);
}
到這里德崭,我們終于看到了相機的打開哮洽,這一段的時序圖如下相機打開后會回調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
。
接下來我們回到PreviewCammand
的run()
方法氧秘,
/**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
時傳入的,最終mRequestBuilderFactory
是SimpleOneCameraFactory
中的rootBuilder
。RequestTemplate 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)預覽缆蝉。
預覽時序圖如下: