1
- package io.bitdrift.capture.replay
1
+ package io.bitdrift.capture.replay.internal
2
2
3
3
import android.content.Context
4
4
import android.graphics.Bitmap
@@ -9,8 +9,8 @@ import io.bitdrift.capture.common.DefaultClock
9
9
import io.bitdrift.capture.common.ErrorHandler
10
10
import io.bitdrift.capture.common.IClock
11
11
import io.bitdrift.capture.common.MainThreadHandler
12
- import io.bitdrift.capture.replay.internal.DisplayManagers
13
- import io.bitdrift.capture.replay.internal.WindowManager
12
+ import io.bitdrift.capture.replay.IScreenshotLogger
13
+ import io.bitdrift.capture.replay.ScreenshotCaptureMetrics
14
14
import java.io.ByteArrayOutputStream
15
15
import java.util.concurrent.Executors
16
16
import java.util.concurrent.ScheduledExecutorService
@@ -38,9 +38,10 @@ internal class ScreenshotCaptureEngine(
38
38
if (Build .VERSION .SDK_INT < Build .VERSION_CODES .UPSIDE_DOWN_CAKE ) {
39
39
return
40
40
}
41
- val startTime = clock.elapsedRealtime()
41
+ val startTimeMs = clock.elapsedRealtime()
42
+ // TODO(murki): Log empty screenshot on unblock the caller if there are no root views
42
43
val topView = windowManager.findRootViews().lastOrNull() ? : return
43
- // TODO(murki): Consider calling setDestinationBitmap() with a Bitmap.Config.RGB_565 instead
44
+ // TODO(murki): Reduce memory footprint by calling setDestinationBitmap() with a Bitmap.Config.RGB_565 instead
44
45
// of the default of Bitmap.Config.ARGB_8888
45
46
val screenshotRequest = PixelCopy .Request .Builder .ofWindow(topView).build()
46
47
PixelCopy .request(screenshotRequest, executor) { screenshotResult ->
@@ -50,28 +51,26 @@ internal class ScreenshotCaptureEngine(
50
51
return @request
51
52
}
52
53
53
- val screenshotTimeMs = clock.elapsedRealtime() - startTime
54
54
val resultBitmap = screenshotResult.bitmap
55
- Log .d(" miguel-Screenshot" , " Miguel-PixelCopy finished capture on thread=${Thread .currentThread().name} , " +
56
- " allocationByteCount=${resultBitmap.allocationByteCount} , " +
57
- " byteCount=${resultBitmap.byteCount} , " +
58
- " duration=$screenshotTimeMs " )
55
+ val metrics = ScreenshotCaptureMetrics (
56
+ screenshotTimeMs = clock.elapsedRealtime() - startTimeMs,
57
+ screenshotAllocationByteCount = resultBitmap.allocationByteCount,
58
+ screenshotByteCount = resultBitmap.byteCount
59
+ )
59
60
val stream = ByteArrayOutputStream ()
60
- // TODO(murki): Confirm the exact compression method used on iOS
61
- // Encode bitmap to bytearray while compressing it using JPEG=10 quality
61
+ // Encode bitmap to bytearray while compressing it using JPEG=10 quality to match iOS
62
62
resultBitmap.compress(Bitmap .CompressFormat .JPEG , 10 , stream)
63
63
resultBitmap.recycle()
64
64
// TODO (murki): Figure out if there's a more memory efficient way to do this
65
65
// see https://stackoverflow.com/questions/4989182/converting-java-bitmap-to-byte-array#comment36547795_4989543 and
66
66
// and https://gaumala.com/posts/2020-01-27-working-with-streams-kotlin.html
67
67
val screenshotBytes = stream.toByteArray()
68
- val compressDurationMs = clock.elapsedRealtime() - startTime - screenshotTimeMs
69
- val totalDurationMs = compressDurationMs + screenshotTimeMs
70
- Log .d(" miguel-Screenshot" , " Miguel-Finished compression on thread=${Thread .currentThread().name} , " +
71
- " screenshotBytes.size=${screenshotBytes.size} , " +
72
- " duration=$compressDurationMs , " +
73
- " totalDuration=$totalDurationMs " )
74
- logger.onScreenshotCaptured(screenshotBytes, totalDurationMs)
68
+ metrics.compressionTimeMs = clock.elapsedRealtime() - startTimeMs - metrics.screenshotTimeMs
69
+ metrics.compressionByteCount = screenshotBytes.size
70
+ Log .d(" miguel-Screenshot" , " Miguel-Finished screenshot operation on thread=${Thread .currentThread().name} , " +
71
+ " metrics=$metrics "
72
+ )
73
+ logger.onScreenshotCaptured(screenshotBytes, metrics)
75
74
}
76
75
77
76
}
0 commit comments