CanvasFrontBufferRenderer is giving error as APP_SCOUT_WARNING

29 Views Asked by At

I am building an app using jetpack compose. It uses stylus as the main functionality. For the faster rendering I am using lowLatencySurface.

I have a composable called 'CommonDrawArea'. Below is the content.

@Composable
fun CommonDrawArea(
    viewModel: PrescriptionPageViewModel,
    drawAreaType: DrawAreaType,
    modifier: Modifier = Modifier
){
    val fastRendering = remember{
        FastRenderer(
            viewModel,
            drawAreaType
        )
    }
    AndroidView(
        factory = { context ->
            LowLatencySurfaceView(context, fastRenderer = fastRendering)
        },
        modifier = modifier
    )
}

Below is the FastRenderer and LowLatencySurfaceView repectively.

class FastRenderer(
    private var viewModel: PrescriptionPageViewModel,
    val drawAreaType: DrawAreaType,
) : CanvasFrontBufferedRenderer.Callback<Line>, ClearLineCallback {

    private var frontBufferRenderer: CanvasFrontBufferedRenderer<Line>? = null
    private var isFastRendererRegistered: Boolean = false

    var canvasWidth: Float = 0f
    var convasHeight: Float = 0f
    var globalPostion: Offset = Offset(0f, 0f)

    @RequiresApi(Build.VERSION_CODES.Q)
    fun attachSurfaceView(surfaceView: SurfaceView) {
        frontBufferRenderer = CanvasFrontBufferedRenderer(surfaceView, this)
        Log.d("kdsflkj", "attach")
    }

    @RequiresApi(Build.VERSION_CODES.Q)
    fun release() {
        frontBufferRenderer?.release(true)
        Log.d("kdsflkj", "release")
    }

    @RequiresApi(Build.VERSION_CODES.Q)
    @SuppressLint("ClickableViewAccessibility")
    val onTouchListener = View.OnTouchListener { view, motionEvent ->
        if(frontBufferRenderer?.isValid() == true){
            if (viewModel.isReadOnly.not()) {
                val isStylus =
                    MotionEvent.TOOL_TYPE_STYLUS == motionEvent.getToolType(motionEvent.pointerCount - 1)
                if (isStylus) {
                    val strokeWidthFactor = motionEvent.pressure
                    when (motionEvent.actionMasked) {
                        MotionEvent.ACTION_DOWN -> {

                            viewModel.checkNewWritingArea(
                                motionEvent,
                                drawAreaType,
                                canvasWidth
                            )

                            if (isFastRendererRegistered.not()) {
                                viewModel.registerFastRenderer(this)
                                isFastRendererRegistered = true
                            }

                            view.requestUnbufferedDispatch(motionEvent)

                            val currentLine = Line(
                                Offset(motionEvent.x, motionEvent.y),
                                Offset(motionEvent.x, motionEvent.y),
                                strokeWidthFactor
                            )
                            frontBufferRenderer?.renderFrontBufferedLayer(currentLine)
                            viewModel.previousLinePointer = Offset(motionEvent.x, motionEvent.y)
                        }

                        MotionEvent.ACTION_MOVE -> {
                            val currentLine =
                                Line(
                                    viewModel.previousLinePointer,
                                    Offset(motionEvent.x, motionEvent.y),
                                    strokeWidthFactor
                                )
                            frontBufferRenderer?.renderFrontBufferedLayer(currentLine)
                            viewModel.previousLinePointer = Offset(motionEvent.x, motionEvent.y)
                        }

                        MotionEvent.ACTION_UP -> {
                            val currentLine =
                                Line(
                                    viewModel.previousLinePointer,
                                    Offset(motionEvent.x, motionEvent.y),
                                    strokeWidthFactor
                                )
                            frontBufferRenderer?.renderFrontBufferedLayer(currentLine)
                            frontBufferRenderer?.commit()
                        }
                    }

//                runBlocking {
//                    launch(Dispatchers.Default) {
//                        viewModel.processStylusMotionEvent(
//                            motionEvent,
//                            Offset(
//                                globalPostion.x + motionEvent.x,
//                                globalPostion.y + motionEvent.y
//                            ),
//                            viewModel.writingArea.value
//                        )
//                    }
//                }

                } else {
//                    runBlocking {
//                        launch(Dispatchers.Default) {
//                            viewModel.processHandMotionEvent(
//                                motionEvent,
//                                drawAreaType,
//                                canvasWidth
//                            )
//                        }
//                    }
                }
            }
        }
        true
    }


    override fun onDrawFrontBufferedLayer(
        canvas: Canvas,
        bufferWidth: Int,
        bufferHeight: Int,
        line: Line
    ) {

        if (viewModel.writingArea.value in medicationFieldDrawAreaTypes) {
            drawIfMedication(listOf(line), canvas)
        } else {
            if (viewModel.writingArea.value == drawAreaType) {
                val paint = Paint().apply {
                    color = Color.argb(255, 51, 102, 204)
                    strokeWidth = line.strokeWidthFactor * 15
                    style = Paint.Style.FILL_AND_STROKE
                }
                canvas.drawLine(line.start.x, line.start.y, line.end.x, line.end.y, paint)
            }
        }
    }

    fun drawIfMedication(
        line: List<Line>,
        canvas: Canvas
    ) {
        if (viewModel.writingArea.value in medicationFieldDrawAreaTypes) {
            line.forEach { line ->

                val paint = Paint().apply {
                    color = Color.argb(255, 51, 102, 204)
                    strokeWidth = line.strokeWidthFactor * 15
                    style = Paint.Style.FILL_AND_STROKE
                }
                canvas.drawLine(line.start.x, line.start.y, line.end.x, line.end.y, paint)
            }
        }
    }

    override fun onDrawMultiBufferedLayer(
        canvas: Canvas,
        bufferWidth: Int,
        bufferHeight: Int,
        params: Collection<Line>
    ) {

        for (line in params.toList()) {
            viewModel.currentLine.add(line)
        }

        if (viewModel.writingArea.value in medicationFieldDrawAreaTypes) {
            drawIfMedication(viewModel.currentLine, canvas)
        } else {
            for (line in viewModel.currentLine) {
                if (viewModel.writingArea.value == drawAreaType) {
                    val paint = Paint().apply {
                        color = Color.argb(255, 51, 102, 204)
                        strokeWidth = line.strokeWidthFactor * 15
                        style = Paint.Style.FILL_AND_STROKE
                    }
                    canvas.drawLine(line.start.x, line.start.y, line.end.x, line.end.y, paint)
                }
            }
        }
    }
}
class LowLatencySurfaceView(context: Context, private val fastRenderer: FastRenderer) :
    SurfaceView(context) {

    init {
        setOnTouchListener(fastRenderer.onTouchListener)
        setZOrderOnTop(true)
        holder.addCallback(object : SurfaceHolder.Callback {
            override fun surfaceCreated(holder: SurfaceHolder) {
            }

            override fun surfaceChanged(
                holder: SurfaceHolder,
                format: Int,
                width: Int,
                height: Int
            ) {
                // Surface size changed, you can get the width and height here
                fastRenderer.canvasWidth = width.toFloat()
                fastRenderer.convasHeight = height.toFloat()

                // Get the global position on the screen
                val screenPos = IntArray(2)
                getLocationOnScreen(screenPos)
                val screenX = screenPos[0]
                val screenY = screenPos[1]

                fastRenderer.globalPostion = Offset(screenX.toFloat(), screenY.toFloat())
                // Now, you can use surfaceWidth and surfaceHeight as needed
            }

            override fun surfaceDestroyed(holder: SurfaceHolder) {
                // Surface is destroyed
            }
        })
    }

    override fun onAttachedToWindow() {
        super.onAttachedToWindow()
        fastRenderer.attachSurfaceView(this)
    }

    override fun onDetachedFromWindow() {
        fastRenderer.release()
        super.onDetachedFromWindow()
    }
}

