title: CameraX - Unable to configure Camera
body: <p>I want to implement a custom View which will display a live preview using Camera X API but I'm stuck with the configuration of <code>Camera X</code>...</p>
  
  <p>Based on the <a href="https://github.com/android/camera-samples/tree/master/CameraXBasic" rel="noreferrer">CameraX sample code</a>, I try to implement my custom view but nothing but a black screen appears and my logs say :</p>
  
  <blockquote>
    <p>E/Camera: Unable to configure camera 1, timeout!</p>
  </blockquote>
  
  <p>Here is my Activity Layout</p>
  
  <pre><code>&lt;?xml version="1.0" encoding="utf-8"?&gt;
  &lt;RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
      xmlns:tools="http://schemas.android.com/tools"
      android:id="@+id/root"
      android:layout_width="match_parent"
      android:layout_height="match_parent"
      android:background="@color/colorBlack"
      tools:context=".MainActivity"&gt;
  
      &lt;com.component.LiveView
          android:id="@+id/live"
          android:layout_width="match_parent"
          android:layout_height="match_parent"
          android:adjustViewBounds="true"
          android:background="@android:color/black" /&gt;
  
  &lt;/RelativeLayout&gt;
  </code></pre>
  
  <p>and the code related to my component</p>
  
  <pre><code>override fun onResume() {
      super.onResume()
      when {
          ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED -&gt;
              // Start camera preview
              live.start(this)
          ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.CAMERA) -&gt; ConfirmationDialogFragment.newInstance(R.string.camera_permission_confirmation,
                  arrayOf(Manifest.permission.CAMERA),
                  REQUEST_CAMERA_PERMISSION,
                  R.string.camera_permission_not_granted)
                  .show(supportFragmentManager, FRAGMENT_DIALOG)
          else -&gt; ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.CAMERA),
                  REQUEST_CAMERA_PERMISSION)
      }
  }
  </code></pre>
  
  <p>Now, my <code>Live</code> component is something like this</p>
  
  <pre><code>class LiveView(context: Context, attrs: AttributeSet) : CameraSourcePreview(context, attrs) {
  
      init {
  
          if (BuildConfig.DEBUG) {
              Timber.plant(Timber.DebugTree())
          } else {
              Timber.plant(TimberReleaseTree())
          }
  
          Timber.e("LiveView init")
      }
  
      fun start(livecycleOwner: LifecycleOwner) {
          super.start(livecycleOwner)
          Timber.e("LiveView start")
      }
  }
  
  /** Preview the camera image in the screen.  */
  open class CameraSourcePreview(context: Context, attrs: AttributeSet) : ViewGroup(context, attrs) {
  
      private val previewView = PreviewView(context, attrs)
  
      private var displayId: Int = -1
      private var lensFacing: Int = CameraSelector.LENS_FACING_FRONT
      private var preview: Preview? = null
      private var imageCapture: ImageCapture? = null
      private var imageAnalyzer: ImageAnalysis? = null
      private var camera: Camera? = null
  
      private val displayManager by lazy {
          context.getSystemService(Context.DISPLAY_SERVICE) as DisplayManager
      }
  
      /** Blocking camera operations are performed using this executor */
      private lateinit var cameraExecutor: ExecutorService
  
      /**
       * We need a display listener for orientation changes that do not trigger a configuration
       * change, for example if we choose to override config change in manifest or for 180-degree
       * orientation changes.
       */
      private val displayListener = object : DisplayManager.DisplayListener {
          override fun onDisplayAdded(displayId: Int) = Unit
          override fun onDisplayRemoved(displayId: Int) = Unit
          override fun onDisplayChanged(displayId: Int) {
              if (displayId == this@CameraSourcePreview.displayId) {
                  Timber.d("Rotation changed: ${display.rotation}")
                  imageCapture?.targetRotation = display.rotation
                  imageAnalyzer?.targetRotation = display.rotation
              }
          }
      }
  
      /**
       * Starts camera source preview.
       */
      @Throws(IOException::class)
      fun start(lifecycleOwner: LifecycleOwner) {
  
          Timber.e("CameraSourcePreview start")
  
          // Initialize our background executor
          cameraExecutor = Executors.newSingleThreadExecutor()
  
          // Wait for the views to be properly laid out
          addView(previewView)
          //previewView.preferredImplementationMode = PreviewView.ImplementationMode.SURFACE_VIEW // seen on https://stackoverflow.com/a/60559642/10159898 bit it doesn't change anything
          previewView.post {
              // Keep track of the display in which this view is attached
              displayId = previewView.display.displayId
              Timber.e("CameraSourcePreview start post")
              // Bind use cases to lifecycle
              bindCameraUseCases(lifecycleOwner)
          }
      }
  
      /**
       * Stop camera source preview. It is requirement to implement this part.
       * Recommended to implement it onPause function.
       */
      fun stop() {
          // Shut down our background executor
          cameraExecutor.shutdown()
          Timber.e("CameraSourcePreview stop")
          // Unregister the broadcast receivers and listeners
          displayManager.unregisterDisplayListener(displayListener)
      }
  
      /** Declare and bind preview, capture and analysis use cases */
      private fun bindCameraUseCases(lifecycleOwner: LifecycleOwner) {
          Timber.e("CameraSourcePreview bindCameraUseCases")
          // Get screen metrics used to setup camera for full screen resolution
          val metrics = DisplayMetrics().also { previewView.display.getRealMetrics(it) }
          Timber.d("Screen metrics: ${metrics.widthPixels} x ${metrics.heightPixels}")
  
          val targetAspectRatio = aspectRatio(metrics.widthPixels, metrics.heightPixels)
          Timber.d("Preview aspect ratio: $targetAspectRatio")
  
          val targetRotation = previewView.display.rotation
  
          val cameraSelector = CameraSelector.Builder()
                  .requireLensFacing(lensFacing)
                  .build()
  
          // Bind the CameraProvider to the LifeCycleOwner
          val cameraProviderFuture = ProcessCameraProvider.getInstance(context)
          cameraProviderFuture.addListener(Runnable {
  
              // CameraProvider
              val cameraProvider = cameraProviderFuture.get()
  
              // Preview Usecase
              preview = Preview.Builder()
                      // We request aspect ratio but no resolution
                      .setTargetAspectRatio(targetAspectRatio)
                      // Set initial target rotation
                      .setTargetRotation(targetRotation)
                      .build()
  
              // Must unbind the use-cases before rebinding them
              cameraProvider.unbindAll()
  
              try {
                  // A variable number of use-cases can be passed here -
                  // camera provides access to CameraControl &amp; CameraInfo
                  camera = cameraProvider.bindToLifecycle(
                          lifecycleOwner, cameraSelector, preview)
  
                  preview?.setSurfaceProvider(previewView.createSurfaceProvider(camera?.cameraInfo))
              } catch (exc: Exception) {
                  Timber.e("Use case binding failed: ${exc.message}")
              }
  
          }, ContextCompat.getMainExecutor(context))
      }
  
      /**
       *  [androidx.camera.core.ImageAnalysisConfig] requires enum value of
       *  [androidx.camera.core.AspectRatio]. Currently it has values of 4:3 &amp; 16:9.
       *
       *  Detecting the most suitable ratio for dimensions provided in @params by counting absolute
       *  of preview ratio to one of the provided values.
       *
       *  @param width - preview width
       *  @param height - preview height
       *  @return suitable aspect ratio
       */
      private fun aspectRatio(width: Int, height: Int): Int {
          Timber.e("CameraSourcePreview aspectRatio")
          val previewRatio = max(width, height).toDouble() / min(width, height)
          if (abs(previewRatio - RATIO_4_3_VALUE) &lt;= abs(previewRatio - RATIO_16_9_VALUE)) {
              return AspectRatio.RATIO_4_3
          }
          return AspectRatio.RATIO_16_9
      }
  
      /**
       * Recalculate the camera preview size.
       */
      override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) {
  //        Timber.e("CameraSourcePreview onLayout: $changed, $left, $top, $right, $bottom")
  //        var width = 480
  //        var height = 640
  //        
  //        // Swap width and height sizes when in portrait, since it will be rotated 90 degrees
  //        if (isPortraitMode) {
  //            val tmp = width
  //            width = height
  //            height = tmp
  //        }
  //        val layoutWidth = right - left
  //        val layoutHeight = bottom - top
  //        // Computes height and width for potentially doing fit width.
  //        var childWidth = layoutWidth
  //        var childHeight = (layoutWidth.toFloat() / width.toFloat() * height).toInt()
  //        // If height is too tall using fit width, does fit height instead.
  //        if (childHeight &gt; layoutHeight) {
  //            childHeight = layoutHeight
  //            childWidth = (layoutHeight.toFloat() / height.toFloat() * width).toInt()
  //        }
  //        for (i in 0 until childCount) {
  //            getChildAt(i).layout(0, 0, childWidth, childHeight)
  //            Timber.d("Assigned view: $i")
  //        }
      }
  
      companion object {
          private const val RATIO_4_3_VALUE = 4.0 / 3.0
          private const val RATIO_16_9_VALUE = 16.0 / 9.0
      }
  }
  </code></pre>
  
  <p>Does someone can have a look at this and point me my issue ?</p>
  
  <p>Note : </p>
  
  <ul>
  <li>I'd like to use a Custom View because the global purpose is to migrate my Camera lib based ans Camera2</li>
  <li>I've already seen <a href="https://stackoverflow.com/a/60559642/10159898">this post about the previewView implementation mode</a> (see code) but it doesn't help me.</li>
  </ul>