docs: private void startPreview() {
  		// Sanity check. Parts of this code assume it's on this thread. If it has been put into a handle
  		// that's fine just be careful nothing assumes it's on the main looper
  		if (Looper.getMainLooper().getThread() != Thread.currentThread()) {
  			throw new RuntimeException("Not on main looper! Modify code to remove assumptions");
  		}
  
  		if( verbose ) {
  			Log.i(TAG,"startPreview()");
  		}
  
  		try {
  			open.mLock.lock();
  
  			if (null == open.mCameraDevice || null == open.mCameraSize) {
  				Log.i(TAG,"  aborting startPreview. Camera not open yet.");
  				return;
  			}
  
  			closePreviewSession();
  			open.surfaces = new ArrayList<>();
  			open.mPreviewRequestBuilder = open.mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
  
  			if( mTextureView != null && mTextureView.isAvailable() ) {
  				SurfaceTexture texture = mTextureView.getSurfaceTexture();
  				assert texture != null;
  				texture.setDefaultBufferSize(open.mCameraSize.getWidth(), open.mCameraSize.getHeight());
  
  				// Display the camera preview into this texture
  				Surface previewSurface = new Surface(texture);
  				open.surfaces.add(previewSurface);
  				open.mPreviewRequestBuilder.addTarget(previewSurface);
  			}
  
  			// This is where the image for processing is extracted from
  			Surface readerSurface = open.mPreviewReader.getSurface();
  			open.surfaces.add(readerSurface);
  			open.mPreviewRequestBuilder.addTarget(readerSurface);
  
  			createCaptureSession();
  		} catch (CameraAccessException e) {
  			e.printStackTrace();
  		} finally {
  			open.mLock.unlock();
  		}
  	}