Skip to content

Commit 2d3d7fe

Browse files
markushigetsentry-botromtsn
authored
[SR] Remove configuration from start() method (#4454)
* Remove configuration from start() method * Open up onConfigurationChanged for Hybrid SDKs * Address logging concerns * Format code * Cache last known config * Update sentry-android-replay/src/main/java/io/sentry/android/replay/capture/BaseCaptureStrategy.kt Co-authored-by: Roman Zavarnitsyn <rom4ek93@gmail.com> * Fix order * Fix compile issue --------- Co-authored-by: Sentry Github Bot <bot+github-bot@sentry.io> Co-authored-by: Roman Zavarnitsyn <rom4ek93@gmail.com>
1 parent b82bb0c commit 2d3d7fe

15 files changed

Lines changed: 189 additions & 185 deletions

File tree

sentry-android-replay/api/sentry-android-replay.api

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -34,10 +34,11 @@ public final class io/sentry/android/replay/ModifierExtensionsKt {
3434
}
3535

3636
public abstract interface class io/sentry/android/replay/Recorder : java/io/Closeable {
37+
public abstract fun onConfigurationChanged (Lio/sentry/android/replay/ScreenshotRecorderConfig;)V
3738
public abstract fun pause ()V
3839
public abstract fun reset ()V
3940
public abstract fun resume ()V
40-
public abstract fun start (Lio/sentry/android/replay/ScreenshotRecorderConfig;)V
41+
public abstract fun start ()V
4142
public abstract fun stop ()V
4243
}
4344

@@ -51,11 +52,11 @@ public final class io/sentry/android/replay/ReplayCache : java/io/Closeable {
5152
public static synthetic fun createVideoOf$default (Lio/sentry/android/replay/ReplayCache;JJIIIIILjava/io/File;ILjava/lang/Object;)Lio/sentry/android/replay/GeneratedVideo;
5253
}
5354

54-
public final class io/sentry/android/replay/ReplayIntegration : android/content/ComponentCallbacks, io/sentry/IConnectionStatusProvider$IConnectionStatusObserver, io/sentry/Integration, io/sentry/ReplayController, io/sentry/android/replay/ScreenshotRecorderCallback, io/sentry/android/replay/WindowCallback, io/sentry/android/replay/gestures/TouchRecorderCallback, io/sentry/transport/RateLimiter$IRateLimitObserver, java/io/Closeable {
55+
public final class io/sentry/android/replay/ReplayIntegration : io/sentry/IConnectionStatusProvider$IConnectionStatusObserver, io/sentry/Integration, io/sentry/ReplayController, io/sentry/android/replay/ScreenshotRecorderCallback, io/sentry/android/replay/WindowCallback, io/sentry/android/replay/gestures/TouchRecorderCallback, io/sentry/transport/RateLimiter$IRateLimitObserver, java/io/Closeable {
5556
public static final field $stable I
5657
public fun <init> (Landroid/content/Context;Lio/sentry/transport/ICurrentDateProvider;)V
57-
public fun <init> (Landroid/content/Context;Lio/sentry/transport/ICurrentDateProvider;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)V
58-
public synthetic fun <init> (Landroid/content/Context;Lio/sentry/transport/ICurrentDateProvider;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
58+
public fun <init> (Landroid/content/Context;Lio/sentry/transport/ICurrentDateProvider;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function1;)V
59+
public synthetic fun <init> (Landroid/content/Context;Lio/sentry/transport/ICurrentDateProvider;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function1;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
5960
public fun captureReplay (Ljava/lang/Boolean;)V
6061
public fun close ()V
6162
public fun disableDebugMaskingOverlay ()V
@@ -65,9 +66,8 @@ public final class io/sentry/android/replay/ReplayIntegration : android/content/
6566
public fun getReplayId ()Lio/sentry/protocol/SentryId;
6667
public fun isDebugMaskingOverlayEnabled ()Z
6768
public fun isRecording ()Z
68-
public fun onConfigurationChanged (Landroid/content/res/Configuration;)V
69+
public final fun onConfigurationChanged (Lio/sentry/android/replay/ScreenshotRecorderConfig;)V
6970
public fun onConnectionStatusChanged (Lio/sentry/IConnectionStatusProvider$ConnectionStatus;)V
70-
public fun onLowMemory ()V
7171
public fun onRateLimitChanged (Lio/sentry/transport/RateLimiter;)V
7272
public fun onScreenshotRecorded (Landroid/graphics/Bitmap;)V
7373
public fun onScreenshotRecorded (Ljava/io/File;J)V

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

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,9 @@ public interface Recorder : Closeable {
88
* at which the screenshots should be taken, and the screenshots size/resolution, which can
99
* change e.g. in the case of orientation change or window size change
1010
*/
11-
public fun start(recorderConfig: ScreenshotRecorderConfig)
11+
public fun start()
12+
13+
public fun onConfigurationChanged(config: ScreenshotRecorderConfig)
1214

1315
public fun resume()
1416

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

Lines changed: 15 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
package io.sentry.android.replay
22

3-
import android.content.ComponentCallbacks
43
import android.content.Context
5-
import android.content.res.Configuration
64
import android.graphics.Bitmap
75
import android.os.Build
86
import android.view.MotionEvent
@@ -60,14 +58,12 @@ public class ReplayIntegration(
6058
private val context: Context,
6159
private val dateProvider: ICurrentDateProvider,
6260
private val recorderProvider: (() -> Recorder)? = null,
63-
private val recorderConfigProvider: ((configChanged: Boolean) -> ScreenshotRecorderConfig)? = null,
6461
private val replayCacheProvider: ((replayId: SentryId) -> ReplayCache)? = null
6562
) : Integration,
6663
Closeable,
6764
ScreenshotRecorderCallback,
6865
TouchRecorderCallback,
6966
ReplayController,
70-
ComponentCallbacks,
7167
IConnectionStatusObserver,
7268
IRateLimitObserver,
7369
WindowCallback {
@@ -84,20 +80,18 @@ public class ReplayIntegration(
8480
context.appContext(),
8581
dateProvider,
8682
null,
87-
null,
8883
null
8984
)
9085

9186
internal constructor(
9287
context: Context,
9388
dateProvider: ICurrentDateProvider,
9489
recorderProvider: (() -> Recorder)?,
95-
recorderConfigProvider: ((configChanged: Boolean) -> ScreenshotRecorderConfig)?,
9690
replayCacheProvider: ((replayId: SentryId) -> ReplayCache)?,
9791
replayCaptureStrategyProvider: ((isFullSession: Boolean) -> CaptureStrategy)? = null,
9892
mainLooperHandler: MainLooperHandler? = null,
9993
gestureRecorderProvider: (() -> GestureRecorder)? = null
100-
) : this(context.appContext(), dateProvider, recorderProvider, recorderConfigProvider, replayCacheProvider) {
94+
) : this(context.appContext(), dateProvider, recorderProvider, replayCacheProvider) {
10195
this.replayCaptureStrategyProvider = replayCaptureStrategyProvider
10296
this.mainLooperHandler = mainLooperHandler ?: MainLooperHandler()
10397
this.gestureRecorderProvider = gestureRecorderProvider
@@ -146,16 +140,6 @@ public class ReplayIntegration(
146140

147141
options.connectionStatusProvider.addConnectionStatusObserver(this)
148142
scopes.rateLimiter?.addRateLimitObserver(this)
149-
if (options.sessionReplay.isTrackOrientationChange) {
150-
try {
151-
context.registerComponentCallbacks(this)
152-
} catch (e: Throwable) {
153-
options.logger.log(
154-
INFO,
155-
"ComponentCallbacks is not available, orientation changes won't be handled by Session replay"
156-
)
157-
}
158-
}
159143

160144
addIntegrationToSdkVersion("Replay")
161145

@@ -190,6 +174,9 @@ public class ReplayIntegration(
190174
} else {
191175
BufferCaptureStrategy(options, scopes, dateProvider, random, replayExecutor, replayCacheProvider)
192176
}
177+
recorder?.start()
178+
captureStrategy?.start()
179+
193180
registerRootViewListeners()
194181
}
195182
}
@@ -310,12 +297,6 @@ public class ReplayIntegration(
310297

311298
options.connectionStatusProvider.removeConnectionStatusObserver(this)
312299
scopes?.rateLimiter?.removeRateLimitObserver(this)
313-
if (options.sessionReplay.isTrackOrientationChange) {
314-
try {
315-
context.unregisterComponentCallbacks(this)
316-
} catch (ignored: Throwable) {
317-
}
318-
}
319300
stop()
320301
recorder?.close()
321302
recorder = null
@@ -325,17 +306,6 @@ public class ReplayIntegration(
325306
}
326307
}
327308

328-
override fun onConfigurationChanged(newConfig: Configuration) {
329-
if (!isEnabled.get() || !isRecording()) {
330-
return
331-
}
332-
333-
recorder?.stop()
334-
335-
// once the window size is determined
336-
// onWindowSizeChanged is triggered and we'll start the actual capturing
337-
}
338-
339309
override fun onConnectionStatusChanged(status: ConnectionStatus) {
340310
if (captureStrategy !is SessionCaptureStrategy) {
341311
// we only want to stop recording when offline for session mode
@@ -363,8 +333,6 @@ public class ReplayIntegration(
363333
}
364334
}
365335

366-
override fun onLowMemory(): Unit = Unit
367-
368336
override fun onTouchEvent(event: MotionEvent) {
369337
if (!isEnabled.get() || !lifecycle.isTouchRecordingAllowed()) {
370338
return
@@ -469,19 +437,19 @@ public class ReplayIntegration(
469437
if (!isEnabled.get() || !isRecording()) {
470438
return
471439
}
440+
if (options.sessionReplay.isTrackConfiguration) {
441+
val recorderConfig =
442+
ScreenshotRecorderConfig.fromSize(context, options.sessionReplay, width, height)
443+
onConfigurationChanged(recorderConfig)
444+
}
445+
}
472446

473-
recorder?.stop()
474-
475-
val recorderConfig = recorderConfigProvider?.invoke(true) ?: ScreenshotRecorderConfig.fromSize(context, options.sessionReplay, width, height)
476-
477-
captureStrategy?.let { capture ->
478-
if (capture.currentReplayId == SentryId.EMPTY_ID) {
479-
capture.start(recorderConfig)
480-
} else {
481-
capture.onConfigurationChanged(recorderConfig)
482-
}
447+
public fun onConfigurationChanged(config: ScreenshotRecorderConfig) {
448+
if (!isEnabled.get() || !isRecording()) {
449+
return
483450
}
484-
recorder?.start(recorderConfig)
451+
captureStrategy?.onConfigurationChanged(config)
452+
recorder?.onConfigurationChanged(config)
485453

486454
// we have to restart recorder with a new config and pause immediately if the replay is paused
487455
if (lifecycle.currentState == PAUSED) {

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

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -92,13 +92,17 @@ internal class WindowRecorder(
9292
}
9393
}
9494

95-
override fun start(recorderConfig: ScreenshotRecorderConfig) {
96-
if (isRecording.getAndSet(true)) {
95+
override fun start() {
96+
isRecording.getAndSet(true)
97+
}
98+
99+
override fun onConfigurationChanged(config: ScreenshotRecorderConfig) {
100+
if (!isRecording.get()) {
97101
return
98102
}
99103

100104
recorder = ScreenshotRecorder(
101-
recorderConfig,
105+
config,
102106
options,
103107
mainLooperHandler,
104108
replayExecutor,
@@ -115,7 +119,7 @@ internal class WindowRecorder(
115119
options,
116120
"$TAG.capture",
117121
100L, // delay the first run by a bit, to allow root view listener to register
118-
1000L / recorderConfig.frameRate,
122+
1000L / config.frameRate,
119123
MILLISECONDS
120124
) {
121125
recorder?.capture()

sentry-android-replay/src/main/java/io/sentry/android/replay/capture/BaseCaptureStrategy.kt

Lines changed: 9 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -61,10 +61,10 @@ internal abstract class BaseCaptureStrategy(
6161

6262
protected val isTerminating = AtomicBoolean(false)
6363
protected var cache: ReplayCache? = null
64-
protected var recorderConfig: ScreenshotRecorderConfig by persistableAtomic { _, _, newValue ->
64+
protected var recorderConfig: ScreenshotRecorderConfig? by persistableAtomicNullable(propertyName = "") { _, _, newValue ->
6565
if (newValue == null) {
6666
// recorderConfig is only nullable on init, but never after
67-
return@persistableAtomic
67+
return@persistableAtomicNullable
6868
}
6969
cache?.persistSegmentValues(SEGMENT_KEY_HEIGHT, newValue.recordingHeight.toString())
7070
cache?.persistSegmentValues(SEGMENT_KEY_WIDTH, newValue.recordingWidth.toString())
@@ -85,7 +85,6 @@ internal abstract class BaseCaptureStrategy(
8585
protected val currentEvents: Deque<RRWebEvent> = ConcurrentLinkedDeque()
8686

8787
override fun start(
88-
recorderConfig: ScreenshotRecorderConfig,
8988
segmentId: Int,
9089
replayId: SentryId,
9190
replayType: ReplayType?
@@ -95,7 +94,6 @@ internal abstract class BaseCaptureStrategy(
9594
this.currentReplayId = replayId
9695
this.currentSegment = segmentId
9796
this.replayType = replayType ?: (if (this is SessionCaptureStrategy) SESSION else BUFFER)
98-
this.recorderConfig = recorderConfig
9997

10098
segmentTimestamp = DateUtils.getCurrentDateTime()
10199
replayStartTimestamp.set(dateProvider.currentTimeMillis)
@@ -122,10 +120,10 @@ internal abstract class BaseCaptureStrategy(
122120
segmentId: Int,
123121
height: Int,
124122
width: Int,
123+
frameRate: Int,
124+
bitRate: Int,
125125
replayType: ReplayType = this.replayType,
126126
cache: ReplayCache? = this.cache,
127-
frameRate: Int = recorderConfig.frameRate,
128-
bitRate: Int = recorderConfig.bitRate,
129127
screenAtStart: String? = this.screenAtStart,
130128
breadcrumbs: List<Breadcrumb>? = null,
131129
events: Deque<RRWebEvent> = this.currentEvents
@@ -153,9 +151,11 @@ internal abstract class BaseCaptureStrategy(
153151
}
154152

155153
override fun onTouchEvent(event: MotionEvent) {
156-
val rrwebEvents = gestureConverter.convert(event, recorderConfig)
157-
if (rrwebEvents != null) {
158-
currentEvents += rrwebEvents
154+
recorderConfig?.let { config ->
155+
val rrwebEvents = gestureConverter.convert(event, config)
156+
if (rrwebEvents != null) {
157+
currentEvents += rrwebEvents
158+
}
159159
}
160160
}
161161

@@ -210,9 +210,4 @@ internal abstract class BaseCaptureStrategy(
210210
}
211211
): ReadWriteProperty<Any?, T> =
212212
persistableAtomicNullable<T>(initialValue, propertyName, onChange) as ReadWriteProperty<Any?, T>
213-
214-
private inline fun <T> persistableAtomic(
215-
crossinline onChange: (propertyName: String?, oldValue: T?, newValue: T?) -> Unit
216-
): ReadWriteProperty<Any?, T> =
217-
persistableAtomicNullable<T>(null, "", onChange) as ReadWriteProperty<Any?, T>
218213
}

sentry-android-replay/src/main/java/io/sentry/android/replay/capture/BufferCaptureStrategy.kt

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ internal class BufferCaptureStrategy(
131131
}
132132
// we hand over replayExecutor to the new strategy to preserve order of execution
133133
val captureStrategy = SessionCaptureStrategy(options, scopes, dateProvider, replayExecutor)
134-
captureStrategy.start(recorderConfig, segmentId = currentSegment, replayId = currentReplayId, replayType = BUFFER)
134+
captureStrategy.start(segmentId = currentSegment, replayId = currentReplayId, replayType = BUFFER)
135135
return captureStrategy
136136
}
137137

@@ -189,6 +189,14 @@ internal class BufferCaptureStrategy(
189189
}
190190

191191
private fun createCurrentSegment(taskName: String, onSegmentCreated: (ReplaySegment) -> Unit) {
192+
val currentConfig = recorderConfig
193+
if (currentConfig == null) {
194+
options.logger.log(
195+
DEBUG,
196+
"Recorder config is not set, not creating segment for task: $taskName"
197+
)
198+
return
199+
}
192200
val errorReplayDuration = options.sessionReplay.errorReplayDuration
193201
val now = dateProvider.currentTimeMillis
194202
val currentSegmentTimestamp = if (cache?.frames?.isNotEmpty() == true) {
@@ -200,12 +208,19 @@ internal class BufferCaptureStrategy(
200208
val segmentId = currentSegment
201209
val duration = now - currentSegmentTimestamp.time
202210
val replayId = currentReplayId
203-
val height = this.recorderConfig.recordingHeight
204-
val width = this.recorderConfig.recordingWidth
205211

206212
replayExecutor.submitSafely(options, "$TAG.$taskName") {
207213
val segment =
208-
createSegmentInternal(duration, currentSegmentTimestamp, replayId, segmentId, height, width)
214+
createSegmentInternal(
215+
duration,
216+
currentSegmentTimestamp,
217+
replayId,
218+
segmentId,
219+
currentConfig.recordingHeight,
220+
currentConfig.recordingWidth,
221+
currentConfig.frameRate,
222+
currentConfig.bitRate
223+
)
209224
onSegmentCreated(segment)
210225
}
211226
}

sentry-android-replay/src/main/java/io/sentry/android/replay/capture/CaptureStrategy.kt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@ internal interface CaptureStrategy {
3131
var segmentTimestamp: Date?
3232

3333
fun start(
34-
recorderConfig: ScreenshotRecorderConfig,
3534
segmentId: Int = 0,
3635
replayId: SentryId = SentryId(),
3736
replayType: ReplayType? = null

0 commit comments

Comments
 (0)