@@ -33,6 +33,7 @@ internal class WindowRecorder(
3333 private val rootViews = ArrayList <WeakReference <View >>()
3434 private var lastKnownWindowSize: Point = Point ()
3535 private val rootViewsLock = AutoClosableReentrantLock ()
36+ private val capturerLock = AutoClosableReentrantLock ()
3637 @Volatile private var capturer: Capturer ? = null
3738
3839 private class Capturer (
@@ -50,6 +51,8 @@ internal class WindowRecorder(
5051 }
5152 recorder?.resume()
5253 isRecording.getAndSet(true )
54+ // Remove any existing callbacks to prevent concurrent capture loops
55+ mainLooperHandler.removeCallbacks(this )
5356 val posted = mainLooperHandler.post(this )
5457 if (! posted) {
5558 options.logger.log(
@@ -165,8 +168,12 @@ internal class WindowRecorder(
165168 }
166169
167170 if (capturer == null ) {
168- // don't recreate runnable for every config change, just update the config
169- capturer = Capturer (options, mainLooperHandler)
171+ capturerLock.acquire().use {
172+ if (capturer == null ) {
173+ // don't recreate runnable for every config change, just update the config
174+ capturer = Capturer (options, mainLooperHandler)
175+ }
176+ }
170177 }
171178
172179 capturer?.config = config
@@ -184,6 +191,9 @@ internal class WindowRecorder(
184191 capturer?.recorder?.bind(newRoot)
185192 }
186193
194+ // Remove any existing callbacks to prevent concurrent capture loops
195+ mainLooperHandler.removeCallbacks(capturer)
196+
187197 val posted =
188198 mainLooperHandler.postDelayed(
189199 capturer,
@@ -215,7 +225,7 @@ internal class WindowRecorder(
215225
216226 override fun stop () {
217227 capturer?.stop()
218- capturer = null
228+ capturerLock.acquire().use { capturer = null }
219229 isRecording.set(false )
220230 }
221231
0 commit comments