Question: Currently there's no equivalent to CameraView (and PreviewView) in Compose. Is it possible to wrap it and display it in a compose layout?

Answer: 
At the moment there isn't any official
Composable function for CameraX so we have to inflate the legacy android view inside compose.

To achieve that
we can use `AndroidView` composable function,
it accepts two parameters

* @param `resId` The id of the layout resource to be inflated.
* @param `postInflationCallback` The callback to be invoked after the layout
is inflated.

and to access the lifecycle and context we use the ambients

```
val lifecycleOwner = LifecycleOwnerAmbient.current
val context = ContextAmbient.current

```

As we have everything we need let's do it:

Create a layout `camera_host.xml`

```
<?xml version="1.0" encoding="utf-8"?>
<androidx.camera.view.PreviewView xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/previewView"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />

```

and inflate it using `AndroidView` Composable function.

```
@Composable
fun SimpleCameraPreview() {
    val lifecycleOwner = LifecycleOwnerAmbient.current
    val context = ContextAmbient.current
    val cameraProviderFuture = remember { ProcessCameraProvider.getInstance(context) }
    AndroidView(resId = R.layout.camera_host) { inflatedLayout ->
       //You can call
      // findViewById<>() and etc ... on inflatedLayout
      // here PreviewView is the root of my layout so I just cast it to
      // the PreviewView and no findViewById is required

        cameraProviderFuture.addListener(Runnable {
            val cameraProvider = cameraProviderFuture.get()
            bindPreview(
                 lifecycleOwner,
                 inflatedLayout as PreviewView /*the inflated layout*/,
                 cameraProvider)
        }, ContextCompat.getMainExecutor(context))

    }
}

fun bindPreview(
    lifecycleOwner: LifecycleOwner,
    previewView: PreviewView,
    cameraProvider: ProcessCameraProvider
) {
    var preview: Preview = Preview.Builder().build()

    var cameraSelector: CameraSelector = CameraSelector.Builder()
        .requireLensFacing(CameraSelector.LENS_FACING_BACK)
        .build()

    preview.setSurfaceProvider(previewView.createSurfaceProvider())

    var camera = cameraProvider.bindToLifecycle(lifecycleOwner, cameraSelector, preview)
}

```

```
class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            SimpleCameraPreview()
        }
    }
}

```
This is my snippet (based on Sean's answer), which also handles torch state and resource disposition and adds a focus on tap logic.
Dependencies:

```
implementation 'androidx.camera:camera-camera2:1.1.0-alpha11'
implementation 'androidx.camera:camera-view:1.0.0-alpha31'
implementation 'androidx.camera:camera-lifecycle:1.1.0-alpha11'

implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-guava:1.6.0-RC'

```

```
@Composable
fun CameraPreview(
    modifier: Modifier = Modifier,
    cameraSelector: CameraSelector = CameraSelector.DEFAULT_BACK_CAMERA,
    implementationMode: PreviewView.ImplementationMode = PreviewView.ImplementationMode.COMPATIBLE,
    scaleType: PreviewView.ScaleType = PreviewView.ScaleType.FILL_CENTER,
    imageAnalysis: ImageAnalysis? = null,
    imageCapture: ImageCapture? = null,
    preview: Preview = remember { Preview.Builder().build() },
    enableTorch: Boolean = false,
    focusOnTap: Boolean = false
) {
    val context = LocalContext.current
    val lifecycleOwner = LocalLifecycleOwner.current

    val cameraProvider by produceState<ProcessCameraProvider?>(initialValue = null) {
        value = ProcessCameraProvider.getInstance(context).await()
    }

    // TODO: add cameraSelector
    val camera = remember(cameraProvider) {
        cameraProvider?.let {
            it.unbindAll()
            it.bindToLifecycle(
                lifecycleOwner,
                cameraSelector,
                *listOfNotNull(imageAnalysis, imageCapture, preview).toTypedArray()
            )
        }
    }

    LaunchedEffect(camera, enableTorch) {
        camera?.let {
            if (it.cameraInfo.hasFlashUnit()) {
                it.cameraControl.enableTorch(enableTorch).await()
            }
        }
    }

    DisposableEffect(Unit) {
        onDispose {
            cameraProvider?.unbindAll()
        }
    }

    AndroidView(
        modifier = modifier.pointerInput(camera, focusOnTap) {
            if (!focusOnTap) return@pointerInput

            detectTapGestures {
                val meteringPointFactory = SurfaceOrientedMeteringPointFactory(
                    size.width.toFloat(),
                    size.height.toFloat()
                )

                val meteringAction = FocusMeteringAction.Builder(
                    meteringPointFactory.createPoint(it.x, it.y),
                    FocusMeteringAction.FLAG_AF
                ).disableAutoCancel().build()

                camera?.cameraControl?.startFocusAndMetering(meteringAction)
            }
        },
        factory = { _ ->
            PreviewView(context).also {
                it.scaleType = scaleType
                it.implementationMode = implementationMode
                preview.setSurfaceProvider(it.surfaceProvider)
            }
        }
    )
}

```