Skip to content

Commit 8b2351a

Browse files
committed
masking first try
1 parent 164dc72 commit 8b2351a

File tree

1 file changed

+51
-37
lines changed
  • sdk/@launchdarkly/observability-android/lib/src/main/kotlin/com/launchdarkly/observability/replay/capture

1 file changed

+51
-37
lines changed

sdk/@launchdarkly/observability-android/lib/src/main/kotlin/com/launchdarkly/observability/replay/capture/CaptureSource.kt

Lines changed: 51 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ class CaptureSource(
6363
val captureFlow: SharedFlow<CaptureEvent> = _captureEventFlow.asSharedFlow()
6464
private val windowInspector = WindowInspector(logger)
6565
private val maskCollector = MaskCollector(logger)
66-
private val beforeMasksPaint = Paint().apply {
66+
private val beforeMaskPaint = Paint().apply {
6767
color = Color.RED
6868
style = Paint.Style.FILL
6969
}
@@ -156,26 +156,23 @@ class CaptureSource(
156156

157157
// off the main thread to avoid blocking the UI thread
158158
return@withContext withContext(DispatcherProviderHolder.current.default) {
159-
if (!areMasksMapsStable(beforeMasks, afterMasks)) {
160-
return@withContext null
161-
}
162-
163159
val baseResult = captureResults[0] ?: return@withContext null
160+
val beforeMasks = areMasksMapsStable(beforeMasks, afterMasks) ?: return@withContext null
164161

165162
// if need to draw something on base bitmap additionally
166-
if (captureResults.size > 1 || beforeMasks.isNotEmpty()) {
163+
if (captureResults.size > 1 || afterMasks.isNotEmpty()) {
167164
val canvas = Canvas(baseResult.bitmap)
168-
// drawMasks(canvas, captureResults[0])
165+
drawMasks(canvas, beforeMasks[0], afterMasks[0])
169166

170-
for (res in captureResults.subList(1, captureResults.size)) {
171-
if (res == null) { continue }
167+
for (i in 1 until captureResults.size) {
168+
val res = captureResults[i] ?: continue
172169
val entry = res.windowEntry
173170
val dx = (entry.screenLeft - baseWindowEntry.screenLeft).toFloat()
174171
val dy = (entry.screenTop - baseWindowEntry.screenTop).toFloat()
175172

176173
canvas.withTranslation(dx, dy) {
177174
drawBitmap(res.bitmap, 0f, 0f, null)
178-
drawMasks(canvas, res)
175+
drawMasks(canvas, beforeMasks[i], afterMasks[i])
179176
}
180177
res.bitmap.recycle()
181178
}
@@ -319,69 +316,86 @@ class CaptureSource(
319316
}
320317

321318
/**
322-
* Applies masking rectangles to the provided [canvas] using the provided [masks].
319+
* Applies masking rectangles to the provided [canvas] using the provided [afterMasks].
323320
*
324321
* @param canvas The canvas to mask
325-
* @param masks areas that will be masked
322+
* @param afterMasks areas that will be masked
326323
*/
327-
private fun drawMasks(canvas: Canvas, captureResult: CaptureResult) {
328-
// val path = Path()
329-
// captureResult.beforeMasks.forEach { mask ->
330-
// mask.draw(path, canvas, beforeMasksPaint)
331-
// }
332-
// captureResult.afterMasks.forEach { mask ->
333-
// mask.draw(path, canvas, afterMaskPaint)
334-
// }
324+
// private fun drawMasks(canvas: Canvas, captureResult: CaptureResult) {
325+
//// val path = Path()
326+
//// captureResult.beforeMasks.forEach { mask ->
327+
//// mask.draw(path, canvas, beforeMasksPaint)
328+
//// }
329+
//// captureResult.afterMasks.forEach { mask ->
330+
//// mask.draw(path, canvas, afterMaskPaint)
331+
//// }
332+
// }
333+
334+
private fun drawMasks(canvas: Canvas, beforeMasks: List<Mask>?, afterMasks: List<Mask>?) {
335+
if (afterMasks == null && beforeMasks == null) return
336+
337+
val path = Path()
338+
beforeMasks?.forEach { mask ->
339+
mask.draw(path, canvas, beforeMaskPaint)
340+
}
341+
afterMasks?.forEach { mask ->
342+
mask.draw(path, canvas, afterMaskPaint)
343+
}
335344
}
336345

337346
fun areMasksMapsStable(
347+
338348
beforeMasksMap: Map<Int, List<Mask>>,
339349
afterMasksMap: Map<Int, List<Mask>>
340-
): Boolean {
350+
): Map<Int, List<Mask>>? {
341351
if (afterMasksMap.count() != beforeMasksMap.count()) {
342-
return false
352+
return null
343353
}
344354

345355
if (afterMasksMap.count() == 0) {
346-
return true
356+
return null
347357
}
348358

359+
val result = mutableMapOf<Int, List<Mask>>()
349360
for ((i, before) in beforeMasksMap) {
350-
val after = afterMasksMap[i] ?: return false
351-
if (!areMasksStable(before, after)) {
352-
return false
353-
}
361+
val after = afterMasksMap[i] ?: return null
362+
val merged = areMasksStable(before, after) ?: return null
363+
result[i] = merged
354364
}
355365

356-
return true
366+
return result
357367
}
358368

359369
fun areMasksStable(
360370
beforeMasks: List<Mask>,
361371
afterMasks: List<Mask>
362-
): Boolean {
372+
): List<Mask>? {
363373
if (afterMasks.count() != beforeMasks.count()) {
364-
return false
374+
return null
365375
}
366376

367377
if (afterMasks.count() == 0) {
368-
return true
378+
return listOf()
369379
}
370380

371-
val oneMaskTolerance = 4f
372-
val stabilityTolerance = 8f
381+
val oneMaskTolerance = 1f
382+
val stabilityTolerance = 40f
373383
var maxDiff = 0f
384+
var resultMasks = mutableListOf<Mask>()
374385
for ((before, after) in beforeMasks.zip(afterMasks)) {
375386
if (before.viewId != after.viewId) {
376-
return false
387+
return null
377388
}
378389
val bPoints = before.points
379390
if (bPoints != null) {
380-
val aPoints = after.points ?: return false
391+
val aPoints = after.points ?: return null
381392
for (i in bPoints.indices) {
382393
val diff = abs(aPoints[i] - bPoints[i])
383394
if (diff > stabilityTolerance) {
384-
return false
395+
return null
396+
}
397+
if (diff > oneMaskTolerance) {
398+
resultMasks += before
385399
}
386400
maxDiff = max(maxDiff, diff)
387401
}
@@ -392,6 +406,6 @@ class CaptureSource(
392406
if (maxDiff > 0) {
393407
Log.i("CaptureSource", "maxDiff = " + maxDiff)
394408
}
395-
return true
409+
return resultMasks
396410
}
397411
}

0 commit comments

Comments
 (0)