Skip to content

Commit cfad186

Browse files
committed
Address PR feedback
1 parent 88f8f9c commit cfad186

File tree

4 files changed

+226
-193
lines changed

4 files changed

+226
-193
lines changed

sentry-android-replay/src/main/java/io/sentry/android/replay/ScreenshotRecorder.kt

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,10 @@ import io.sentry.android.replay.screenshot.CanvasStrategy
1515
import io.sentry.android.replay.screenshot.PixelCopyStrategy
1616
import io.sentry.android.replay.screenshot.ScreenshotStrategy
1717
import io.sentry.android.replay.util.DebugOverlayDrawable
18-
import io.sentry.android.replay.util.MainLooperHandler
1918
import io.sentry.android.replay.util.addOnDrawListenerSafe
2019
import io.sentry.android.replay.util.removeOnDrawListenerSafe
2120
import java.io.File
2221
import java.lang.ref.WeakReference
23-
import java.util.concurrent.ScheduledExecutorService
2422
import java.util.concurrent.atomic.AtomicBoolean
2523
import kotlin.math.roundToInt
2624

@@ -29,8 +27,7 @@ import kotlin.math.roundToInt
2927
internal class ScreenshotRecorder(
3028
val config: ScreenshotRecorderConfig,
3129
val options: SentryOptions,
32-
val handler: MainLooperHandler,
33-
executorService: ScheduledExecutorService,
30+
val executorProvider: ExecutorProvider,
3431
screenshotRecorderCallback: ScreenshotRecorderCallback?,
3532
) : ViewTreeObserver.OnDrawListener {
3633
private var rootView: WeakReference<View>? = null
@@ -42,11 +39,10 @@ internal class ScreenshotRecorder(
4239
private val screenshotStrategy: ScreenshotStrategy =
4340
when (options.sessionReplay.screenshotStrategy) {
4441
ScreenshotStrategyType.CANVAS ->
45-
CanvasStrategy(executorService, screenshotRecorderCallback, options, config)
42+
CanvasStrategy(executorProvider, screenshotRecorderCallback, options, config)
4643
ScreenshotStrategyType.PIXEL_COPY ->
4744
PixelCopyStrategy(
48-
executorService,
49-
handler,
45+
executorProvider,
5046
screenshotRecorderCallback,
5147
options,
5248
config,

sentry-android-replay/src/main/java/io/sentry/android/replay/WindowRecorder.kt

Lines changed: 43 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ package io.sentry.android.replay
22

33
import android.annotation.TargetApi
44
import android.graphics.Point
5+
import android.os.Handler
6+
import android.os.HandlerThread
57
import android.view.View
68
import android.view.ViewTreeObserver
79
import io.sentry.SentryLevel.DEBUG
@@ -24,15 +26,20 @@ internal class WindowRecorder(
2426
private val windowCallback: WindowCallback,
2527
private val mainLooperHandler: MainLooperHandler,
2628
private val replayExecutor: ScheduledExecutorService,
27-
) : Recorder, OnRootViewsChangedListener {
29+
) : Recorder, OnRootViewsChangedListener, ExecutorProvider {
2830

2931
private val isRecording = AtomicBoolean(false)
3032
private val rootViews = ArrayList<WeakReference<View>>()
3133
private var lastKnownWindowSize: Point = Point()
3234
private val rootViewsLock = AutoClosableReentrantLock()
3335
private val capturerLock = AutoClosableReentrantLock()
36+
private val backgroundProcessingHandlerLock = AutoClosableReentrantLock()
37+
3438
@Volatile private var capturer: Capturer? = null
3539

40+
@Volatile private var backgroundProcessingHandlerThread: HandlerThread? = null
41+
@Volatile private var backgroundProcessingHandler: Handler? = null
42+
3643
private class Capturer(
3744
private val options: SentryOptions,
3845
private val mainLooperHandler: MainLooperHandler,
@@ -174,14 +181,7 @@ internal class WindowRecorder(
174181
}
175182

176183
capturer?.config = config
177-
capturer?.recorder =
178-
ScreenshotRecorder(
179-
config,
180-
options,
181-
mainLooperHandler,
182-
replayExecutor,
183-
screenshotRecorderCallback,
184-
)
184+
capturer?.recorder = ScreenshotRecorder(config, options, this, screenshotRecorderCallback)
185185

186186
val newRoot = rootViews.lastOrNull()?.get()
187187
if (newRoot != null) {
@@ -229,6 +229,40 @@ internal class WindowRecorder(
229229
override fun close() {
230230
reset()
231231
mainLooperHandler.removeCallbacks(capturer)
232+
backgroundProcessingHandlerLock.acquire().use {
233+
backgroundProcessingHandler?.removeCallbacksAndMessages(null)
234+
backgroundProcessingHandlerThread?.quitSafely()
235+
}
232236
stop()
233237
}
238+
239+
override fun getExecutor(): ScheduledExecutorService = replayExecutor
240+
241+
override fun getMainLooperHandler(): MainLooperHandler = mainLooperHandler
242+
243+
override fun getBackgroundHandler(): Handler {
244+
// only start the background thread if it's actually needed, as it's only used by Canvas Capture
245+
// Strategy
246+
if (backgroundProcessingHandler == null) {
247+
backgroundProcessingHandlerLock.acquire().use {
248+
if (backgroundProcessingHandler == null) {
249+
backgroundProcessingHandlerThread = HandlerThread("SentryReplayBackgroundProcessing")
250+
backgroundProcessingHandlerThread?.start()
251+
backgroundProcessingHandler = Handler(backgroundProcessingHandlerThread!!.looper)
252+
}
253+
}
254+
}
255+
return backgroundProcessingHandler!!
256+
}
257+
}
258+
259+
internal interface ExecutorProvider {
260+
/** Returns an executor suitable for background tasks. */
261+
fun getExecutor(): ScheduledExecutorService
262+
263+
/** Returns a handler associated with the main thread looper. */
264+
fun getMainLooperHandler(): MainLooperHandler
265+
266+
/** Returns a handler associated with a background thread looper. */
267+
fun getBackgroundHandler(): Handler
234268
}

0 commit comments

Comments
 (0)