I am facing an Error, where initially when the app opens newly, everything works fine. But when the lifecycle state changes to onstop and again comes to onStart or onResume. It give me "APP_SCOUT_WARNING" error and the whole app freezes. Below is the error logs.

2024-01-22 18:04:39.048 14945-14945 Gralloc4                com.unriddle.paper                   E  buffer descriptor contains invalid usage bits 0x100000000
2024-01-22 18:04:39.048 14945-14945 BufferRendererV29       com.unriddle.paper                   V  Explicit usage of single buffered preservation strategy
2024-01-22 18:04:39.051 14945-22572 FrameEvents             com.unriddle.paper                   E  updateAcquireFence: Did not find frame.
2024-01-22 18:04:39.051 14945-22572 Parcel                  com.unriddle.paper                   W  Expecting binder but got null!
2024-01-22 18:04:43.545 14945-22986 MIUIScout App           com.unriddle.paper                   W  Enter APP_SCOUT_WARNING State
2024-01-22 18:04:43.548 14945-22986 MIUIScout App           com.unriddle.paper                   W   (Current message: duration=5001ms seq=308 late=24ms h=android.view.Choreographer$FrameHandler c=android.view.Choreographer$FrameDisplayEventReceiver)
2024-01-22 18:04:43.570 14945-22986 AppScoutStateMachine    com.unriddle.paper                   D  dump trace dirName = com.unriddle.paper-14945-APP_SCOUT_WARNING-2024-01-22-18-04-43
2024-01-22 18:04:43.592 14945-22550 .unriddle.paper         com.unriddle.paper                   I  Thread[6,tid=22550,WaitingInMainSignalCatcherLoop,Thread*=0xb4000072ede45000,peer=0x15080440,"Signal Catcher"]: reacting to signal 3
2024-01-22 18:04:43.592 14945-22550 .unriddle.paper         com.unriddle.paper                   I  
2024-01-22 18:04:43.602 14945-23029 MIUIScout App           com.unriddle.paper                   W  Event:APP_SCOUT_WARNING Thread:main backtrace:
                                                                                                        at jdk.internal.misc.Unsafe.park(Native Method)
                                                                                                        at java.util.concurrent.locks.LockSupport.park(LockSupport.java:211)
                                                                                                        at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquire(AbstractQueuedSynchronizer.java:715)
                                                                                                        at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireSharedInterruptibly(AbstractQueuedSynchronizer.java:1047)
                                                                                                        at java.util.concurrent.CountDownLatch.await(CountDownLatch.java:230)
                                                                                                        at androidx.graphics.lowlatency.PreservedBufferContentsVerifier.supportsPreservedRenderedContent(PreservedBufferContentsVerifier.kt:118)
                                                                                                        at androidx.graphics.CanvasBufferedRendererV29$Companion.createPreservationStrategy$graphics_core_release(CanvasBufferedRendererV29.kt:380)
                                                                                                        at androidx.graphics.CanvasBufferedRendererV29.<init>(CanvasBufferedRendererV29.kt:53)
                                                                                                        at androidx.graphics.CanvasBufferedRenderer.<init>(CanvasBufferedRenderer.kt:82)
                                                                                                        at androidx.graphics.CanvasBufferedRenderer$Builder.build(CanvasBufferedRenderer.kt:272)
                                                                                                        at androidx.graphics.lowlatency.SingleBufferedCanvasRenderer.<init>(SingleBufferedCanvasRenderer.kt:137)
                                                                                                        at androidx.graphics.lowlatency.CanvasFrontBufferedRenderer.update$graphics_core_release(CanvasFrontBufferedRenderer.kt:226)
                                                                                                        at androidx.graphics.lowlatency.CanvasFrontBufferedRenderer$mHolderCallback$1.surfaceChanged(CanvasFrontBufferedRenderer.kt:162)
                                                                                                        at android.view.SurfaceView.updateSurface(SurfaceView.java:1136)
                                                                                                        at android.view.SurfaceView.setFrame(SurfaceView.java:493)
                                                                                                        at android.view.View.layout(View.java:23873)
                                                                                                        at androidx.compose.ui.viewinterop.AndroidViewHolder.onLayout(AndroidViewHolder.android.kt:238)
                                                                                                        at android.view.View.layout(View.java:23876)
                                                                                                        at android.view.ViewGroup.layout(ViewGroup.java:6454)

Please help me solve this issue.

I want the app to flowlessly work even after the tablet is locked and unlocked, without freezing.

0

There are 0 best solutions below