diff --git a/dd-sdk-android-internal/api/apiSurface b/dd-sdk-android-internal/api/apiSurface index f80629999a..597d40934f 100644 --- a/dd-sdk-android-internal/api/apiSurface +++ b/dd-sdk-android-internal/api/apiSurface @@ -29,6 +29,12 @@ sealed class com.datadog.android.internal.telemetry.InternalTelemetryEvent constructor(Boolean, Boolean, Boolean, MutableMap<String, Any?> = mutableMapOf()) object InterceptorInstantiated : InternalTelemetryEvent fun ByteArray.toHexString(): String +object com.datadog.android.internal.utils.ImageViewUtils + fun resolveParentRectAbsPosition(android.view.View): android.graphics.Rect + fun calculateClipping(android.graphics.Rect, android.graphics.Rect, Float): android.graphics.Rect + fun resolveContentRectWithScaling(android.widget.ImageView, android.graphics.drawable.Drawable): android.graphics.Rect +fun Int.densityNormalized(Float): Int +fun Long.densityNormalized(Float): Long fun Throwable.loggableStackTrace(): String annotation com.datadog.tools.annotation.NoOpImplementation constructor(Boolean = false) diff --git a/dd-sdk-android-internal/api/dd-sdk-android-internal.api b/dd-sdk-android-internal/api/dd-sdk-android-internal.api index a6ae5b9963..f15b234506 100644 --- a/dd-sdk-android-internal/api/dd-sdk-android-internal.api +++ b/dd-sdk-android-internal/api/dd-sdk-android-internal.api @@ -108,6 +108,21 @@ public final class com/datadog/android/internal/utils/ByteArrayExtKt { public static final fun toHexString ([B)Ljava/lang/String; } +public final class com/datadog/android/internal/utils/ImageViewUtils { + public static final field INSTANCE Lcom/datadog/android/internal/utils/ImageViewUtils; + public final fun calculateClipping (Landroid/graphics/Rect;Landroid/graphics/Rect;F)Landroid/graphics/Rect; + public final fun resolveContentRectWithScaling (Landroid/widget/ImageView;Landroid/graphics/drawable/Drawable;)Landroid/graphics/Rect; + public final fun resolveParentRectAbsPosition (Landroid/view/View;)Landroid/graphics/Rect; +} + +public final class com/datadog/android/internal/utils/IntExtKt { + public static final fun densityNormalized (IF)I +} + +public final class com/datadog/android/internal/utils/LongExtKt { + public static final fun densityNormalized (JF)J +} + public final class com/datadog/android/internal/utils/ThrowableExtKt { public static final fun loggableStackTrace (Ljava/lang/Throwable;)Ljava/lang/String; } diff --git a/features/dd-sdk-android-session-replay/src/main/kotlin/com/datadog/android/sessionreplay/internal/utils/ImageViewUtils.kt b/dd-sdk-android-internal/src/main/java/com/datadog/android/internal/utils/ImageViewUtils.kt similarity index 84% rename from features/dd-sdk-android-session-replay/src/main/kotlin/com/datadog/android/sessionreplay/internal/utils/ImageViewUtils.kt rename to dd-sdk-android-internal/src/main/java/com/datadog/android/internal/utils/ImageViewUtils.kt index d5ca9d6b26..b8a35b3496 100644 --- a/features/dd-sdk-android-session-replay/src/main/kotlin/com/datadog/android/sessionreplay/internal/utils/ImageViewUtils.kt +++ b/dd-sdk-android-internal/src/main/java/com/datadog/android/internal/utils/ImageViewUtils.kt @@ -4,17 +4,25 @@ * Copyright 2016-Present Datadog, Inc. */ -package com.datadog.android.sessionreplay.internal.utils +package com.datadog.android.internal.utils import android.graphics.Rect import android.graphics.drawable.Drawable import android.view.View import android.widget.ImageView -import com.datadog.android.sessionreplay.internal.recorder.densityNormalized -import com.datadog.android.sessionreplay.model.MobileSegment -internal object ImageViewUtils { - internal fun resolveParentRectAbsPosition(view: View): Rect { +/** + * A collection of view utility functions for resolving absolute + * positions, clipping bounds, and other useful data for + * image views operations. + */ +object ImageViewUtils { + /** + * Resolves the absolute position on the screen of the given [View]. + * @param view: the [View]. + * @return the [Rect] representing the absolute position of the view. + */ + fun resolveParentRectAbsPosition(view: View): Rect { val coords = IntArray(2) // this will always have size >= 2 @Suppress("UnsafeThirdPartyFunctionCall") @@ -31,7 +39,15 @@ internal object ImageViewUtils { ) } - internal fun calculateClipping(parentRect: Rect, childRect: Rect, density: Float): MobileSegment.WireframeClip { + /** + * Calculates the clipping [Rect] of the given child [Rect] using its parent [Rect] and + * the screen density. + * @param parentRect: the parent [Rect]. + * @param childRect: the child [Rect]. + * @param density: the screen density. + * @return the clipping [Rect]. + */ + fun calculateClipping(parentRect: Rect, childRect: Rect, density: Float): Rect { val left = if (childRect.left < parentRect.left) { parentRect.left - childRect.left } else { @@ -52,16 +68,21 @@ internal object ImageViewUtils { } else { 0 } - - return MobileSegment.WireframeClip( - left = left.densityNormalized(density).toLong(), - top = top.densityNormalized(density).toLong(), - right = right.densityNormalized(density).toLong(), - bottom = bottom.densityNormalized(density).toLong() + return Rect( + left.densityNormalized(density), + top.densityNormalized(density), + right.densityNormalized(density), + bottom.densityNormalized(density) ) } - internal fun resolveContentRectWithScaling( + /** + * Resolves the [Drawable] content [Rect] using the given [ImageView] scale type. + * @param imageView: the [ImageView]. + * @param drawable: the [Drawable]. + * @return the resolved content [Rect]. + */ + fun resolveContentRectWithScaling( imageView: ImageView, drawable: Drawable ): Rect { diff --git a/features/dd-sdk-android-session-replay/src/main/kotlin/com/datadog/android/sessionreplay/internal/recorder/IntExt.kt b/dd-sdk-android-internal/src/main/java/com/datadog/android/internal/utils/IntExt.kt similarity index 83% rename from features/dd-sdk-android-session-replay/src/main/kotlin/com/datadog/android/sessionreplay/internal/recorder/IntExt.kt rename to dd-sdk-android-internal/src/main/java/com/datadog/android/internal/utils/IntExt.kt index 59d515a40e..04d5528f34 100644 --- a/features/dd-sdk-android-session-replay/src/main/kotlin/com/datadog/android/sessionreplay/internal/recorder/IntExt.kt +++ b/dd-sdk-android-internal/src/main/java/com/datadog/android/internal/utils/IntExt.kt @@ -4,7 +4,7 @@ * Copyright 2016-Present Datadog, Inc. */ -package com.datadog.android.sessionreplay.internal.recorder +package com.datadog.android.internal.utils /** * Normalizes an Int value (font size, view dimension, view position, etc.) according with the @@ -13,7 +13,7 @@ package com.datadog.android.sessionreplay.internal.recorder * view.height/2. * @param density */ -internal fun Int.densityNormalized(density: Float): Int { +fun Int.densityNormalized(density: Float): Int { if (density == 0f) { return this } diff --git a/features/dd-sdk-android-session-replay/src/main/kotlin/com/datadog/android/sessionreplay/internal/recorder/LongExt.kt b/dd-sdk-android-internal/src/main/java/com/datadog/android/internal/utils/LongExt.kt similarity index 83% rename from features/dd-sdk-android-session-replay/src/main/kotlin/com/datadog/android/sessionreplay/internal/recorder/LongExt.kt rename to dd-sdk-android-internal/src/main/java/com/datadog/android/internal/utils/LongExt.kt index 53e04d322e..b057e92220 100644 --- a/features/dd-sdk-android-session-replay/src/main/kotlin/com/datadog/android/sessionreplay/internal/recorder/LongExt.kt +++ b/dd-sdk-android-internal/src/main/java/com/datadog/android/internal/utils/LongExt.kt @@ -4,7 +4,7 @@ * Copyright 2016-Present Datadog, Inc. */ -package com.datadog.android.sessionreplay.internal.recorder +package com.datadog.android.internal.utils /** * Normalizes a Long value (font size, view dimension, view position, etc.) according with the @@ -13,7 +13,7 @@ package com.datadog.android.sessionreplay.internal.recorder * view.height/2. * @param density */ -internal fun Long.densityNormalized(density: Float): Long { +fun Long.densityNormalized(density: Float): Long { if (density == 0f) { return this } diff --git a/features/dd-sdk-android-session-replay/api/apiSurface b/features/dd-sdk-android-session-replay/api/apiSurface index ef2ead17ba..ad23691fd8 100644 --- a/features/dd-sdk-android-session-replay/api/apiSurface +++ b/features/dd-sdk-android-session-replay/api/apiSurface @@ -59,10 +59,6 @@ interface com.datadog.android.sessionreplay.internal.recorder.obfuscator.StringO fun obfuscate(String): String companion object fun getStringObfuscator(): StringObfuscator -class com.datadog.android.sessionreplay.internal.recorder.resources.DefaultDrawableCopier : DrawableCopier - override fun copy(android.graphics.drawable.Drawable, android.content.res.Resources): android.graphics.drawable.Drawable? -interface com.datadog.android.sessionreplay.internal.recorder.resources.DrawableCopier - fun copy(android.graphics.drawable.Drawable, android.content.res.Resources): android.graphics.drawable.Drawable? data class com.datadog.android.sessionreplay.recorder.MappingContext constructor(SystemInformation, com.datadog.android.sessionreplay.utils.ImageWireframeHelper, com.datadog.android.sessionreplay.TextAndInputPrivacy, com.datadog.android.sessionreplay.ImagePrivacy, Boolean = false) interface com.datadog.android.sessionreplay.recorder.OptionSelectorDetector @@ -70,7 +66,11 @@ interface com.datadog.android.sessionreplay.recorder.OptionSelectorDetector data class com.datadog.android.sessionreplay.recorder.SystemInformation constructor(com.datadog.android.sessionreplay.utils.GlobalBounds, Int = Configuration.ORIENTATION_UNDEFINED, Float, String? = null) abstract class com.datadog.android.sessionreplay.recorder.mapper.BaseAsyncBackgroundWireframeMapper<T: android.view.View> : BaseWireframeMapper<T> + constructor(com.datadog.android.sessionreplay.utils.ViewIdentifierResolver, com.datadog.android.sessionreplay.utils.ColorStringFormatter, com.datadog.android.sessionreplay.utils.ViewBoundsResolver, com.datadog.android.sessionreplay.utils.DrawableToColorMapper) override fun map(T, com.datadog.android.sessionreplay.recorder.MappingContext, com.datadog.android.sessionreplay.utils.AsyncJobStatusCallback, com.datadog.android.api.InternalLogger): List<com.datadog.android.sessionreplay.model.MobileSegment.Wireframe> + protected open fun resolveViewBackground(android.view.View, com.datadog.android.sessionreplay.recorder.MappingContext, com.datadog.android.sessionreplay.utils.AsyncJobStatusCallback, com.datadog.android.api.InternalLogger): com.datadog.android.sessionreplay.model.MobileSegment.Wireframe? + protected open fun resolveBackgroundAsShapeWireframe(android.view.View, com.datadog.android.sessionreplay.utils.GlobalBounds, Int, Int, com.datadog.android.sessionreplay.model.MobileSegment.ShapeStyle?): com.datadog.android.sessionreplay.model.MobileSegment.Wireframe.ShapeWireframe? + protected open fun resolveBackgroundAsImageWireframe(android.view.View, com.datadog.android.sessionreplay.utils.GlobalBounds, Int, Int, com.datadog.android.sessionreplay.recorder.MappingContext, com.datadog.android.sessionreplay.utils.AsyncJobStatusCallback): com.datadog.android.sessionreplay.model.MobileSegment.Wireframe? companion object open class com.datadog.android.sessionreplay.recorder.mapper.BaseViewGroupMapper<T: android.view.ViewGroup> : BaseAsyncBackgroundWireframeMapper<T>, TraverseAllChildrenMapper<T> constructor(com.datadog.android.sessionreplay.utils.ViewIdentifierResolver, com.datadog.android.sessionreplay.utils.ColorStringFormatter, com.datadog.android.sessionreplay.utils.ViewBoundsResolver, com.datadog.android.sessionreplay.utils.DrawableToColorMapper) @@ -83,7 +83,7 @@ class com.datadog.android.sessionreplay.recorder.mapper.EditTextMapper : TextVie override fun resolveCapturedText(android.widget.EditText, com.datadog.android.sessionreplay.TextAndInputPrivacy, Boolean): String companion object open class com.datadog.android.sessionreplay.recorder.mapper.ImageViewMapper : BaseAsyncBackgroundWireframeMapper<android.widget.ImageView> - constructor(com.datadog.android.sessionreplay.utils.ViewIdentifierResolver, com.datadog.android.sessionreplay.utils.ColorStringFormatter, com.datadog.android.sessionreplay.utils.ViewBoundsResolver, com.datadog.android.sessionreplay.utils.DrawableToColorMapper) + constructor(com.datadog.android.sessionreplay.utils.ViewIdentifierResolver, com.datadog.android.sessionreplay.utils.ColorStringFormatter, com.datadog.android.sessionreplay.utils.ViewBoundsResolver, com.datadog.android.sessionreplay.utils.DrawableToColorMapper, com.datadog.android.sessionreplay.recorder.resources.DrawableCopier) override fun map(android.widget.ImageView, com.datadog.android.sessionreplay.recorder.MappingContext, com.datadog.android.sessionreplay.utils.AsyncJobStatusCallback, com.datadog.android.api.InternalLogger): List<com.datadog.android.sessionreplay.model.MobileSegment.Wireframe> open class com.datadog.android.sessionreplay.recorder.mapper.TextViewMapper<T: android.widget.TextView> : BaseAsyncBackgroundWireframeMapper<T> constructor(com.datadog.android.sessionreplay.utils.ViewIdentifierResolver, com.datadog.android.sessionreplay.utils.ColorStringFormatter, com.datadog.android.sessionreplay.utils.ViewBoundsResolver, com.datadog.android.sessionreplay.utils.DrawableToColorMapper) @@ -93,6 +93,10 @@ open class com.datadog.android.sessionreplay.recorder.mapper.TextViewMapper<T: a interface com.datadog.android.sessionreplay.recorder.mapper.TraverseAllChildrenMapper<T: android.view.ViewGroup> : WireframeMapper<T> interface com.datadog.android.sessionreplay.recorder.mapper.WireframeMapper<T: android.view.View> fun map(T, com.datadog.android.sessionreplay.recorder.MappingContext, com.datadog.android.sessionreplay.utils.AsyncJobStatusCallback, com.datadog.android.api.InternalLogger): List<com.datadog.android.sessionreplay.model.MobileSegment.Wireframe> +class com.datadog.android.sessionreplay.recorder.resources.DefaultDrawableCopier : DrawableCopier + override fun copy(android.graphics.drawable.Drawable, android.content.res.Resources): android.graphics.drawable.Drawable? +interface com.datadog.android.sessionreplay.recorder.resources.DrawableCopier + fun copy(android.graphics.drawable.Drawable, android.content.res.Resources): android.graphics.drawable.Drawable? open class com.datadog.android.sessionreplay.utils.AndroidMDrawableToColorMapper : LegacyDrawableToColorMapper constructor(List<DrawableToColorMapper> = emptyList()) override fun resolveRippleDrawable(android.graphics.drawable.RippleDrawable, com.datadog.android.api.InternalLogger): Int? @@ -126,7 +130,7 @@ data class com.datadog.android.sessionreplay.utils.GlobalBounds constructor(Long, Long, Long, Long) interface com.datadog.android.sessionreplay.utils.ImageWireframeHelper fun createImageWireframeByBitmap(Long, GlobalBounds, android.graphics.Bitmap, Float, Boolean, com.datadog.android.sessionreplay.ImagePrivacy, AsyncJobStatusCallback, com.datadog.android.sessionreplay.model.MobileSegment.WireframeClip? = null, com.datadog.android.sessionreplay.model.MobileSegment.ShapeStyle? = null, com.datadog.android.sessionreplay.model.MobileSegment.ShapeBorder? = null): com.datadog.android.sessionreplay.model.MobileSegment.Wireframe? - fun createImageWireframeByDrawable(android.view.View, com.datadog.android.sessionreplay.ImagePrivacy, Int, Long, Long, Int, Int, Boolean, android.graphics.drawable.Drawable, com.datadog.android.sessionreplay.internal.recorder.resources.DrawableCopier = DefaultDrawableCopier(), AsyncJobStatusCallback, com.datadog.android.sessionreplay.model.MobileSegment.WireframeClip? = null, com.datadog.android.sessionreplay.model.MobileSegment.ShapeStyle? = null, com.datadog.android.sessionreplay.model.MobileSegment.ShapeBorder? = null, String? = DRAWABLE_CHILD_NAME, String?): com.datadog.android.sessionreplay.model.MobileSegment.Wireframe? + fun createImageWireframeByDrawable(android.view.View, com.datadog.android.sessionreplay.ImagePrivacy, Int, Long, Long, Int, Int, Boolean, android.graphics.drawable.Drawable, com.datadog.android.sessionreplay.recorder.resources.DrawableCopier = DefaultDrawableCopier(), AsyncJobStatusCallback, com.datadog.android.sessionreplay.model.MobileSegment.WireframeClip? = null, com.datadog.android.sessionreplay.model.MobileSegment.ShapeStyle? = null, com.datadog.android.sessionreplay.model.MobileSegment.ShapeBorder? = null, String? = DRAWABLE_CHILD_NAME, String?): com.datadog.android.sessionreplay.model.MobileSegment.Wireframe? fun createCompoundDrawableWireframes(android.widget.TextView, com.datadog.android.sessionreplay.recorder.MappingContext, Int, String?, AsyncJobStatusCallback): MutableList<com.datadog.android.sessionreplay.model.MobileSegment.Wireframe> companion object open class com.datadog.android.sessionreplay.utils.LegacyDrawableToColorMapper : DrawableToColorMapper diff --git a/features/dd-sdk-android-session-replay/api/dd-sdk-android-session-replay.api b/features/dd-sdk-android-session-replay/api/dd-sdk-android-session-replay.api index 08d8e85f4b..cd5b8ca7e0 100644 --- a/features/dd-sdk-android-session-replay/api/dd-sdk-android-session-replay.api +++ b/features/dd-sdk-android-session-replay/api/dd-sdk-android-session-replay.api @@ -117,15 +117,6 @@ public final class com/datadog/android/sessionreplay/internal/recorder/obfuscato public final fun getStringObfuscator ()Lcom/datadog/android/sessionreplay/internal/recorder/obfuscator/StringObfuscator; } -public final class com/datadog/android/sessionreplay/internal/recorder/resources/DefaultDrawableCopier : com/datadog/android/sessionreplay/internal/recorder/resources/DrawableCopier { - public fun <init> ()V - public fun copy (Landroid/graphics/drawable/Drawable;Landroid/content/res/Resources;)Landroid/graphics/drawable/Drawable; -} - -public abstract interface class com/datadog/android/sessionreplay/internal/recorder/resources/DrawableCopier { - public abstract fun copy (Landroid/graphics/drawable/Drawable;Landroid/content/res/Resources;)Landroid/graphics/drawable/Drawable; -} - public final class com/datadog/android/sessionreplay/model/MobileSegment { public static final field Companion Lcom/datadog/android/sessionreplay/model/MobileSegment$Companion; public fun <init> (Lcom/datadog/android/sessionreplay/model/MobileSegment$Application;Lcom/datadog/android/sessionreplay/model/MobileSegment$Session;Lcom/datadog/android/sessionreplay/model/MobileSegment$View;JJJLjava/lang/Long;Ljava/lang/Boolean;Lcom/datadog/android/sessionreplay/model/MobileSegment$Source;Ljava/util/List;)V @@ -1453,7 +1444,11 @@ public final class com/datadog/android/sessionreplay/recorder/SystemInformation public abstract class com/datadog/android/sessionreplay/recorder/mapper/BaseAsyncBackgroundWireframeMapper : com/datadog/android/sessionreplay/recorder/mapper/BaseWireframeMapper { public static final field Companion Lcom/datadog/android/sessionreplay/recorder/mapper/BaseAsyncBackgroundWireframeMapper$Companion; + public fun <init> (Lcom/datadog/android/sessionreplay/utils/ViewIdentifierResolver;Lcom/datadog/android/sessionreplay/utils/ColorStringFormatter;Lcom/datadog/android/sessionreplay/utils/ViewBoundsResolver;Lcom/datadog/android/sessionreplay/utils/DrawableToColorMapper;)V public fun map (Landroid/view/View;Lcom/datadog/android/sessionreplay/recorder/MappingContext;Lcom/datadog/android/sessionreplay/utils/AsyncJobStatusCallback;Lcom/datadog/android/api/InternalLogger;)Ljava/util/List; + protected fun resolveBackgroundAsImageWireframe (Landroid/view/View;Lcom/datadog/android/sessionreplay/utils/GlobalBounds;IILcom/datadog/android/sessionreplay/recorder/MappingContext;Lcom/datadog/android/sessionreplay/utils/AsyncJobStatusCallback;)Lcom/datadog/android/sessionreplay/model/MobileSegment$Wireframe; + protected fun resolveBackgroundAsShapeWireframe (Landroid/view/View;Lcom/datadog/android/sessionreplay/utils/GlobalBounds;IILcom/datadog/android/sessionreplay/model/MobileSegment$ShapeStyle;)Lcom/datadog/android/sessionreplay/model/MobileSegment$Wireframe$ShapeWireframe; + protected fun resolveViewBackground (Landroid/view/View;Lcom/datadog/android/sessionreplay/recorder/MappingContext;Lcom/datadog/android/sessionreplay/utils/AsyncJobStatusCallback;Lcom/datadog/android/api/InternalLogger;)Lcom/datadog/android/sessionreplay/model/MobileSegment$Wireframe; } public final class com/datadog/android/sessionreplay/recorder/mapper/BaseAsyncBackgroundWireframeMapper$Companion { @@ -1483,7 +1478,7 @@ public final class com/datadog/android/sessionreplay/recorder/mapper/EditTextMap } public class com/datadog/android/sessionreplay/recorder/mapper/ImageViewMapper : com/datadog/android/sessionreplay/recorder/mapper/BaseAsyncBackgroundWireframeMapper { - public fun <init> (Lcom/datadog/android/sessionreplay/utils/ViewIdentifierResolver;Lcom/datadog/android/sessionreplay/utils/ColorStringFormatter;Lcom/datadog/android/sessionreplay/utils/ViewBoundsResolver;Lcom/datadog/android/sessionreplay/utils/DrawableToColorMapper;)V + public fun <init> (Lcom/datadog/android/sessionreplay/utils/ViewIdentifierResolver;Lcom/datadog/android/sessionreplay/utils/ColorStringFormatter;Lcom/datadog/android/sessionreplay/utils/ViewBoundsResolver;Lcom/datadog/android/sessionreplay/utils/DrawableToColorMapper;Lcom/datadog/android/sessionreplay/recorder/resources/DrawableCopier;)V public synthetic fun map (Landroid/view/View;Lcom/datadog/android/sessionreplay/recorder/MappingContext;Lcom/datadog/android/sessionreplay/utils/AsyncJobStatusCallback;Lcom/datadog/android/api/InternalLogger;)Ljava/util/List; public fun map (Landroid/widget/ImageView;Lcom/datadog/android/sessionreplay/recorder/MappingContext;Lcom/datadog/android/sessionreplay/utils/AsyncJobStatusCallback;Lcom/datadog/android/api/InternalLogger;)Ljava/util/List; } @@ -1503,6 +1498,15 @@ public abstract interface class com/datadog/android/sessionreplay/recorder/mappe public abstract fun map (Landroid/view/View;Lcom/datadog/android/sessionreplay/recorder/MappingContext;Lcom/datadog/android/sessionreplay/utils/AsyncJobStatusCallback;Lcom/datadog/android/api/InternalLogger;)Ljava/util/List; } +public final class com/datadog/android/sessionreplay/recorder/resources/DefaultDrawableCopier : com/datadog/android/sessionreplay/recorder/resources/DrawableCopier { + public fun <init> ()V + public fun copy (Landroid/graphics/drawable/Drawable;Landroid/content/res/Resources;)Landroid/graphics/drawable/Drawable; +} + +public abstract interface class com/datadog/android/sessionreplay/recorder/resources/DrawableCopier { + public abstract fun copy (Landroid/graphics/drawable/Drawable;Landroid/content/res/Resources;)Landroid/graphics/drawable/Drawable; +} + public class com/datadog/android/sessionreplay/utils/AndroidMDrawableToColorMapper : com/datadog/android/sessionreplay/utils/LegacyDrawableToColorMapper { public fun <init> ()V public fun <init> (Ljava/util/List;)V @@ -1586,7 +1590,7 @@ public abstract interface class com/datadog/android/sessionreplay/utils/ImageWir public static final field Companion Lcom/datadog/android/sessionreplay/utils/ImageWireframeHelper$Companion; public abstract fun createCompoundDrawableWireframes (Landroid/widget/TextView;Lcom/datadog/android/sessionreplay/recorder/MappingContext;ILjava/lang/String;Lcom/datadog/android/sessionreplay/utils/AsyncJobStatusCallback;)Ljava/util/List; public abstract fun createImageWireframeByBitmap (JLcom/datadog/android/sessionreplay/utils/GlobalBounds;Landroid/graphics/Bitmap;FZLcom/datadog/android/sessionreplay/ImagePrivacy;Lcom/datadog/android/sessionreplay/utils/AsyncJobStatusCallback;Lcom/datadog/android/sessionreplay/model/MobileSegment$WireframeClip;Lcom/datadog/android/sessionreplay/model/MobileSegment$ShapeStyle;Lcom/datadog/android/sessionreplay/model/MobileSegment$ShapeBorder;)Lcom/datadog/android/sessionreplay/model/MobileSegment$Wireframe; - public abstract fun createImageWireframeByDrawable (Landroid/view/View;Lcom/datadog/android/sessionreplay/ImagePrivacy;IJJIIZLandroid/graphics/drawable/Drawable;Lcom/datadog/android/sessionreplay/internal/recorder/resources/DrawableCopier;Lcom/datadog/android/sessionreplay/utils/AsyncJobStatusCallback;Lcom/datadog/android/sessionreplay/model/MobileSegment$WireframeClip;Lcom/datadog/android/sessionreplay/model/MobileSegment$ShapeStyle;Lcom/datadog/android/sessionreplay/model/MobileSegment$ShapeBorder;Ljava/lang/String;Ljava/lang/String;)Lcom/datadog/android/sessionreplay/model/MobileSegment$Wireframe; + public abstract fun createImageWireframeByDrawable (Landroid/view/View;Lcom/datadog/android/sessionreplay/ImagePrivacy;IJJIIZLandroid/graphics/drawable/Drawable;Lcom/datadog/android/sessionreplay/recorder/resources/DrawableCopier;Lcom/datadog/android/sessionreplay/utils/AsyncJobStatusCallback;Lcom/datadog/android/sessionreplay/model/MobileSegment$WireframeClip;Lcom/datadog/android/sessionreplay/model/MobileSegment$ShapeStyle;Lcom/datadog/android/sessionreplay/model/MobileSegment$ShapeBorder;Ljava/lang/String;Ljava/lang/String;)Lcom/datadog/android/sessionreplay/model/MobileSegment$Wireframe; } public final class com/datadog/android/sessionreplay/utils/ImageWireframeHelper$Companion { @@ -1594,7 +1598,7 @@ public final class com/datadog/android/sessionreplay/utils/ImageWireframeHelper$ public final class com/datadog/android/sessionreplay/utils/ImageWireframeHelper$DefaultImpls { public static synthetic fun createImageWireframeByBitmap$default (Lcom/datadog/android/sessionreplay/utils/ImageWireframeHelper;JLcom/datadog/android/sessionreplay/utils/GlobalBounds;Landroid/graphics/Bitmap;FZLcom/datadog/android/sessionreplay/ImagePrivacy;Lcom/datadog/android/sessionreplay/utils/AsyncJobStatusCallback;Lcom/datadog/android/sessionreplay/model/MobileSegment$WireframeClip;Lcom/datadog/android/sessionreplay/model/MobileSegment$ShapeStyle;Lcom/datadog/android/sessionreplay/model/MobileSegment$ShapeBorder;ILjava/lang/Object;)Lcom/datadog/android/sessionreplay/model/MobileSegment$Wireframe; - public static synthetic fun createImageWireframeByDrawable$default (Lcom/datadog/android/sessionreplay/utils/ImageWireframeHelper;Landroid/view/View;Lcom/datadog/android/sessionreplay/ImagePrivacy;IJJIIZLandroid/graphics/drawable/Drawable;Lcom/datadog/android/sessionreplay/internal/recorder/resources/DrawableCopier;Lcom/datadog/android/sessionreplay/utils/AsyncJobStatusCallback;Lcom/datadog/android/sessionreplay/model/MobileSegment$WireframeClip;Lcom/datadog/android/sessionreplay/model/MobileSegment$ShapeStyle;Lcom/datadog/android/sessionreplay/model/MobileSegment$ShapeBorder;Ljava/lang/String;Ljava/lang/String;ILjava/lang/Object;)Lcom/datadog/android/sessionreplay/model/MobileSegment$Wireframe; + public static synthetic fun createImageWireframeByDrawable$default (Lcom/datadog/android/sessionreplay/utils/ImageWireframeHelper;Landroid/view/View;Lcom/datadog/android/sessionreplay/ImagePrivacy;IJJIIZLandroid/graphics/drawable/Drawable;Lcom/datadog/android/sessionreplay/recorder/resources/DrawableCopier;Lcom/datadog/android/sessionreplay/utils/AsyncJobStatusCallback;Lcom/datadog/android/sessionreplay/model/MobileSegment$WireframeClip;Lcom/datadog/android/sessionreplay/model/MobileSegment$ShapeStyle;Lcom/datadog/android/sessionreplay/model/MobileSegment$ShapeBorder;Ljava/lang/String;Ljava/lang/String;ILjava/lang/Object;)Lcom/datadog/android/sessionreplay/model/MobileSegment$Wireframe; } public class com/datadog/android/sessionreplay/utils/LegacyDrawableToColorMapper : com/datadog/android/sessionreplay/utils/DrawableToColorMapper { diff --git a/features/dd-sdk-android-session-replay/src/main/kotlin/com/datadog/android/sessionreplay/internal/DefaultRecorderProvider.kt b/features/dd-sdk-android-session-replay/src/main/kotlin/com/datadog/android/sessionreplay/internal/DefaultRecorderProvider.kt index bbe80d462c..d73d4e15b3 100644 --- a/features/dd-sdk-android-session-replay/src/main/kotlin/com/datadog/android/sessionreplay/internal/DefaultRecorderProvider.kt +++ b/features/dd-sdk-android-session-replay/src/main/kotlin/com/datadog/android/sessionreplay/internal/DefaultRecorderProvider.kt @@ -22,6 +22,7 @@ import android.widget.TextView import androidx.appcompat.widget.ActionBarContainer import androidx.appcompat.widget.SwitchCompat import com.datadog.android.api.feature.FeatureSdkCore +import com.datadog.android.internal.utils.ImageViewUtils import com.datadog.android.sessionreplay.ImagePrivacy import com.datadog.android.sessionreplay.MapperTypeWrapper import com.datadog.android.sessionreplay.TextAndInputPrivacy @@ -41,12 +42,12 @@ import com.datadog.android.sessionreplay.internal.resources.ResourceDataStoreMan import com.datadog.android.sessionreplay.internal.storage.RecordWriter import com.datadog.android.sessionreplay.internal.storage.ResourcesWriter import com.datadog.android.sessionreplay.internal.time.SessionReplayTimeProvider -import com.datadog.android.sessionreplay.internal.utils.ImageViewUtils import com.datadog.android.sessionreplay.recorder.OptionSelectorDetector import com.datadog.android.sessionreplay.recorder.mapper.EditTextMapper import com.datadog.android.sessionreplay.recorder.mapper.ImageViewMapper import com.datadog.android.sessionreplay.recorder.mapper.TextViewMapper import com.datadog.android.sessionreplay.recorder.mapper.WireframeMapper +import com.datadog.android.sessionreplay.recorder.resources.DefaultDrawableCopier import com.datadog.android.sessionreplay.utils.ColorStringFormatter import com.datadog.android.sessionreplay.utils.DefaultColorStringFormatter import com.datadog.android.sessionreplay.utils.DefaultViewBoundsResolver @@ -101,7 +102,8 @@ internal class DefaultRecorderProvider( colorStringFormatter = colorStringFormatter, viewBoundsResolver = viewBoundsResolver, drawableToColorMapper = drawableToColorMapper, - imageViewUtils = ImageViewUtils + imageViewUtils = ImageViewUtils, + drawableCopier = DefaultDrawableCopier() ) val textViewMapper = TextViewMapper<TextView>( viewIdentifierResolver, diff --git a/features/dd-sdk-android-session-replay/src/main/kotlin/com/datadog/android/sessionreplay/internal/recorder/ViewUtilsInternal.kt b/features/dd-sdk-android-session-replay/src/main/kotlin/com/datadog/android/sessionreplay/internal/recorder/ViewUtilsInternal.kt index 41bca26faa..dd9f119ab0 100644 --- a/features/dd-sdk-android-session-replay/src/main/kotlin/com/datadog/android/sessionreplay/internal/recorder/ViewUtilsInternal.kt +++ b/features/dd-sdk-android-session-replay/src/main/kotlin/com/datadog/android/sessionreplay/internal/recorder/ViewUtilsInternal.kt @@ -12,6 +12,7 @@ import android.view.View import android.view.ViewStub import androidx.appcompat.widget.ActionBarContextView import androidx.appcompat.widget.Toolbar +import com.datadog.android.internal.utils.densityNormalized import com.datadog.android.sessionreplay.internal.recorder.resources.DefaultImageWireframeHelper import com.datadog.android.sessionreplay.utils.GlobalBounds diff --git a/features/dd-sdk-android-session-replay/src/main/kotlin/com/datadog/android/sessionreplay/internal/recorder/callback/RecorderWindowCallback.kt b/features/dd-sdk-android-session-replay/src/main/kotlin/com/datadog/android/sessionreplay/internal/recorder/callback/RecorderWindowCallback.kt index 40293a5ae4..0c60391473 100644 --- a/features/dd-sdk-android-session-replay/src/main/kotlin/com/datadog/android/sessionreplay/internal/recorder/callback/RecorderWindowCallback.kt +++ b/features/dd-sdk-android-session-replay/src/main/kotlin/com/datadog/android/sessionreplay/internal/recorder/callback/RecorderWindowCallback.kt @@ -12,13 +12,13 @@ import android.view.MotionEvent import android.view.Window import androidx.annotation.MainThread import com.datadog.android.api.InternalLogger +import com.datadog.android.internal.utils.densityNormalized import com.datadog.android.sessionreplay.ImagePrivacy import com.datadog.android.sessionreplay.TextAndInputPrivacy import com.datadog.android.sessionreplay.internal.TouchPrivacyManager import com.datadog.android.sessionreplay.internal.async.RecordedDataQueueHandler import com.datadog.android.sessionreplay.internal.recorder.ViewOnDrawInterceptor import com.datadog.android.sessionreplay.internal.recorder.WindowInspector -import com.datadog.android.sessionreplay.internal.recorder.densityNormalized import com.datadog.android.sessionreplay.internal.utils.TimeProvider import com.datadog.android.sessionreplay.model.MobileSegment import java.util.LinkedList diff --git a/features/dd-sdk-android-session-replay/src/main/kotlin/com/datadog/android/sessionreplay/internal/recorder/mapper/BasePickerMapper.kt b/features/dd-sdk-android-session-replay/src/main/kotlin/com/datadog/android/sessionreplay/internal/recorder/mapper/BasePickerMapper.kt index 712a2b6dfd..7031d33ea7 100644 --- a/features/dd-sdk-android-session-replay/src/main/kotlin/com/datadog/android/sessionreplay/internal/recorder/mapper/BasePickerMapper.kt +++ b/features/dd-sdk-android-session-replay/src/main/kotlin/com/datadog/android/sessionreplay/internal/recorder/mapper/BasePickerMapper.kt @@ -9,7 +9,7 @@ package com.datadog.android.sessionreplay.internal.recorder.mapper import android.os.Build import android.widget.NumberPicker import androidx.annotation.RequiresApi -import com.datadog.android.sessionreplay.internal.recorder.densityNormalized +import com.datadog.android.internal.utils.densityNormalized import com.datadog.android.sessionreplay.model.MobileSegment import com.datadog.android.sessionreplay.recorder.mapper.BaseWireframeMapper import com.datadog.android.sessionreplay.utils.ColorStringFormatter diff --git a/features/dd-sdk-android-session-replay/src/main/kotlin/com/datadog/android/sessionreplay/internal/recorder/mapper/CheckableCompoundButtonMapper.kt b/features/dd-sdk-android-session-replay/src/main/kotlin/com/datadog/android/sessionreplay/internal/recorder/mapper/CheckableCompoundButtonMapper.kt index 1d057ff9a9..8cc7d1f449 100644 --- a/features/dd-sdk-android-session-replay/src/main/kotlin/com/datadog/android/sessionreplay/internal/recorder/mapper/CheckableCompoundButtonMapper.kt +++ b/features/dd-sdk-android-session-replay/src/main/kotlin/com/datadog/android/sessionreplay/internal/recorder/mapper/CheckableCompoundButtonMapper.kt @@ -12,7 +12,7 @@ import android.os.Build import android.widget.CompoundButton import androidx.annotation.UiThread import com.datadog.android.api.InternalLogger -import com.datadog.android.sessionreplay.internal.recorder.densityNormalized +import com.datadog.android.internal.utils.densityNormalized import com.datadog.android.sessionreplay.recorder.mapper.TextViewMapper import com.datadog.android.sessionreplay.utils.ColorStringFormatter import com.datadog.android.sessionreplay.utils.DrawableToColorMapper diff --git a/features/dd-sdk-android-session-replay/src/main/kotlin/com/datadog/android/sessionreplay/internal/recorder/mapper/CheckableTextViewMapper.kt b/features/dd-sdk-android-session-replay/src/main/kotlin/com/datadog/android/sessionreplay/internal/recorder/mapper/CheckableTextViewMapper.kt index ab75a3f988..c4fb1f894b 100644 --- a/features/dd-sdk-android-session-replay/src/main/kotlin/com/datadog/android/sessionreplay/internal/recorder/mapper/CheckableTextViewMapper.kt +++ b/features/dd-sdk-android-session-replay/src/main/kotlin/com/datadog/android/sessionreplay/internal/recorder/mapper/CheckableTextViewMapper.kt @@ -11,10 +11,10 @@ import android.widget.Checkable import android.widget.TextView import androidx.annotation.UiThread import com.datadog.android.api.InternalLogger -import com.datadog.android.sessionreplay.internal.recorder.resources.DrawableCopier import com.datadog.android.sessionreplay.model.MobileSegment import com.datadog.android.sessionreplay.recorder.MappingContext import com.datadog.android.sessionreplay.recorder.mapper.TextViewMapper +import com.datadog.android.sessionreplay.recorder.resources.DrawableCopier import com.datadog.android.sessionreplay.utils.AsyncJobStatusCallback import com.datadog.android.sessionreplay.utils.ColorStringFormatter import com.datadog.android.sessionreplay.utils.DrawableToColorMapper diff --git a/features/dd-sdk-android-session-replay/src/main/kotlin/com/datadog/android/sessionreplay/internal/recorder/mapper/CheckedTextViewMapper.kt b/features/dd-sdk-android-session-replay/src/main/kotlin/com/datadog/android/sessionreplay/internal/recorder/mapper/CheckedTextViewMapper.kt index 05222776c7..9b788120bc 100644 --- a/features/dd-sdk-android-session-replay/src/main/kotlin/com/datadog/android/sessionreplay/internal/recorder/mapper/CheckedTextViewMapper.kt +++ b/features/dd-sdk-android-session-replay/src/main/kotlin/com/datadog/android/sessionreplay/internal/recorder/mapper/CheckedTextViewMapper.kt @@ -10,7 +10,7 @@ import android.graphics.drawable.Drawable import android.graphics.drawable.DrawableContainer import android.widget.CheckedTextView import androidx.annotation.UiThread -import com.datadog.android.sessionreplay.internal.recorder.densityNormalized +import com.datadog.android.internal.utils.densityNormalized import com.datadog.android.sessionreplay.recorder.mapper.TextViewMapper import com.datadog.android.sessionreplay.utils.ColorStringFormatter import com.datadog.android.sessionreplay.utils.DrawableToColorMapper diff --git a/features/dd-sdk-android-session-replay/src/main/kotlin/com/datadog/android/sessionreplay/internal/recorder/mapper/ProgressBarWireframeMapper.kt b/features/dd-sdk-android-session-replay/src/main/kotlin/com/datadog/android/sessionreplay/internal/recorder/mapper/ProgressBarWireframeMapper.kt index 621cc5e6fb..f5ba0fdfc8 100644 --- a/features/dd-sdk-android-session-replay/src/main/kotlin/com/datadog/android/sessionreplay/internal/recorder/mapper/ProgressBarWireframeMapper.kt +++ b/features/dd-sdk-android-session-replay/src/main/kotlin/com/datadog/android/sessionreplay/internal/recorder/mapper/ProgressBarWireframeMapper.kt @@ -14,8 +14,8 @@ import android.widget.ProgressBar import androidx.annotation.RequiresApi import androidx.annotation.UiThread import com.datadog.android.api.InternalLogger +import com.datadog.android.internal.utils.densityNormalized import com.datadog.android.sessionreplay.TextAndInputPrivacy -import com.datadog.android.sessionreplay.internal.recorder.densityNormalized import com.datadog.android.sessionreplay.model.MobileSegment import com.datadog.android.sessionreplay.recorder.MappingContext import com.datadog.android.sessionreplay.recorder.mapper.BaseAsyncBackgroundWireframeMapper diff --git a/features/dd-sdk-android-session-replay/src/main/kotlin/com/datadog/android/sessionreplay/internal/recorder/mapper/SeekBarWireframeMapper.kt b/features/dd-sdk-android-session-replay/src/main/kotlin/com/datadog/android/sessionreplay/internal/recorder/mapper/SeekBarWireframeMapper.kt index c2cd516288..e3cce77f8e 100644 --- a/features/dd-sdk-android-session-replay/src/main/kotlin/com/datadog/android/sessionreplay/internal/recorder/mapper/SeekBarWireframeMapper.kt +++ b/features/dd-sdk-android-session-replay/src/main/kotlin/com/datadog/android/sessionreplay/internal/recorder/mapper/SeekBarWireframeMapper.kt @@ -8,8 +8,8 @@ package com.datadog.android.sessionreplay.internal.recorder.mapper import android.widget.SeekBar import com.datadog.android.api.InternalLogger +import com.datadog.android.internal.utils.densityNormalized import com.datadog.android.sessionreplay.TextAndInputPrivacy -import com.datadog.android.sessionreplay.internal.recorder.densityNormalized import com.datadog.android.sessionreplay.model.MobileSegment import com.datadog.android.sessionreplay.recorder.MappingContext import com.datadog.android.sessionreplay.utils.AsyncJobStatusCallback diff --git a/features/dd-sdk-android-session-replay/src/main/kotlin/com/datadog/android/sessionreplay/internal/recorder/mapper/SwitchCompatMapper.kt b/features/dd-sdk-android-session-replay/src/main/kotlin/com/datadog/android/sessionreplay/internal/recorder/mapper/SwitchCompatMapper.kt index 603ff000c1..c25c7ce16d 100644 --- a/features/dd-sdk-android-session-replay/src/main/kotlin/com/datadog/android/sessionreplay/internal/recorder/mapper/SwitchCompatMapper.kt +++ b/features/dd-sdk-android-session-replay/src/main/kotlin/com/datadog/android/sessionreplay/internal/recorder/mapper/SwitchCompatMapper.kt @@ -9,11 +9,11 @@ package com.datadog.android.sessionreplay.internal.recorder.mapper import androidx.annotation.UiThread import androidx.appcompat.widget.SwitchCompat import com.datadog.android.api.InternalLogger -import com.datadog.android.sessionreplay.internal.recorder.densityNormalized -import com.datadog.android.sessionreplay.internal.recorder.resources.DrawableCopier +import com.datadog.android.internal.utils.densityNormalized import com.datadog.android.sessionreplay.model.MobileSegment import com.datadog.android.sessionreplay.recorder.MappingContext import com.datadog.android.sessionreplay.recorder.mapper.TextViewMapper +import com.datadog.android.sessionreplay.recorder.resources.DrawableCopier import com.datadog.android.sessionreplay.utils.AsyncJobStatusCallback import com.datadog.android.sessionreplay.utils.ColorStringFormatter import com.datadog.android.sessionreplay.utils.DrawableToColorMapper diff --git a/features/dd-sdk-android-session-replay/src/main/kotlin/com/datadog/android/sessionreplay/internal/recorder/resources/DefaultImageWireframeHelper.kt b/features/dd-sdk-android-session-replay/src/main/kotlin/com/datadog/android/sessionreplay/internal/recorder/resources/DefaultImageWireframeHelper.kt index e915659362..d9bae6304e 100644 --- a/features/dd-sdk-android-session-replay/src/main/kotlin/com/datadog/android/sessionreplay/internal/recorder/resources/DefaultImageWireframeHelper.kt +++ b/features/dd-sdk-android-session-replay/src/main/kotlin/com/datadog/android/sessionreplay/internal/recorder/resources/DefaultImageWireframeHelper.kt @@ -15,11 +15,12 @@ import android.widget.TextView import androidx.annotation.UiThread import androidx.annotation.VisibleForTesting import com.datadog.android.api.InternalLogger +import com.datadog.android.internal.utils.densityNormalized import com.datadog.android.sessionreplay.ImagePrivacy import com.datadog.android.sessionreplay.internal.recorder.ViewUtilsInternal -import com.datadog.android.sessionreplay.internal.recorder.densityNormalized import com.datadog.android.sessionreplay.model.MobileSegment import com.datadog.android.sessionreplay.recorder.MappingContext +import com.datadog.android.sessionreplay.recorder.resources.DrawableCopier import com.datadog.android.sessionreplay.utils.AsyncJobStatusCallback import com.datadog.android.sessionreplay.utils.GlobalBounds import com.datadog.android.sessionreplay.utils.ImageWireframeHelper diff --git a/features/dd-sdk-android-session-replay/src/main/kotlin/com/datadog/android/sessionreplay/internal/recorder/resources/ImageTypeResolver.kt b/features/dd-sdk-android-session-replay/src/main/kotlin/com/datadog/android/sessionreplay/internal/recorder/resources/ImageTypeResolver.kt index a414a0849b..4417eb3927 100644 --- a/features/dd-sdk-android-session-replay/src/main/kotlin/com/datadog/android/sessionreplay/internal/recorder/resources/ImageTypeResolver.kt +++ b/features/dd-sdk-android-session-replay/src/main/kotlin/com/datadog/android/sessionreplay/internal/recorder/resources/ImageTypeResolver.kt @@ -9,7 +9,7 @@ package com.datadog.android.sessionreplay.internal.recorder.resources import android.graphics.drawable.Drawable import android.graphics.drawable.GradientDrawable import androidx.annotation.VisibleForTesting -import com.datadog.android.sessionreplay.internal.recorder.densityNormalized +import com.datadog.android.internal.utils.densityNormalized internal class ImageTypeResolver { fun isDrawablePII(drawable: Drawable, density: Float): Boolean { diff --git a/features/dd-sdk-android-session-replay/src/main/kotlin/com/datadog/android/sessionreplay/internal/recorder/resources/ResourceResolver.kt b/features/dd-sdk-android-session-replay/src/main/kotlin/com/datadog/android/sessionreplay/internal/recorder/resources/ResourceResolver.kt index de04810994..0ff79eaeb5 100644 --- a/features/dd-sdk-android-session-replay/src/main/kotlin/com/datadog/android/sessionreplay/internal/recorder/resources/ResourceResolver.kt +++ b/features/dd-sdk-android-session-replay/src/main/kotlin/com/datadog/android/sessionreplay/internal/recorder/resources/ResourceResolver.kt @@ -18,6 +18,7 @@ import com.datadog.android.api.InternalLogger import com.datadog.android.core.internal.utils.executeSafe import com.datadog.android.sessionreplay.internal.async.DataQueueHandler import com.datadog.android.sessionreplay.internal.utils.DrawableUtils +import com.datadog.android.sessionreplay.recorder.resources.DrawableCopier import java.util.concurrent.ExecutorService import java.util.concurrent.LinkedBlockingDeque import java.util.concurrent.ThreadPoolExecutor @@ -110,8 +111,8 @@ internal class ResourceResolver( // do in the background threadPoolExecutor.executeSafe("resolveResourceId", logger) { createBitmap( - resources = resources, drawable = originalDrawable, + copiedDrawable = copiedDrawable, drawableWidth = drawableWidth, drawableHeight = drawableHeight, displayMetrics = displayMetrics, @@ -137,8 +138,8 @@ internal class ResourceResolver( @WorkerThread private fun createBitmap( - resources: Resources, drawable: Drawable, + copiedDrawable: Drawable, drawableWidth: Int, drawableHeight: Int, displayMetrics: DisplayMetrics, @@ -148,7 +149,7 @@ internal class ResourceResolver( ) { val handledBitmap = if (bitmapFromDrawable != null) { tryToGetBitmapFromBitmapDrawable( - drawable = drawable as BitmapDrawable, + drawable = drawable, bitmapFromDrawable = bitmapFromDrawable, customResourceIdCacheKey = customResourceIdCacheKey, resolveResourceCallback = resolveResourceCallback @@ -159,8 +160,7 @@ internal class ResourceResolver( if (handledBitmap == null) { tryToDrawNewBitmap( - resources = resources, - drawable = drawable, + drawable = copiedDrawable, drawableWidth = drawableWidth, drawableHeight = drawableHeight, displayMetrics = displayMetrics, @@ -249,7 +249,6 @@ internal class ResourceResolver( @WorkerThread private fun tryToDrawNewBitmap( - resources: Resources, drawable: Drawable, drawableWidth: Int, drawableHeight: Int, @@ -258,7 +257,6 @@ internal class ResourceResolver( resolveResourceCallback: ResolveResourceCallback ) { drawableUtils.createBitmapOfApproxSizeFromDrawable( - resources = resources, drawable = drawable, drawableWidth = drawableWidth, drawableHeight = drawableHeight, @@ -295,7 +293,7 @@ internal class ResourceResolver( @WorkerThread @Suppress("ReturnCount") private fun tryToGetBitmapFromBitmapDrawable( - drawable: BitmapDrawable, + drawable: Drawable, bitmapFromDrawable: Bitmap, customResourceIdCacheKey: String?, resolveResourceCallback: ResolveResourceCallback diff --git a/features/dd-sdk-android-session-replay/src/main/kotlin/com/datadog/android/sessionreplay/internal/utils/DrawableUtils.kt b/features/dd-sdk-android-session-replay/src/main/kotlin/com/datadog/android/sessionreplay/internal/utils/DrawableUtils.kt index 49eebf59ea..1e6dadf165 100644 --- a/features/dd-sdk-android-session-replay/src/main/kotlin/com/datadog/android/sessionreplay/internal/utils/DrawableUtils.kt +++ b/features/dd-sdk-android-session-replay/src/main/kotlin/com/datadog/android/sessionreplay/internal/utils/DrawableUtils.kt @@ -6,7 +6,6 @@ package com.datadog.android.sessionreplay.internal.utils -import android.content.res.Resources import android.graphics.Bitmap import android.graphics.Bitmap.Config import android.graphics.Color @@ -39,7 +38,6 @@ internal class DrawableUtils( */ @WorkerThread internal fun createBitmapOfApproxSizeFromDrawable( - resources: Resources, drawable: Drawable, drawableWidth: Int, drawableHeight: Int, @@ -59,7 +57,6 @@ internal class DrawableUtils( override fun onSuccess(bitmap: Bitmap) { executorService.submitSafe("drawOnCanvas", internalLogger) { drawOnCanvas( - resources, bitmap, drawable, bitmapCreationCallback @@ -103,27 +100,21 @@ internal class DrawableUtils( @WorkerThread private fun drawOnCanvas( - resources: Resources, bitmap: Bitmap, drawable: Drawable, bitmapCreationCallback: ResourceResolver.BitmapCreationCallback ) { - // don't use the original drawable - it will affect the view hierarchy - val newDrawable = drawable.constantState?.newDrawable(resources)?.apply { - // `constantState` contains only immutable properties of drawable,the state needs to be set manually - setState(drawable.current.state) - } val canvas = canvasWrapper.createCanvas(bitmap) - if (canvas == null || newDrawable == null) { + if (canvas == null) { bitmapCreationCallback.onFailure() } else { // erase the canvas // needed because overdrawing an already used bitmap causes unusual visual artifacts canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.MULTIPLY) - newDrawable.setBounds(0, 0, canvas.width, canvas.height) - newDrawable.draw(canvas) + drawable.setBounds(0, 0, canvas.width, canvas.height) + drawable.draw(canvas) bitmapCreationCallback.onReady(bitmap) } } diff --git a/features/dd-sdk-android-session-replay/src/main/kotlin/com/datadog/android/sessionreplay/internal/utils/MiscUtils.kt b/features/dd-sdk-android-session-replay/src/main/kotlin/com/datadog/android/sessionreplay/internal/utils/MiscUtils.kt index 96a7859abb..324d7db542 100644 --- a/features/dd-sdk-android-session-replay/src/main/kotlin/com/datadog/android/sessionreplay/internal/utils/MiscUtils.kt +++ b/features/dd-sdk-android-session-replay/src/main/kotlin/com/datadog/android/sessionreplay/internal/utils/MiscUtils.kt @@ -13,7 +13,7 @@ import android.os.Build import android.util.TypedValue import android.view.WindowManager import com.datadog.android.api.InternalLogger -import com.datadog.android.sessionreplay.internal.recorder.densityNormalized +import com.datadog.android.internal.utils.densityNormalized import com.datadog.android.sessionreplay.recorder.SystemInformation import com.datadog.android.sessionreplay.utils.DefaultColorStringFormatter import com.datadog.android.sessionreplay.utils.GlobalBounds diff --git a/features/dd-sdk-android-session-replay/src/main/kotlin/com/datadog/android/sessionreplay/internal/utils/RectExt.kt b/features/dd-sdk-android-session-replay/src/main/kotlin/com/datadog/android/sessionreplay/internal/utils/RectExt.kt new file mode 100644 index 0000000000..d60e440d7f --- /dev/null +++ b/features/dd-sdk-android-session-replay/src/main/kotlin/com/datadog/android/sessionreplay/internal/utils/RectExt.kt @@ -0,0 +1,19 @@ +/* + * Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0. + * This product includes software developed at Datadog (https://www.datadoghq.com/). + * Copyright 2016-Present Datadog, Inc. + */ + +package com.datadog.android.sessionreplay.internal.utils + +import android.graphics.Rect +import com.datadog.android.sessionreplay.model.MobileSegment + +internal fun Rect.toWireframeClip(): MobileSegment.WireframeClip { + return MobileSegment.WireframeClip( + this.top.toLong(), + this.bottom.toLong(), + this.left.toLong(), + this.right.toLong() + ) +} diff --git a/features/dd-sdk-android-session-replay/src/main/kotlin/com/datadog/android/sessionreplay/recorder/mapper/BaseAsyncBackgroundWireframeMapper.kt b/features/dd-sdk-android-session-replay/src/main/kotlin/com/datadog/android/sessionreplay/recorder/mapper/BaseAsyncBackgroundWireframeMapper.kt index e3f4cad38a..7d64174f59 100644 --- a/features/dd-sdk-android-session-replay/src/main/kotlin/com/datadog/android/sessionreplay/recorder/mapper/BaseAsyncBackgroundWireframeMapper.kt +++ b/features/dd-sdk-android-session-replay/src/main/kotlin/com/datadog/android/sessionreplay/recorder/mapper/BaseAsyncBackgroundWireframeMapper.kt @@ -9,7 +9,7 @@ package com.datadog.android.sessionreplay.recorder.mapper import android.view.View import androidx.annotation.UiThread import com.datadog.android.api.InternalLogger -import com.datadog.android.sessionreplay.internal.recorder.densityNormalized +import com.datadog.android.internal.utils.densityNormalized import com.datadog.android.sessionreplay.model.MobileSegment import com.datadog.android.sessionreplay.recorder.MappingContext import com.datadog.android.sessionreplay.utils.AsyncJobStatusCallback @@ -31,7 +31,7 @@ import com.datadog.android.sessionreplay.utils.ViewIdentifierResolver * @param viewBoundsResolver the [ViewBoundsResolver] to get a view boundaries in density independent units * @param drawableToColorMapper the [DrawableToColorMapper] to convert a background drawable into a solid color */ -abstract class BaseAsyncBackgroundWireframeMapper<in T : View> internal constructor( +abstract class BaseAsyncBackgroundWireframeMapper<in T : View> ( viewIdentifierResolver: ViewIdentifierResolver, colorStringFormatter: ColorStringFormatter, viewBoundsResolver: ViewBoundsResolver, @@ -57,8 +57,16 @@ abstract class BaseAsyncBackgroundWireframeMapper<in T : View> internal construc return backgroundWireframe?.let { listOf(it) } ?: emptyList() } + /** + * Function used to resolve the Wireframe to represent the view background, based on its type. + * + * @param view the [View] to map + * @param mappingContext the [MappingContext] which contains contextual data, useful for mapping. + * @param asyncJobStatusCallback the [AsyncJobStatusCallback] callback used for internal async operations. + * @param internalLogger the [InternalLogger], used for internal logging. + */ @UiThread - private fun resolveViewBackground( + protected open fun resolveViewBackground( view: View, mappingContext: MappingContext, asyncJobStatusCallback: AsyncJobStatusCallback, @@ -90,7 +98,16 @@ abstract class BaseAsyncBackgroundWireframeMapper<in T : View> internal construc } } - private fun resolveBackgroundAsShapeWireframe( + /** + * Function used to resolve the view background as a Shape wireframe. + * + * @param view the [View] to map + * @param bounds the [GlobalBounds] of the view. + * @param width the view width. + * @param height the view height. + * @param shapeStyle the optional [MobileSegment.ShapeStyle] to use. + */ + protected open fun resolveBackgroundAsShapeWireframe( view: View, bounds: GlobalBounds, width: Int, @@ -115,8 +132,18 @@ abstract class BaseAsyncBackgroundWireframeMapper<in T : View> internal construc ) } + /** + * Function used to resolve the view background as a Image wireframe. + * + * @param view the [View] to map + * @param bounds the [GlobalBounds] of the view. + * @param width the view width. + * @param height the view height. + * @param mappingContext the [MappingContext] which contains contextual data, useful for mapping. + * @param asyncJobStatusCallback the [AsyncJobStatusCallback] callback used for internal async operations. + */ @UiThread - private fun resolveBackgroundAsImageWireframe( + protected open fun resolveBackgroundAsImageWireframe( view: View, bounds: GlobalBounds, width: Int, diff --git a/features/dd-sdk-android-session-replay/src/main/kotlin/com/datadog/android/sessionreplay/recorder/mapper/ImageViewMapper.kt b/features/dd-sdk-android-session-replay/src/main/kotlin/com/datadog/android/sessionreplay/recorder/mapper/ImageViewMapper.kt index 4d5b9a16c1..b080a898df 100644 --- a/features/dd-sdk-android-session-replay/src/main/kotlin/com/datadog/android/sessionreplay/recorder/mapper/ImageViewMapper.kt +++ b/features/dd-sdk-android-session-replay/src/main/kotlin/com/datadog/android/sessionreplay/recorder/mapper/ImageViewMapper.kt @@ -9,10 +9,12 @@ package com.datadog.android.sessionreplay.recorder.mapper import android.widget.ImageView import androidx.annotation.UiThread import com.datadog.android.api.InternalLogger -import com.datadog.android.sessionreplay.internal.recorder.densityNormalized -import com.datadog.android.sessionreplay.internal.utils.ImageViewUtils +import com.datadog.android.internal.utils.ImageViewUtils +import com.datadog.android.internal.utils.densityNormalized +import com.datadog.android.sessionreplay.internal.utils.toWireframeClip import com.datadog.android.sessionreplay.model.MobileSegment import com.datadog.android.sessionreplay.recorder.MappingContext +import com.datadog.android.sessionreplay.recorder.resources.DrawableCopier import com.datadog.android.sessionreplay.utils.AsyncJobStatusCallback import com.datadog.android.sessionreplay.utils.ColorStringFormatter import com.datadog.android.sessionreplay.utils.DrawableToColorMapper @@ -25,19 +27,22 @@ import com.datadog.android.sessionreplay.utils.ViewIdentifierResolver */ open class ImageViewMapper : BaseAsyncBackgroundWireframeMapper<ImageView> { private val imageViewUtils: ImageViewUtils + private val drawableCopier: DrawableCopier @Suppress("Unused") // used by external mappers constructor( viewIdentifierResolver: ViewIdentifierResolver, colorStringFormatter: ColorStringFormatter, viewBoundsResolver: ViewBoundsResolver, - drawableToColorMapper: DrawableToColorMapper + drawableToColorMapper: DrawableToColorMapper, + drawableCopier: DrawableCopier ) : this( viewIdentifierResolver, colorStringFormatter, viewBoundsResolver, drawableToColorMapper, - ImageViewUtils + ImageViewUtils, + drawableCopier ) internal constructor( @@ -45,7 +50,8 @@ open class ImageViewMapper : BaseAsyncBackgroundWireframeMapper<ImageView> { colorStringFormatter: ColorStringFormatter, viewBoundsResolver: ViewBoundsResolver, drawableToColorMapper: DrawableToColorMapper, - imageViewUtils: ImageViewUtils + imageViewUtils: ImageViewUtils, + drawableCopier: DrawableCopier ) : super( viewIdentifierResolver, colorStringFormatter, @@ -53,6 +59,7 @@ open class ImageViewMapper : BaseAsyncBackgroundWireframeMapper<ImageView> { drawableToColorMapper ) { this.imageViewUtils = imageViewUtils + this.drawableCopier = drawableCopier } @UiThread @@ -76,7 +83,7 @@ open class ImageViewMapper : BaseAsyncBackgroundWireframeMapper<ImageView> { val density = resources.displayMetrics.density val clipping = if (view.cropToPadding) { - imageViewUtils.calculateClipping(parentRect, contentRect, density) + imageViewUtils.calculateClipping(parentRect, contentRect, density).toWireframeClip() } else { null } @@ -97,6 +104,7 @@ open class ImageViewMapper : BaseAsyncBackgroundWireframeMapper<ImageView> { height = contentHeightPx, usePIIPlaceholder = true, drawable = drawable, + drawableCopier = drawableCopier, asyncJobStatusCallback = asyncJobStatusCallback, clipping = clipping, shapeStyle = null, diff --git a/features/dd-sdk-android-session-replay/src/main/kotlin/com/datadog/android/sessionreplay/recorder/mapper/TextViewMapper.kt b/features/dd-sdk-android-session-replay/src/main/kotlin/com/datadog/android/sessionreplay/recorder/mapper/TextViewMapper.kt index 85ba1b627b..289e66e44d 100644 --- a/features/dd-sdk-android-session-replay/src/main/kotlin/com/datadog/android/sessionreplay/recorder/mapper/TextViewMapper.kt +++ b/features/dd-sdk-android-session-replay/src/main/kotlin/com/datadog/android/sessionreplay/recorder/mapper/TextViewMapper.kt @@ -11,8 +11,8 @@ import android.view.Gravity import android.widget.TextView import androidx.annotation.UiThread import com.datadog.android.api.InternalLogger +import com.datadog.android.internal.utils.densityNormalized import com.datadog.android.sessionreplay.TextAndInputPrivacy -import com.datadog.android.sessionreplay.internal.recorder.densityNormalized import com.datadog.android.sessionreplay.internal.recorder.obfuscator.StringObfuscator import com.datadog.android.sessionreplay.model.MobileSegment import com.datadog.android.sessionreplay.recorder.MappingContext diff --git a/features/dd-sdk-android-session-replay/src/main/kotlin/com/datadog/android/sessionreplay/internal/recorder/resources/DefaultDrawableCopier.kt b/features/dd-sdk-android-session-replay/src/main/kotlin/com/datadog/android/sessionreplay/recorder/resources/DefaultDrawableCopier.kt similarity index 83% rename from features/dd-sdk-android-session-replay/src/main/kotlin/com/datadog/android/sessionreplay/internal/recorder/resources/DefaultDrawableCopier.kt rename to features/dd-sdk-android-session-replay/src/main/kotlin/com/datadog/android/sessionreplay/recorder/resources/DefaultDrawableCopier.kt index 8bd17fdba1..92f527d404 100644 --- a/features/dd-sdk-android-session-replay/src/main/kotlin/com/datadog/android/sessionreplay/internal/recorder/resources/DefaultDrawableCopier.kt +++ b/features/dd-sdk-android-session-replay/src/main/kotlin/com/datadog/android/sessionreplay/recorder/resources/DefaultDrawableCopier.kt @@ -4,16 +4,14 @@ * Copyright 2016-Present Datadog, Inc. */ -package com.datadog.android.sessionreplay.internal.recorder.resources +package com.datadog.android.sessionreplay.recorder.resources import android.content.res.Resources import android.graphics.drawable.Drawable -import com.datadog.android.lint.InternalApi /** * Default implementation of [DrawableCopier] interface, it copies the drawable from constant state. */ -@InternalApi class DefaultDrawableCopier : DrawableCopier { override fun copy(originalDrawable: Drawable, resources: Resources): Drawable? { return originalDrawable.constantState?.newDrawable(resources) diff --git a/features/dd-sdk-android-session-replay/src/main/kotlin/com/datadog/android/sessionreplay/internal/recorder/resources/DrawableCopier.kt b/features/dd-sdk-android-session-replay/src/main/kotlin/com/datadog/android/sessionreplay/recorder/resources/DrawableCopier.kt similarity index 84% rename from features/dd-sdk-android-session-replay/src/main/kotlin/com/datadog/android/sessionreplay/internal/recorder/resources/DrawableCopier.kt rename to features/dd-sdk-android-session-replay/src/main/kotlin/com/datadog/android/sessionreplay/recorder/resources/DrawableCopier.kt index f732b1b5a4..a01e0bc09f 100644 --- a/features/dd-sdk-android-session-replay/src/main/kotlin/com/datadog/android/sessionreplay/internal/recorder/resources/DrawableCopier.kt +++ b/features/dd-sdk-android-session-replay/src/main/kotlin/com/datadog/android/sessionreplay/recorder/resources/DrawableCopier.kt @@ -4,16 +4,14 @@ * Copyright 2016-Present Datadog, Inc. */ -package com.datadog.android.sessionreplay.internal.recorder.resources +package com.datadog.android.sessionreplay.recorder.resources import android.content.res.Resources import android.graphics.drawable.Drawable -import com.datadog.android.lint.InternalApi /** * Interface of copying drawable to a new one. */ -@InternalApi fun interface DrawableCopier { /** diff --git a/features/dd-sdk-android-session-replay/src/main/kotlin/com/datadog/android/sessionreplay/utils/ImageWireframeHelper.kt b/features/dd-sdk-android-session-replay/src/main/kotlin/com/datadog/android/sessionreplay/utils/ImageWireframeHelper.kt index b147caf4ce..d627d49fe0 100644 --- a/features/dd-sdk-android-session-replay/src/main/kotlin/com/datadog/android/sessionreplay/utils/ImageWireframeHelper.kt +++ b/features/dd-sdk-android-session-replay/src/main/kotlin/com/datadog/android/sessionreplay/utils/ImageWireframeHelper.kt @@ -12,10 +12,10 @@ import android.view.View import android.widget.TextView import androidx.annotation.UiThread import com.datadog.android.sessionreplay.ImagePrivacy -import com.datadog.android.sessionreplay.internal.recorder.resources.DefaultDrawableCopier -import com.datadog.android.sessionreplay.internal.recorder.resources.DrawableCopier import com.datadog.android.sessionreplay.model.MobileSegment import com.datadog.android.sessionreplay.recorder.MappingContext +import com.datadog.android.sessionreplay.recorder.resources.DefaultDrawableCopier +import com.datadog.android.sessionreplay.recorder.resources.DrawableCopier /** * A Helper to handle capturing images in Session replay wireframes. diff --git a/features/dd-sdk-android-session-replay/src/test/kotlin/com/datadog/android/sessionreplay/internal/recorder/IntExtTest.kt b/features/dd-sdk-android-session-replay/src/test/kotlin/com/datadog/android/sessionreplay/internal/recorder/IntExtTest.kt index 68a9b90fc4..cc4da5de0e 100644 --- a/features/dd-sdk-android-session-replay/src/test/kotlin/com/datadog/android/sessionreplay/internal/recorder/IntExtTest.kt +++ b/features/dd-sdk-android-session-replay/src/test/kotlin/com/datadog/android/sessionreplay/internal/recorder/IntExtTest.kt @@ -6,6 +6,7 @@ package com.datadog.android.sessionreplay.internal.recorder +import com.datadog.android.internal.utils.densityNormalized import com.datadog.android.sessionreplay.forge.ForgeConfigurator import fr.xgouchet.elmyr.annotation.FloatForgery import fr.xgouchet.elmyr.annotation.IntForgery diff --git a/features/dd-sdk-android-session-replay/src/test/kotlin/com/datadog/android/sessionreplay/internal/recorder/LongExtTest.kt b/features/dd-sdk-android-session-replay/src/test/kotlin/com/datadog/android/sessionreplay/internal/recorder/LongExtTest.kt index 0715d2f8b1..be1842864d 100644 --- a/features/dd-sdk-android-session-replay/src/test/kotlin/com/datadog/android/sessionreplay/internal/recorder/LongExtTest.kt +++ b/features/dd-sdk-android-session-replay/src/test/kotlin/com/datadog/android/sessionreplay/internal/recorder/LongExtTest.kt @@ -6,6 +6,7 @@ package com.datadog.android.sessionreplay.internal.recorder +import com.datadog.android.internal.utils.densityNormalized import com.datadog.android.sessionreplay.forge.ForgeConfigurator import fr.xgouchet.elmyr.annotation.FloatForgery import fr.xgouchet.elmyr.annotation.LongForgery diff --git a/features/dd-sdk-android-session-replay/src/test/kotlin/com/datadog/android/sessionreplay/internal/recorder/mapper/BaseCheckableTextViewMapperTest.kt b/features/dd-sdk-android-session-replay/src/test/kotlin/com/datadog/android/sessionreplay/internal/recorder/mapper/BaseCheckableTextViewMapperTest.kt index 930c1a030f..15558911ff 100644 --- a/features/dd-sdk-android-session-replay/src/test/kotlin/com/datadog/android/sessionreplay/internal/recorder/mapper/BaseCheckableTextViewMapperTest.kt +++ b/features/dd-sdk-android-session-replay/src/test/kotlin/com/datadog/android/sessionreplay/internal/recorder/mapper/BaseCheckableTextViewMapperTest.kt @@ -17,9 +17,9 @@ import com.datadog.android.sessionreplay.TextAndInputPrivacy import com.datadog.android.sessionreplay.forge.ForgeConfigurator import com.datadog.android.sessionreplay.internal.recorder.mapper.CheckableTextViewMapper.Companion.CHECK_BOX_CHECKED_DRAWABLE_INDEX import com.datadog.android.sessionreplay.internal.recorder.mapper.CheckableTextViewMapper.Companion.CHECK_BOX_NOT_CHECKED_DRAWABLE_INDEX -import com.datadog.android.sessionreplay.internal.recorder.resources.DrawableCopier import com.datadog.android.sessionreplay.model.MobileSegment import com.datadog.android.sessionreplay.recorder.mapper.TextViewMapper +import com.datadog.android.sessionreplay.recorder.resources.DrawableCopier import com.datadog.android.sessionreplay.utils.GlobalBounds import com.datadog.android.sessionreplay.utils.OPAQUE_ALPHA_VALUE import com.datadog.tools.unit.annotations.TestTargetApi diff --git a/features/dd-sdk-android-session-replay/src/test/kotlin/com/datadog/android/sessionreplay/internal/recorder/mapper/BaseNumberPickerMapperTest.kt b/features/dd-sdk-android-session-replay/src/test/kotlin/com/datadog/android/sessionreplay/internal/recorder/mapper/BaseNumberPickerMapperTest.kt index 67b0596bb0..e74dcfbd27 100644 --- a/features/dd-sdk-android-session-replay/src/test/kotlin/com/datadog/android/sessionreplay/internal/recorder/mapper/BaseNumberPickerMapperTest.kt +++ b/features/dd-sdk-android-session-replay/src/test/kotlin/com/datadog/android/sessionreplay/internal/recorder/mapper/BaseNumberPickerMapperTest.kt @@ -7,7 +7,7 @@ package com.datadog.android.sessionreplay.internal.recorder.mapper import android.widget.NumberPicker -import com.datadog.android.sessionreplay.internal.recorder.densityNormalized +import com.datadog.android.internal.utils.densityNormalized import com.datadog.android.sessionreplay.model.MobileSegment import com.datadog.android.sessionreplay.utils.GlobalBounds import com.datadog.android.sessionreplay.utils.OPAQUE_ALPHA_VALUE diff --git a/features/dd-sdk-android-session-replay/src/test/kotlin/com/datadog/android/sessionreplay/internal/recorder/mapper/BaseSwitchCompatMapperTest.kt b/features/dd-sdk-android-session-replay/src/test/kotlin/com/datadog/android/sessionreplay/internal/recorder/mapper/BaseSwitchCompatMapperTest.kt index c48948df15..e3a7e09327 100644 --- a/features/dd-sdk-android-session-replay/src/test/kotlin/com/datadog/android/sessionreplay/internal/recorder/mapper/BaseSwitchCompatMapperTest.kt +++ b/features/dd-sdk-android-session-replay/src/test/kotlin/com/datadog/android/sessionreplay/internal/recorder/mapper/BaseSwitchCompatMapperTest.kt @@ -11,9 +11,9 @@ import android.graphics.Rect import android.graphics.drawable.Drawable import android.graphics.drawable.Drawable.ConstantState import androidx.appcompat.widget.SwitchCompat +import com.datadog.android.internal.utils.densityNormalized import com.datadog.android.sessionreplay.TextAndInputPrivacy import com.datadog.android.sessionreplay.forge.ForgeConfigurator -import com.datadog.android.sessionreplay.internal.recorder.densityNormalized import com.datadog.android.sessionreplay.model.MobileSegment import com.datadog.android.sessionreplay.recorder.mapper.TextViewMapper import com.datadog.android.sessionreplay.utils.GlobalBounds diff --git a/features/dd-sdk-android-session-replay/src/test/kotlin/com/datadog/android/sessionreplay/internal/recorder/mapper/ProgressBarWireframeMapperTest.kt b/features/dd-sdk-android-session-replay/src/test/kotlin/com/datadog/android/sessionreplay/internal/recorder/mapper/ProgressBarWireframeMapperTest.kt index ed4e4dfcb4..31da2a5dad 100644 --- a/features/dd-sdk-android-session-replay/src/test/kotlin/com/datadog/android/sessionreplay/internal/recorder/mapper/ProgressBarWireframeMapperTest.kt +++ b/features/dd-sdk-android-session-replay/src/test/kotlin/com/datadog/android/sessionreplay/internal/recorder/mapper/ProgressBarWireframeMapperTest.kt @@ -4,9 +4,9 @@ import android.content.res.ColorStateList import android.graphics.Rect import android.os.Build import android.widget.ProgressBar +import com.datadog.android.internal.utils.densityNormalized import com.datadog.android.sessionreplay.TextAndInputPrivacy import com.datadog.android.sessionreplay.forge.ForgeConfigurator -import com.datadog.android.sessionreplay.internal.recorder.densityNormalized import com.datadog.android.sessionreplay.internal.recorder.mapper.SeekBarWireframeMapper.Companion.TRACK_HEIGHT_IN_PX import com.datadog.android.sessionreplay.model.MobileSegment import com.datadog.android.sessionreplay.recorder.mapper.AbstractWireframeMapperTest diff --git a/features/dd-sdk-android-session-replay/src/test/kotlin/com/datadog/android/sessionreplay/internal/recorder/mapper/SeekBarWireframeMapperTest.kt b/features/dd-sdk-android-session-replay/src/test/kotlin/com/datadog/android/sessionreplay/internal/recorder/mapper/SeekBarWireframeMapperTest.kt index a282d78e9f..638ba063a8 100644 --- a/features/dd-sdk-android-session-replay/src/test/kotlin/com/datadog/android/sessionreplay/internal/recorder/mapper/SeekBarWireframeMapperTest.kt +++ b/features/dd-sdk-android-session-replay/src/test/kotlin/com/datadog/android/sessionreplay/internal/recorder/mapper/SeekBarWireframeMapperTest.kt @@ -5,9 +5,9 @@ import android.graphics.Rect import android.graphics.drawable.Drawable import android.os.Build import android.widget.SeekBar +import com.datadog.android.internal.utils.densityNormalized import com.datadog.android.sessionreplay.TextAndInputPrivacy import com.datadog.android.sessionreplay.forge.ForgeConfigurator -import com.datadog.android.sessionreplay.internal.recorder.densityNormalized import com.datadog.android.sessionreplay.internal.recorder.mapper.SeekBarWireframeMapper.Companion.TRACK_HEIGHT_IN_PX import com.datadog.android.sessionreplay.model.MobileSegment import com.datadog.android.sessionreplay.recorder.mapper.AbstractWireframeMapperTest diff --git a/features/dd-sdk-android-session-replay/src/test/kotlin/com/datadog/android/sessionreplay/internal/recorder/mapper/SwitchCompatMapperTest.kt b/features/dd-sdk-android-session-replay/src/test/kotlin/com/datadog/android/sessionreplay/internal/recorder/mapper/SwitchCompatMapperTest.kt index ccb3181a0d..b93ef068a9 100644 --- a/features/dd-sdk-android-session-replay/src/test/kotlin/com/datadog/android/sessionreplay/internal/recorder/mapper/SwitchCompatMapperTest.kt +++ b/features/dd-sdk-android-session-replay/src/test/kotlin/com/datadog/android/sessionreplay/internal/recorder/mapper/SwitchCompatMapperTest.kt @@ -7,10 +7,10 @@ package com.datadog.android.sessionreplay.internal.recorder.mapper import android.graphics.drawable.Drawable +import com.datadog.android.internal.utils.densityNormalized import com.datadog.android.sessionreplay.ImagePrivacy import com.datadog.android.sessionreplay.TextAndInputPrivacy import com.datadog.android.sessionreplay.forge.ForgeConfigurator -import com.datadog.android.sessionreplay.internal.recorder.densityNormalized import com.datadog.android.sessionreplay.model.MobileSegment import fr.xgouchet.elmyr.Forge import fr.xgouchet.elmyr.junit5.ForgeConfiguration diff --git a/features/dd-sdk-android-session-replay/src/test/kotlin/com/datadog/android/sessionreplay/internal/recorder/resources/DefaultImageWireframeHelperTest.kt b/features/dd-sdk-android-session-replay/src/test/kotlin/com/datadog/android/sessionreplay/internal/recorder/resources/DefaultImageWireframeHelperTest.kt index 196ff22dc7..2b8416a3d5 100644 --- a/features/dd-sdk-android-session-replay/src/test/kotlin/com/datadog/android/sessionreplay/internal/recorder/resources/DefaultImageWireframeHelperTest.kt +++ b/features/dd-sdk-android-session-replay/src/test/kotlin/com/datadog/android/sessionreplay/internal/recorder/resources/DefaultImageWireframeHelperTest.kt @@ -173,15 +173,6 @@ internal class DefaultImageWireframeHelperTest { ) ).thenReturn(fakeGeneratedIdentifier) - whenever( - mockViewUtilsInternal.resolveCompoundDrawableBounds( - view = any(), - drawable = any(), - pixelsDensity = any(), - position = any() - ) - ).thenReturn(fakeBounds) - testedHelper = DefaultImageWireframeHelper( logger = mockLogger, resourceResolver = mockResourceResolver, @@ -503,7 +494,26 @@ internal class DefaultImageWireframeHelperTest { } @Test - fun `M not return image wireframe W createImageWireframeByDrawable { usePIIPlaceholder and MASK_NONE }`() { + fun `M return content placeholder W createImageWireframeByBitmap() { ImagePrivacy MASK_ALL }`() { + // When + val wireframe = testedHelper.createImageWireframeByBitmap( + id = fakeViewId, + bitmap = mockBitmap, + density = fakeDensity, + imagePrivacy = ImagePrivacy.MASK_ALL, + isContextualImage = false, + globalBounds = fakeBounds, + shapeStyle = null, + border = null, + asyncJobStatusCallback = mockAsyncJobStatusCallback + ) + + // Then + assertThat(wireframe).isInstanceOf(MobileSegment.Wireframe.PlaceholderWireframe::class.java) + } + + @Test + fun `M not return image wireframe W createImageWireframeByDrawable(usePIIPlaceholder = true) { MASK_NONE }`() { // When val wireframe = testedHelper.createImageWireframeByDrawable( view = mockView, @@ -526,7 +536,26 @@ internal class DefaultImageWireframeHelperTest { } @Test - fun `M return null W createImageWireframeByDrawable { application context is null }`() { + fun `M not return image wireframe W createImageWireframeByBitmap { MASK_LARGE_ONLY & isContextual image}`() { + // When + val wireframe = testedHelper.createImageWireframeByBitmap( + id = fakeViewId, + bitmap = mockBitmap, + density = fakeDensity, + imagePrivacy = ImagePrivacy.MASK_LARGE_ONLY, + isContextualImage = true, + globalBounds = fakeBounds, + shapeStyle = null, + border = null, + asyncJobStatusCallback = mockAsyncJobStatusCallback + ) + + // Then + assertThat(wireframe).isInstanceOf(MobileSegment.Wireframe.PlaceholderWireframe::class.java) + } + + @Test + fun `M return null W createImageWireframeByDrawable() { application context is null }`() { // Given whenever(mockView.context.applicationContext).thenReturn(null) @@ -552,7 +581,7 @@ internal class DefaultImageWireframeHelperTest { } @Test - fun `M send telemetry W createImageWireframeByDrawable { application context is null }`() { + fun `M send telemetry W createImageWireframeByDrawable() { application context is null }`() { // Given whenever(mockView.context.applicationContext).thenReturn(null) @@ -582,7 +611,7 @@ internal class DefaultImageWireframeHelperTest { } @Test - fun `M log error W createImageWireframeByDrawable { resources is null }`() { + fun `M log error W createImageWireframeByDrawable() { resources is null }`() { // Given whenever(mockView.resources).thenReturn(null) @@ -612,7 +641,7 @@ internal class DefaultImageWireframeHelperTest { } @Test - fun `M return null W createImageWireframeByDrawable { id is null }`() { + fun `M return null W createImageWireframeByDrawable() { id is null }`() { // Given whenever(mockViewIdentifierResolver.resolveChildUniqueIdentifier(any(), any())) .thenReturn(null) @@ -640,7 +669,7 @@ internal class DefaultImageWireframeHelperTest { } @Test - fun `M return null W createImageWireframeByDrawable { drawable has no width }`() { + fun `M return null W createImageWireframeByDrawable() { drawable has no width }`() { // When val wireframe = testedHelper.createImageWireframeByDrawable( view = mockView, @@ -663,7 +692,7 @@ internal class DefaultImageWireframeHelperTest { } @Test - fun `M return null W createImageWireframeByDrawable { drawable has no height }`() { + fun `M return null W createImageWireframeByDrawable() { drawable has no height }`() { // When val wireframe = testedHelper.createImageWireframeByDrawable( view = mockView, @@ -686,7 +715,7 @@ internal class DefaultImageWireframeHelperTest { } @Test - fun `M return wireframe W createImageWireframeByDrawable`( + fun `M return wireframe W createImageWireframeByDrawable()`( @Mock mockShapeStyle: MobileSegment.ShapeStyle, @Mock mockBorder: MobileSegment.ShapeBorder, @Mock stubWireframeClip: MobileSegment.WireframeClip @@ -761,7 +790,202 @@ internal class DefaultImageWireframeHelperTest { } @Test - fun `M resolve view width and height W createImageWireframeByDrawable { RippleDrawable }`( + fun `M return wireframe W createImageWireframeByBitmap()`( + @Mock mockShapeStyle: MobileSegment.ShapeStyle, + @Mock mockBorder: MobileSegment.ShapeBorder, + @Mock stubWireframeClip: MobileSegment.WireframeClip + ) { + // Given + whenever( + mockResourceResolver.resolveResourceId( + bitmap = any(), + resourceResolverCallback = any() + ) + ).thenAnswer { + val callback = it.arguments[1] as ResourceResolverCallback + callback.onSuccess(fakeResourceId) + } + + val expectedWireframe = MobileSegment.Wireframe.ImageWireframe( + id = fakeGeneratedIdentifier, + x = fakeBounds.x, + y = fakeBounds.y, + width = fakeBounds.width, + height = fakeBounds.height, + shapeStyle = mockShapeStyle, + border = mockBorder, + resourceId = fakeResourceId, + clip = stubWireframeClip, + isEmpty = false + ) + + // When + val wireframe = testedHelper.createImageWireframeByBitmap( + id = fakeGeneratedIdentifier, + imagePrivacy = ImagePrivacy.MASK_LARGE_ONLY, + density = fakeDensity, + globalBounds = fakeBounds, + bitmap = mockBitmap, + shapeStyle = mockShapeStyle, + border = mockBorder, + asyncJobStatusCallback = mockAsyncJobStatusCallback, + isContextualImage = false, + clipping = stubWireframeClip + ) + + // Then + verify(mockResourceResolver).resolveResourceId( + bitmap = any(), + resourceResolverCallback = any() + ) + verify(mockAsyncJobStatusCallback).jobStarted() + verify(mockAsyncJobStatusCallback).jobFinished() + verifyNoMoreInteractions(mockAsyncJobStatusCallback) + assertThat(wireframe).isEqualTo(expectedWireframe) + } + + // endregion + + // region createCompoundDrawableWireframes + + @Test + fun `M return empty list W createCompoundDrawableWireframes() { no compound drawables }`() { + // Given + whenever(mockTextView.compoundDrawables) + .thenReturn(arrayOf(null, null, null, null)) + + // When + val wireframes = testedHelper.createCompoundDrawableWireframes( + textView = mockTextView, + mappingContext = mockMappingContext, + prevWireframeIndex = 0, + customResourceIdCacheKey = null, + asyncJobStatusCallback = mockAsyncJobStatusCallback + ) + + // Then + verifyNoInteractions(mockAsyncJobStatusCallback) + assertThat(wireframes).isEmpty() + } + + @Test + fun `M return wireframe W createCompoundDrawableWireframes()`() { + // Given + whenever( + mockViewUtilsInternal.resolveCompoundDrawableBounds( + view = any(), + drawable = any(), + pixelsDensity = any(), + position = any() + ) + ).thenReturn(fakeBounds) + val fakeDrawables = arrayOf(null, mockDrawable, null, null) + whenever(mockTextView.compoundDrawables) + .thenReturn(fakeDrawables) + + // When + val wireframes = testedHelper.createCompoundDrawableWireframes( + textView = mockTextView, + mappingContext = mockMappingContext, + prevWireframeIndex = 0, + customResourceIdCacheKey = null, + asyncJobStatusCallback = mockAsyncJobStatusCallback + ) + + assertThat(wireframes[0]).isInstanceOf(MobileSegment.Wireframe.ImageWireframe::class.java) + + // Then + val argumentCaptor = argumentCaptor<ResourceResolverCallback>() + + verify(mockResourceResolver).resolveResourceId( + resources = any(), + applicationContext = any(), + displayMetrics = any(), + originalDrawable = any(), + drawableCopier = any(), + drawableWidth = any(), + drawableHeight = any(), + customResourceIdCacheKey = anyOrNull(), + resourceResolverCallback = argumentCaptor.capture() + ) + argumentCaptor.allValues.forEach { + it.onSuccess(fakeResourceId) + } + verify(mockAsyncJobStatusCallback).jobStarted() + verify(mockAsyncJobStatusCallback).jobFinished() + assertThat(wireframes.size).isEqualTo(1) + } + + @Test + fun `M return multiple wireframes W createCompoundDrawableWireframes() { multiple drawables }`() { + // Given + whenever( + mockViewUtilsInternal.resolveCompoundDrawableBounds( + view = any(), + drawable = any(), + pixelsDensity = any(), + position = any() + ) + ) + .thenReturn(fakeBounds) + val fakeDrawables = arrayOf(null, mockDrawable, null, mockDrawable) + whenever(mockTextView.compoundDrawables) + .thenReturn(fakeDrawables) + + // When + val wireframes = testedHelper.createCompoundDrawableWireframes( + textView = mockTextView, + mappingContext = mockMappingContext, + prevWireframeIndex = 0, + customResourceIdCacheKey = null, + asyncJobStatusCallback = mockAsyncJobStatusCallback + ) + + assertThat(wireframes[0]).isInstanceOf(MobileSegment.Wireframe.ImageWireframe::class.java) + + // Then + val argumentCaptor = argumentCaptor<ResourceResolverCallback>() + verify(mockResourceResolver, times(2)).resolveResourceId( + resources = any(), + applicationContext = any(), + displayMetrics = any(), + originalDrawable = any(), + drawableCopier = any(), + drawableWidth = any(), + drawableHeight = any(), + customResourceIdCacheKey = anyOrNull(), + resourceResolverCallback = argumentCaptor.capture() + ) + argumentCaptor.allValues.forEach { + it.onSuccess(fakeResourceId) + } + verify(mockAsyncJobStatusCallback, times(2)).jobStarted() + verify(mockAsyncJobStatusCallback, times(2)).jobFinished() + assertThat(wireframes).hasSize(2) + } + + @Test + fun `M skip invalid elements W createCompoundDrawableWireframes() { invalid indices }`() { + // Given + whenever(mockTextView.compoundDrawables) + .thenReturn(arrayOf(null, null, null, null, null, null)) + + // When + val wireframes = testedHelper.createCompoundDrawableWireframes( + textView = mockTextView, + mappingContext = mockMappingContext, + prevWireframeIndex = 0, + customResourceIdCacheKey = null, + asyncJobStatusCallback = mockAsyncJobStatusCallback + ) + + // Then + verifyNoInteractions(mockAsyncJobStatusCallback) + assertThat(wireframes).isEmpty() + } + + @Test + fun `M resolve view width and height W createImageWireframe() { RippleDrawable }`( @Mock mockDrawable: RippleDrawable, @Mock mockInsetDrawable: InsetDrawable, @Mock mockGradientDrawable: GradientDrawable, @@ -809,7 +1033,7 @@ internal class DefaultImageWireframeHelperTest { } @Test - fun `M resolve drawable width and height W createImageWireframeByDrawable { TextView }`() { + fun `M resolve drawable width and height W createImageWireframe() { TextView }`() { // When testedHelper.createImageWireframeByDrawable( view = mockView, @@ -845,7 +1069,7 @@ internal class DefaultImageWireframeHelperTest { } @Test - fun `M not try to resolve bitmap W createImageWireframeByDrawable { PII image }`( + fun `M not try to resolve bitmap W createImageWireframeByDrawable() { PII image }`( forge: Forge, @Mock mockResources: Resources, @Mock mockDisplayMetrics: DisplayMetrics, @@ -893,7 +1117,7 @@ internal class DefaultImageWireframeHelperTest { } @Test - fun `M try to resolve bitmap W createImageWireframeByDrawable { non-PII image }`() { + fun `M try to resolve bitmap W createImageWireframeByDrawable() { non-PII image }`() { // Given whenever(mockImageTypeResolver.isDrawablePII(any(), any())).thenReturn(false) @@ -929,7 +1153,7 @@ internal class DefaultImageWireframeHelperTest { } @Test - fun `M return content placeholder W createImageWireframeByDrawable { PII image }`() { + fun `M return content placeholder W createImageWireframeByDrawable() { PII image }`() { // Given whenever(mockImageTypeResolver.isDrawablePII(any(), any())).thenReturn(true) @@ -968,6 +1192,15 @@ internal class DefaultImageWireframeHelperTest { whenever(mockTextView.compoundDrawables) .thenReturn(arrayOf(mockDrawable, mockDrawable, mockDrawable, mockDrawable)) + whenever( + mockViewUtilsInternal.resolveCompoundDrawableBounds( + view = any(), + drawable = any(), + pixelsDensity = any(), + position = any() + ) + ).thenReturn(fakeBounds) + // When testedHelper.createCompoundDrawableWireframes( textView = mockTextView, @@ -1022,6 +1255,15 @@ internal class DefaultImageWireframeHelperTest { whenever(mockTextView.compoundDrawables) .thenReturn(fakeDrawables) + whenever( + mockViewUtilsInternal.resolveCompoundDrawableBounds( + view = any(), + drawable = any(), + pixelsDensity = any(), + position = any() + ) + ).thenReturn(fakeBounds) + // When val wireframes = testedHelper.createCompoundDrawableWireframes( textView = mockTextView, @@ -1030,7 +1272,8 @@ internal class DefaultImageWireframeHelperTest { customResourceIdCacheKey = null, asyncJobStatusCallback = mockAsyncJobStatusCallback ) - wireframes[0] as MobileSegment.Wireframe.ImageWireframe + + assertThat(wireframes[0]).isInstanceOf(MobileSegment.Wireframe.ImageWireframe::class.java) // Then val argumentCaptor = argumentCaptor<ResourceResolverCallback>() @@ -1078,7 +1321,8 @@ internal class DefaultImageWireframeHelperTest { customResourceIdCacheKey = null, asyncJobStatusCallback = mockAsyncJobStatusCallback ) - wireframes[0] as MobileSegment.Wireframe.ImageWireframe + + assertThat(wireframes[0]).isInstanceOf(MobileSegment.Wireframe.ImageWireframe::class.java) // Then val argumentCaptor = argumentCaptor<ResourceResolverCallback>() diff --git a/features/dd-sdk-android-session-replay/src/test/kotlin/com/datadog/android/sessionreplay/internal/recorder/resources/ResourceResolverTest.kt b/features/dd-sdk-android-session-replay/src/test/kotlin/com/datadog/android/sessionreplay/internal/recorder/resources/ResourceResolverTest.kt index 7f8b40bec7..8d640190d3 100644 --- a/features/dd-sdk-android-session-replay/src/test/kotlin/com/datadog/android/sessionreplay/internal/recorder/resources/ResourceResolverTest.kt +++ b/features/dd-sdk-android-session-replay/src/test/kotlin/com/datadog/android/sessionreplay/internal/recorder/resources/ResourceResolverTest.kt @@ -18,6 +18,7 @@ import com.datadog.android.api.InternalLogger import com.datadog.android.sessionreplay.forge.ForgeConfigurator import com.datadog.android.sessionreplay.internal.async.RecordedDataQueueHandler import com.datadog.android.sessionreplay.internal.utils.DrawableUtils +import com.datadog.android.sessionreplay.recorder.resources.DrawableCopier import fr.xgouchet.elmyr.Forge import fr.xgouchet.elmyr.annotation.Forgery import fr.xgouchet.elmyr.annotation.StringForgery @@ -141,7 +142,6 @@ internal class ResourceResolverTest { whenever( mockDrawableUtils.createBitmapOfApproxSizeFromDrawable( - resources = any(), drawable = any(), drawableWidth = any(), drawableHeight = any(), @@ -151,7 +151,7 @@ internal class ResourceResolverTest { bitmapCreationCallback = any() ) ).then { - (it.arguments[7] as ResourceResolver.BitmapCreationCallback).onReady(mockBitmap) + (it.arguments[6] as ResourceResolver.BitmapCreationCallback).onReady(mockBitmap) } // executeSafe is an extension so we have to mock the internal execute function @@ -233,7 +233,6 @@ internal class ResourceResolverTest { // Then verify(mockDrawableUtils).createBitmapOfApproxSizeFromDrawable( - resources = any(), drawable = any(), drawableWidth = any(), drawableHeight = any(), @@ -342,7 +341,6 @@ internal class ResourceResolverTest { // Then verify(mockDrawableUtils).createBitmapOfApproxSizeFromDrawable( - resources = any(), drawable = any(), drawableWidth = any(), drawableHeight = any(), @@ -359,7 +357,6 @@ internal class ResourceResolverTest { whenever(mockResourcesLRUCache.get(fakeResourceKey)).thenReturn(null) whenever( mockDrawableUtils.createBitmapOfApproxSizeFromDrawable( - resources = any(), drawable = any(), drawableWidth = any(), drawableHeight = any(), @@ -369,7 +366,7 @@ internal class ResourceResolverTest { bitmapCreationCallback = any() ) ).then { - (it.arguments[7] as ResourceResolver.BitmapCreationCallback).onFailure() + (it.arguments[6] as ResourceResolver.BitmapCreationCallback).onFailure() } // When @@ -459,7 +456,6 @@ internal class ResourceResolverTest { // Then verify(mockDrawableUtils, times(1)).createBitmapOfApproxSizeFromDrawable( - resources = any(), drawable = any(), drawableWidth = any(), drawableHeight = any(), @@ -490,7 +486,6 @@ internal class ResourceResolverTest { // Then verify(mockDrawableUtils, times(1)).createBitmapOfApproxSizeFromDrawable( - resources = any(), drawable = any(), drawableWidth = any(), drawableHeight = any(), @@ -547,7 +542,6 @@ internal class ResourceResolverTest { anyOrNull() ) verify(mockDrawableUtils, times(1)).createBitmapOfApproxSizeFromDrawable( - resources = any(), drawable = any(), drawableWidth = any(), drawableHeight = any(), @@ -582,7 +576,6 @@ internal class ResourceResolverTest { anyOrNull() ) verify(mockDrawableUtils, times(1)).createBitmapOfApproxSizeFromDrawable( - resources = any(), drawable = any(), drawableWidth = any(), drawableHeight = any(), @@ -873,7 +866,6 @@ internal class ResourceResolverTest { // Then verify(mockDrawableUtils).createBitmapOfApproxSizeFromDrawable( - resources = any(), drawable = any(), drawableWidth = any(), drawableHeight = any(), diff --git a/features/dd-sdk-android-session-replay/src/test/kotlin/com/datadog/android/sessionreplay/internal/utils/DrawableUtilsTest.kt b/features/dd-sdk-android-session-replay/src/test/kotlin/com/datadog/android/sessionreplay/internal/utils/DrawableUtilsTest.kt index e46f22922d..60b419f7da 100644 --- a/features/dd-sdk-android-session-replay/src/test/kotlin/com/datadog/android/sessionreplay/internal/utils/DrawableUtilsTest.kt +++ b/features/dd-sdk-android-session-replay/src/test/kotlin/com/datadog/android/sessionreplay/internal/utils/DrawableUtilsTest.kt @@ -33,7 +33,6 @@ import org.mockito.kotlin.any import org.mockito.kotlin.argumentCaptor import org.mockito.kotlin.doAnswer import org.mockito.kotlin.mock -import org.mockito.kotlin.never import org.mockito.kotlin.verify import org.mockito.kotlin.whenever import org.mockito.quality.Strictness @@ -141,7 +140,6 @@ internal class DrawableUtilsTest { // When testedDrawableUtils.createBitmapOfApproxSizeFromDrawable( - resources = mockResources, drawable = mockDrawable, drawableWidth = mockDrawable.intrinsicWidth, drawableHeight = mockDrawable.intrinsicHeight, @@ -179,7 +177,6 @@ internal class DrawableUtilsTest { // When testedDrawableUtils.createBitmapOfApproxSizeFromDrawable( - resources = mockResources, drawable = mockDrawable, drawableWidth = mockDrawable.intrinsicWidth, drawableHeight = mockDrawable.intrinsicHeight, @@ -214,7 +211,6 @@ internal class DrawableUtilsTest { // When testedDrawableUtils.createBitmapOfApproxSizeFromDrawable( - resources = mockResources, drawable = mockDrawable, drawableWidth = mockDrawable.intrinsicWidth, drawableHeight = mockDrawable.intrinsicHeight, @@ -254,7 +250,6 @@ internal class DrawableUtilsTest { // When testedDrawableUtils.createBitmapOfApproxSizeFromDrawable( - resources = mockResources, drawable = mockDrawable, drawableWidth = mockDrawable.intrinsicWidth, drawableHeight = mockDrawable.intrinsicHeight, @@ -279,7 +274,6 @@ internal class DrawableUtilsTest { // When testedDrawableUtils.createBitmapOfApproxSizeFromDrawable( - resources = mockResources, drawable = mockDrawable, drawableWidth = mockDrawable.intrinsicWidth, drawableHeight = mockDrawable.intrinsicHeight, @@ -297,12 +291,13 @@ internal class DrawableUtilsTest { // Given whenever(mockDrawable.intrinsicWidth).thenReturn(1) whenever(mockDrawable.intrinsicHeight).thenReturn(1) - whenever(mockConstantState.newDrawable(mockResources)) - .thenReturn(null) + whenever(mockBitmap.isRecycled).thenReturn(true) + whenever(mockBitmapWrapper.createBitmap(any(), any(), any(), any())).thenReturn( + null + ) // When testedDrawableUtils.createBitmapOfApproxSizeFromDrawable( - resources = mockResources, drawable = mockDrawable, drawableWidth = mockDrawable.intrinsicWidth, drawableHeight = mockDrawable.intrinsicHeight, @@ -325,7 +320,6 @@ internal class DrawableUtilsTest { // When testedDrawableUtils.createBitmapOfApproxSizeFromDrawable( - resources = mockResources, drawable = mockDrawable, drawableWidth = mockDrawable.intrinsicWidth, drawableHeight = mockDrawable.intrinsicHeight, @@ -353,7 +347,6 @@ internal class DrawableUtilsTest { // When testedDrawableUtils.createBitmapOfApproxSizeFromDrawable( - resources = mockResources, drawable = mockDrawable, drawableWidth = mockDrawable.intrinsicWidth, drawableHeight = mockDrawable.intrinsicHeight, @@ -378,30 +371,6 @@ internal class DrawableUtilsTest { assertThat(displayMetricsCaptor.firstValue).isEqualTo(mockDisplayMetrics) } - @Test - fun `M not use original drawable W createBitmapOfApproxSizeFromDrawable`() { - // Given - whenever(mockDrawable.intrinsicWidth).thenReturn(1) - whenever(mockDrawable.intrinsicHeight).thenReturn(1) - - // When - testedDrawableUtils.createBitmapOfApproxSizeFromDrawable( - resources = mockResources, - drawable = mockDrawable, - drawableWidth = mockDrawable.intrinsicWidth, - drawableHeight = mockDrawable.intrinsicHeight, - displayMetrics = mockDisplayMetrics, - config = mockConfig, - bitmapCreationCallback = mockBitmapCreationCallback - ) - - // Then - verify(mockDrawable, never()).setBounds(any(), any(), any(), any()) - verify(mockDrawable, never()).draw(any()) - verify(mockSecondDrawable).setBounds(any(), any(), any(), any()) - verify(mockSecondDrawable).draw(any()) - } - @Test fun `M return scaled bitmap W createScaledBitmap()`( @Mock mockScaledBitmap: Bitmap diff --git a/features/dd-sdk-android-session-replay/src/test/kotlin/com/datadog/android/sessionreplay/internal/utils/ImageViewUtilsTest.kt b/features/dd-sdk-android-session-replay/src/test/kotlin/com/datadog/android/sessionreplay/internal/utils/ImageViewUtilsTest.kt index 45bf0adcdd..b3ad5c0df4 100644 --- a/features/dd-sdk-android-session-replay/src/test/kotlin/com/datadog/android/sessionreplay/internal/utils/ImageViewUtilsTest.kt +++ b/features/dd-sdk-android-session-replay/src/test/kotlin/com/datadog/android/sessionreplay/internal/utils/ImageViewUtilsTest.kt @@ -10,6 +10,7 @@ import android.graphics.Rect import android.graphics.drawable.Drawable import android.view.View import android.widget.ImageView +import com.datadog.android.internal.utils.ImageViewUtils import com.datadog.android.sessionreplay.forge.ForgeConfigurator import com.datadog.android.sessionreplay.model.MobileSegment import com.datadog.android.utils.isCloseToOrGreaterThan @@ -72,7 +73,7 @@ internal class ImageViewUtilsTest { ) // Then - assertThat(result).isEqualTo(expectedClipping) + assertThat(result.toWireframeClip()).isEqualTo(expectedClipping) } @Test @@ -104,7 +105,7 @@ internal class ImageViewUtilsTest { ) // Then - assertThat(result).isEqualTo(expectedClipping) + assertThat(result.toWireframeClip()).isEqualTo(expectedClipping) } @Test @@ -136,7 +137,7 @@ internal class ImageViewUtilsTest { ) // Then - assertThat(result).isEqualTo(expectedClipping) + assertThat(result.toWireframeClip()).isEqualTo(expectedClipping) } @Test @@ -168,7 +169,7 @@ internal class ImageViewUtilsTest { ) // Then - assertThat(result).isEqualTo(expectedClipping) + assertThat(result.toWireframeClip()).isEqualTo(expectedClipping) } @Test @@ -200,7 +201,7 @@ internal class ImageViewUtilsTest { ) // Then - assertThat(result).isEqualTo(expectedClipping) + assertThat(result.toWireframeClip()).isEqualTo(expectedClipping) } // endregion diff --git a/features/dd-sdk-android-session-replay/src/test/kotlin/com/datadog/android/sessionreplay/internal/utils/MiscUtilsTest.kt b/features/dd-sdk-android-session-replay/src/test/kotlin/com/datadog/android/sessionreplay/internal/utils/MiscUtilsTest.kt index 12187927b2..1d2c73c720 100644 --- a/features/dd-sdk-android-session-replay/src/test/kotlin/com/datadog/android/sessionreplay/internal/utils/MiscUtilsTest.kt +++ b/features/dd-sdk-android-session-replay/src/test/kotlin/com/datadog/android/sessionreplay/internal/utils/MiscUtilsTest.kt @@ -19,8 +19,8 @@ import android.view.Display import android.view.WindowManager import android.view.WindowMetrics import com.datadog.android.api.InternalLogger +import com.datadog.android.internal.utils.densityNormalized import com.datadog.android.sessionreplay.forge.ForgeConfigurator -import com.datadog.android.sessionreplay.internal.recorder.densityNormalized import com.datadog.android.sessionreplay.internal.utils.MiscUtils.DESERIALIZE_JSON_ERROR import com.datadog.android.sessionreplay.recorder.SystemInformation import com.datadog.android.sessionreplay.utils.DefaultColorStringFormatter diff --git a/features/dd-sdk-android-session-replay/src/test/kotlin/com/datadog/android/sessionreplay/recorder/mapper/ImageViewMapperTest.kt b/features/dd-sdk-android-session-replay/src/test/kotlin/com/datadog/android/sessionreplay/recorder/mapper/ImageViewMapperTest.kt index 9bf84246ba..ae4891ec68 100644 --- a/features/dd-sdk-android-session-replay/src/test/kotlin/com/datadog/android/sessionreplay/recorder/mapper/ImageViewMapperTest.kt +++ b/features/dd-sdk-android-session-replay/src/test/kotlin/com/datadog/android/sessionreplay/recorder/mapper/ImageViewMapperTest.kt @@ -16,12 +16,13 @@ import android.util.DisplayMetrics import android.view.View import android.widget.ImageView import com.datadog.android.api.InternalLogger +import com.datadog.android.internal.utils.ImageViewUtils import com.datadog.android.sessionreplay.ImagePrivacy import com.datadog.android.sessionreplay.forge.ForgeConfigurator -import com.datadog.android.sessionreplay.internal.utils.ImageViewUtils import com.datadog.android.sessionreplay.model.MobileSegment import com.datadog.android.sessionreplay.recorder.MappingContext import com.datadog.android.sessionreplay.recorder.SystemInformation +import com.datadog.android.sessionreplay.recorder.resources.DrawableCopier import com.datadog.android.sessionreplay.utils.AsyncJobStatusCallback import com.datadog.android.sessionreplay.utils.ColorStringFormatter import com.datadog.android.sessionreplay.utils.DrawableToColorMapper @@ -100,6 +101,9 @@ internal class ImageViewMapperTest { @Mock lateinit var mockDrawableToColorMapper: DrawableToColorMapper + @Mock + lateinit var mockDrawableCopier: DrawableCopier + @Mock lateinit var mockGlobalBounds: GlobalBounds @@ -113,7 +117,7 @@ internal class ImageViewMapperTest { lateinit var mockBackgroundConstantState: ConstantState @Mock - lateinit var stubClipping: MobileSegment.WireframeClip + lateinit var stubClipping: Rect @Mock lateinit var stubParentRect: Rect @@ -197,7 +201,8 @@ internal class ImageViewMapperTest { colorStringFormatter = mockColorStringFormatter, viewBoundsResolver = mockViewBoundsResolver, drawableToColorMapper = mockDrawableToColorMapper, - imageViewUtils = stubImageViewUtils + imageViewUtils = stubImageViewUtils, + drawableCopier = mockDrawableCopier ) } diff --git a/features/dd-sdk-android-session-replay/src/test/kotlin/com/datadog/android/sessionreplay/utils/DefaultViewBoundsResolverTest.kt b/features/dd-sdk-android-session-replay/src/test/kotlin/com/datadog/android/sessionreplay/utils/DefaultViewBoundsResolverTest.kt index 4242325e1b..69eab2fcaf 100644 --- a/features/dd-sdk-android-session-replay/src/test/kotlin/com/datadog/android/sessionreplay/utils/DefaultViewBoundsResolverTest.kt +++ b/features/dd-sdk-android-session-replay/src/test/kotlin/com/datadog/android/sessionreplay/utils/DefaultViewBoundsResolverTest.kt @@ -7,8 +7,8 @@ package com.datadog.android.sessionreplay.utils import android.view.View +import com.datadog.android.internal.utils.densityNormalized import com.datadog.android.sessionreplay.forge.ForgeConfigurator -import com.datadog.android.sessionreplay.internal.recorder.densityNormalized import fr.xgouchet.elmyr.Forge import fr.xgouchet.elmyr.junit5.ForgeConfiguration import fr.xgouchet.elmyr.junit5.ForgeExtension