Skip to content

Commit

Permalink
Introduce InteractionTrigger subtypes to make filtering easier
Browse files Browse the repository at this point in the history
  • Loading branch information
pyricau committed Aug 25, 2024
1 parent 0831025 commit 1339663
Show file tree
Hide file tree
Showing 6 changed files with 109 additions and 63 deletions.
5 changes: 2 additions & 3 deletions papa-dev/src/main/java/papa/InteractionOverlayView.kt
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import android.util.TypedValue.COMPLEX_UNIT_SP
import android.view.KeyEvent
import android.view.MotionEvent
import android.view.View
import papa.internal.InputEventTrigger

/**
* Overlay view that displays the interactions in flight.
Expand Down Expand Up @@ -69,8 +68,8 @@ class InteractionOverlayView<EventType : Any>(

val interactionLines =
trackedInteractionsWithFrameCount.map { (trackedInteraction, frameCount) ->
val input = trackedInteraction.interactionTrigger?.payload?.let { deliveredInput ->
when (val inputEvent = (deliveredInput as InputEventTrigger).inputEvent) {
val input = trackedInteraction.interactionTrigger?.toInputEventTriggerOrNull()?.payload?.let { deliveredInput ->
when (val inputEvent = deliveredInput.inputEvent) {
is MotionEvent -> MotionEvent.actionToString(inputEvent.action)
is KeyEvent -> KeyEvent.keyCodeToString(inputEvent.keyCode)
else -> error("Unknown input event class ${inputEvent::class.java.name}")
Expand Down
71 changes: 41 additions & 30 deletions papa/api/papa.api
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,23 @@ public final class papa/AppVisibilityState : java/lang/Enum {
public abstract interface class papa/FinishingInteraction : papa/TrackedInteraction {
}

public final class papa/InputEventTrigger {
public synthetic fun <init> (Landroid/view/InputEvent;JLkotlin/jvm/internal/DefaultConstructorMarker;)V
public final fun component1 ()Landroid/view/InputEvent;
public final fun component2-UwyO8pc ()J
public final fun copy-HG0u8IE (Landroid/view/InputEvent;J)Lpapa/InputEventTrigger;
public static synthetic fun copy-HG0u8IE$default (Lpapa/InputEventTrigger;Landroid/view/InputEvent;JILjava/lang/Object;)Lpapa/InputEventTrigger;
public fun equals (Ljava/lang/Object;)Z
public final fun getDeliveryUptime-UwyO8pc ()J
public final fun getInputEvent ()Landroid/view/InputEvent;
public fun hashCode ()I
public fun toString ()Ljava/lang/String;
}

public final class papa/InputEventTriggerKt {
public static final fun toInputEventTriggerOrNull (Lpapa/InteractionTrigger;)Lpapa/InteractionTriggerWithPayload;
}

public abstract interface class papa/InteractionEventSink {
public abstract fun sendEvent (Ljava/lang/Object;)V
}
Expand Down Expand Up @@ -271,33 +288,31 @@ public final class papa/InteractionTrace$Companion {
public final fun startNow (Ljava/lang/String;)Lpapa/InteractionTrace;
}

public final class papa/InteractionTrigger {
public abstract interface class papa/InteractionTrigger {
public static final field Companion Lpapa/InteractionTrigger$Companion;
public synthetic fun <init> (JLjava/lang/String;Lpapa/InteractionTrace;Ljava/lang/Object;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
public synthetic fun <init> (JLjava/lang/String;Lpapa/InteractionTrace;Ljava/lang/Object;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
public final fun component1-UwyO8pc ()J
public final fun component2 ()Ljava/lang/String;
public final fun component4 ()Ljava/lang/Object;
public final fun copy-rnQQ1Ag (JLjava/lang/String;Lpapa/InteractionTrace;Ljava/lang/Object;)Lpapa/InteractionTrigger;
public static synthetic fun copy-rnQQ1Ag$default (Lpapa/InteractionTrigger;JLjava/lang/String;Lpapa/InteractionTrace;Ljava/lang/Object;ILjava/lang/Object;)Lpapa/InteractionTrigger;
public fun equals (Ljava/lang/Object;)Z
public final fun getName ()Ljava/lang/String;
public final fun getPayload ()Ljava/lang/Object;
public final fun getTriggerUptime-UwyO8pc ()J
public fun hashCode ()I
public final fun takeOverInteractionTrace ()Lpapa/InteractionTrace;
public fun toString ()Ljava/lang/String;
public abstract fun getName ()Ljava/lang/String;
public abstract fun getTriggerUptime-UwyO8pc ()J
public abstract fun takeOverInteractionTrace ()Lpapa/InteractionTrace;
}

public final class papa/InteractionTrigger$Companion {
public final fun triggerNow (Ljava/lang/String;Ljava/lang/Object;)Lpapa/InteractionTrigger;
public static synthetic fun triggerNow$default (Lpapa/InteractionTrigger$Companion;Ljava/lang/String;Ljava/lang/Object;ILjava/lang/Object;)Lpapa/InteractionTrigger;
public final fun triggerNow (Ljava/lang/String;)Lpapa/InteractionTrigger;
}

public final class papa/InteractionTriggerWithPayload : papa/InteractionTrigger {
public synthetic fun <init> (JLjava/lang/String;Lpapa/InteractionTrace;Ljava/lang/Object;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
public fun getName ()Ljava/lang/String;
public final fun getPayload ()Ljava/lang/Object;
public fun getTriggerUptime-UwyO8pc ()J
public fun takeOverInteractionTrace ()Lpapa/InteractionTrace;
public fun toString ()Ljava/lang/String;
}

public final class papa/MainThreadTriggerStack {
public static final field INSTANCE Lpapa/MainThreadTriggerStack;
public final fun getCurrentTriggers ()Ljava/util/List;
public final fun getEarliestInteractionTrigger ()Lpapa/InteractionTrigger;
public final fun getInputEventInteractionTriggers ()Ljava/util/List;
public final fun triggeredBy (Lpapa/InteractionTrigger;ZLkotlin/jvm/functions/Function0;)Ljava/lang/Object;
}

Expand Down Expand Up @@ -432,6 +447,15 @@ public final class papa/SentEvent {
public final fun getUptime-UwyO8pc ()J
}

public final class papa/SimpleInteractionTrigger : papa/InteractionTrigger {
public synthetic fun <init> (JLjava/lang/String;Lpapa/InteractionTrace;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
public synthetic fun <init> (JLjava/lang/String;Lpapa/InteractionTrace;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
public fun getName ()Ljava/lang/String;
public fun getTriggerUptime-UwyO8pc ()J
public fun takeOverInteractionTrace ()Lpapa/InteractionTrace;
public fun toString ()Ljava/lang/String;
}

public abstract interface class papa/TrackedInteraction {
public abstract fun getInteractionTrigger ()Lpapa/InteractionTrigger;
public abstract fun getSentEvents ()Ljava/util/List;
Expand All @@ -457,16 +481,3 @@ public final class papa/TriggerData$Unknown : papa/TriggerData {
public fun toString ()Ljava/lang/String;
}

public final class papa/internal/InputEventTrigger {
public synthetic fun <init> (Landroid/view/InputEvent;JLkotlin/jvm/internal/DefaultConstructorMarker;)V
public final fun component1 ()Landroid/view/InputEvent;
public final fun component2-UwyO8pc ()J
public final fun copy-HG0u8IE (Landroid/view/InputEvent;J)Lpapa/internal/InputEventTrigger;
public static synthetic fun copy-HG0u8IE$default (Lpapa/internal/InputEventTrigger;Landroid/view/InputEvent;JILjava/lang/Object;)Lpapa/internal/InputEventTrigger;
public fun equals (Ljava/lang/Object;)Z
public final fun getDeliveryUptime-UwyO8pc ()J
public final fun getInputEvent ()Landroid/view/InputEvent;
public fun hashCode ()I
public fun toString ()Ljava/lang/String;
}

18 changes: 18 additions & 0 deletions papa/src/main/java/papa/InputEventTrigger.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package papa

import android.view.InputEvent
import kotlin.time.Duration

data class InputEventTrigger(
val inputEvent: InputEvent,
val deliveryUptime: Duration
)

fun InteractionTrigger.toInputEventTriggerOrNull(): InteractionTriggerWithPayload<InputEventTrigger>? {
@Suppress("UNCHECKED_CAST")
return if (this is InteractionTriggerWithPayload<*> && payload is InputEventTrigger) {
this as InteractionTriggerWithPayload<InputEventTrigger>
} else {
null
}
}
56 changes: 36 additions & 20 deletions papa/src/main/java/papa/InteractionTrigger.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,30 @@ import papa.internal.checkMainThread
import kotlin.time.Duration
import kotlin.time.Duration.Companion.nanoseconds

data class InteractionTrigger(
val triggerUptime: Duration,
val name: String,
sealed interface InteractionTrigger {
val triggerUptime: Duration
val name: String
fun takeOverInteractionTrace(): InteractionTrace?

companion object {
fun triggerNow(
name: String,
): InteractionTrigger {
val nowUptimeNanos = System.nanoTime()
val interactionTrace = InteractionTrace.startNow(name)
val triggerUptime = nowUptimeNanos.nanoseconds
return SimpleInteractionTrigger(triggerUptime, name, interactionTrace)
}
}
}

class SimpleInteractionTrigger(
override val triggerUptime: Duration,
override val name: String,
private var interactionTrace: InteractionTrace? = null,
/**
* Additional details that can be carried by [InteractionTrigger]
*/
val payload: Any? = null
) {
) : InteractionTrigger {

fun takeOverInteractionTrace(): InteractionTrace? {
override fun takeOverInteractionTrace(): InteractionTrace? {
checkMainThread()
try {
return interactionTrace
Expand All @@ -23,15 +36,18 @@ data class InteractionTrigger(
}
}

companion object {
fun triggerNow(
name: String,
payload: Any? = null
): InteractionTrigger {
val nowUptimeNanos = System.nanoTime()
val interactionTrace = InteractionTrace.startNow(name)
val triggerUptime = nowUptimeNanos.nanoseconds
return InteractionTrigger(triggerUptime, name, interactionTrace, payload)
}
override fun toString(): String {
return "InteractionTrigger(name='$name', triggerUptime=$triggerUptime)"
}
}

class InteractionTriggerWithPayload<T>(
triggerUptime: Duration,
name: String,
interactionTrace: InteractionTrace?,
val payload: T
) : InteractionTrigger by SimpleInteractionTrigger(triggerUptime, name, interactionTrace) {
override fun toString(): String {
return "InteractionTrigger(name='$name', triggerUptime=$triggerUptime, payload=$payload)"
}
}
}
8 changes: 8 additions & 0 deletions papa/src/main/java/papa/MainThreadTriggerStack.kt
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,14 @@ object MainThreadTriggerStack {
return interactionTriggerStack.minByOrNull { it.triggerUptime }
}

val inputEventInteractionTriggers: List<InteractionTriggerWithPayload<InputEventTrigger>>
get() {
checkMainThread()
return interactionTriggerStack.mapNotNull {
it.toInputEventTriggerOrNull()
}
}

private val interactionTriggerStack = mutableListOf<InteractionTrigger>()

/**
Expand Down
14 changes: 4 additions & 10 deletions papa/src/main/java/papa/internal/InputTracker.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import android.app.Application
import android.os.Handler
import android.os.Looper
import android.os.SystemClock
import android.view.InputEvent
import android.view.KeyEvent
import android.view.MotionEvent
import android.view.ViewConfiguration
Expand All @@ -19,12 +18,12 @@ import curtains.keyEventInterceptors
import curtains.phoneWindow
import curtains.touchEventInterceptors
import curtains.windowAttachCount
import papa.InteractionTrigger
import papa.InputEventTrigger
import papa.InteractionTriggerWithPayload
import papa.MainThreadTriggerStack
import papa.SafeTrace
import papa.internal.FrozenFrameOnTouchDetector.findPressedView
import papa.safeTrace
import kotlin.time.Duration
import kotlin.time.Duration.Companion.milliseconds
import kotlin.time.Duration.Companion.nanoseconds

Expand Down Expand Up @@ -54,7 +53,7 @@ internal object InputTracker {
// Event bugfix: if event time is after delivery time, use delivery time as trigger time.
val triggerUptime = if (eventUptime > deliveryUptime) deliveryUptime else eventUptime

InteractionTrigger(
InteractionTriggerWithPayload(
triggerUptime = triggerUptime,
name = "tap",
interactionTrace = {
Expand Down Expand Up @@ -132,7 +131,7 @@ internal object InputTracker {
// Event bugfix: if event time is after delivery time, use delivery time as trigger time.
val triggerUptime = if (eventUptime > deliveryUptime) deliveryUptime else eventUptime

val trigger = InteractionTrigger(
val trigger = InteractionTriggerWithPayload(
triggerUptime = triggerUptime,
name = "key ${keyEvent.name}",
interactionTrace = {
Expand Down Expand Up @@ -176,8 +175,3 @@ internal object InputTracker {
}
}
}

data class InputEventTrigger(
val inputEvent: InputEvent,
val deliveryUptime: Duration
)

0 comments on commit 1339663

Please sign in to comment.