Coordinate update event when litho scrolls or is shifted
Summary: See doc comment for explanation Reviewed By: lblasa Differential Revision: D40587610 fbshipit-source-id: f0909440c4e6e3cc9f5c7b557198a93ba8809bd9
This commit is contained in:
committed by
Facebook GitHub Bot
parent
a447712865
commit
b1bee28f08
@@ -29,6 +29,17 @@ data class SubtreeUpdateEvent(
|
||||
}
|
||||
}
|
||||
|
||||
@kotlinx.serialization.Serializable
|
||||
data class CoordinateUpdateEvent(
|
||||
val observerType: String,
|
||||
val nodeId: Id,
|
||||
val coordinate: Coordinate
|
||||
) {
|
||||
companion object {
|
||||
const val name = "coordinateUpdate"
|
||||
}
|
||||
}
|
||||
|
||||
/** Separate optional performance statistics event */
|
||||
@kotlinx.serialization.Serializable
|
||||
data class PerfStatsEvent(
|
||||
|
||||
@@ -16,6 +16,8 @@ import com.facebook.flipper.plugins.uidebugger.LogTag
|
||||
import com.facebook.flipper.plugins.uidebugger.common.BitmapPool
|
||||
import com.facebook.flipper.plugins.uidebugger.core.Context
|
||||
import com.facebook.flipper.plugins.uidebugger.descriptors.Id
|
||||
import com.facebook.flipper.plugins.uidebugger.model.Coordinate
|
||||
import com.facebook.flipper.plugins.uidebugger.model.CoordinateUpdateEvent
|
||||
import com.facebook.flipper.plugins.uidebugger.model.Node
|
||||
import com.facebook.flipper.plugins.uidebugger.model.PerfStatsEvent
|
||||
import com.facebook.flipper.plugins.uidebugger.model.SubtreeUpdateEvent
|
||||
@@ -25,6 +27,11 @@ import kotlinx.coroutines.*
|
||||
import kotlinx.coroutines.channels.Channel
|
||||
import kotlinx.serialization.json.Json
|
||||
|
||||
sealed interface Update
|
||||
|
||||
data class CoordinateUpdate(val observerType: String, val nodeId: Id, val coordinate: Coordinate) :
|
||||
Update
|
||||
|
||||
data class SubtreeUpdate(
|
||||
val observerType: String,
|
||||
val rootId: Id,
|
||||
@@ -33,19 +40,19 @@ data class SubtreeUpdate(
|
||||
val traversalCompleteTime: Long,
|
||||
val snapshotComplete: Long,
|
||||
val snapshot: BitmapPool.ReusableBitmap?
|
||||
)
|
||||
) : Update
|
||||
|
||||
/** Holds the root observer and manages sending updates to desktop */
|
||||
class TreeObserverManager(val context: Context) {
|
||||
|
||||
private val rootObserver = ApplicationTreeObserver(context)
|
||||
private lateinit var treeUpdates: Channel<SubtreeUpdate>
|
||||
private lateinit var updates: Channel<Update>
|
||||
private var job: Job? = null
|
||||
private val workerScope = CoroutineScope(Dispatchers.IO)
|
||||
private val txId = AtomicInteger()
|
||||
|
||||
fun enqueueUpdate(update: SubtreeUpdate) {
|
||||
treeUpdates.trySend(update)
|
||||
fun enqueueUpdate(update: Update) {
|
||||
updates.trySend(update)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -55,64 +62,24 @@ class TreeObserverManager(val context: Context) {
|
||||
@SuppressLint("NewApi")
|
||||
fun start() {
|
||||
|
||||
treeUpdates = Channel(Channel.UNLIMITED)
|
||||
updates = Channel(Channel.UNLIMITED)
|
||||
rootObserver.subscribe(context.applicationRef)
|
||||
|
||||
job =
|
||||
workerScope.launch {
|
||||
while (isActive) {
|
||||
try {
|
||||
val treeUpdate = treeUpdates.receive()
|
||||
val onWorkerThread = System.currentTimeMillis()
|
||||
val txId = txId.getAndIncrement().toLong()
|
||||
|
||||
var serialized: String?
|
||||
if (treeUpdate.snapshot == null) {
|
||||
serialized =
|
||||
Json.encodeToString(
|
||||
SubtreeUpdateEvent.serializer(),
|
||||
SubtreeUpdateEvent(
|
||||
txId, treeUpdate.observerType, treeUpdate.rootId, treeUpdate.nodes))
|
||||
} else {
|
||||
val stream = ByteArrayOutputStream()
|
||||
val base64Stream = Base64OutputStream(stream, Base64.DEFAULT)
|
||||
treeUpdate.snapshot.bitmap?.compress(Bitmap.CompressFormat.JPEG, 100, base64Stream)
|
||||
val snapshot = stream.toString()
|
||||
serialized =
|
||||
Json.encodeToString(
|
||||
SubtreeUpdateEvent.serializer(),
|
||||
SubtreeUpdateEvent(
|
||||
txId,
|
||||
treeUpdate.observerType,
|
||||
treeUpdate.rootId,
|
||||
treeUpdate.nodes,
|
||||
snapshot))
|
||||
|
||||
treeUpdate.snapshot.readyForReuse()
|
||||
val update = updates.receive()
|
||||
when (update) {
|
||||
is SubtreeUpdate -> sendSubtreeUpdate(update)
|
||||
is CoordinateUpdate -> {
|
||||
val event =
|
||||
CoordinateUpdateEvent(update.observerType, update.nodeId, update.coordinate)
|
||||
val serialized = Json.encodeToString(CoordinateUpdateEvent.serializer(), event)
|
||||
context.connectionRef.connection?.send(CoordinateUpdateEvent.name, serialized)
|
||||
}
|
||||
}
|
||||
|
||||
val serializationEnd = System.currentTimeMillis()
|
||||
|
||||
context.connectionRef.connection?.send(SubtreeUpdateEvent.name, serialized)
|
||||
val socketEnd = System.currentTimeMillis()
|
||||
Log.i(
|
||||
LogTag,
|
||||
"Sent event for ${treeUpdate.observerType} root ID ${treeUpdate.rootId} nodes ${treeUpdate.nodes.size}")
|
||||
|
||||
val perfStats =
|
||||
PerfStatsEvent(
|
||||
txId = txId,
|
||||
observerType = treeUpdate.observerType,
|
||||
start = treeUpdate.startTime,
|
||||
traversalComplete = treeUpdate.traversalCompleteTime,
|
||||
snapshotComplete = treeUpdate.snapshotComplete,
|
||||
queuingComplete = onWorkerThread,
|
||||
serializationComplete = serializationEnd,
|
||||
socketComplete = socketEnd,
|
||||
nodesCount = treeUpdate.nodes.size)
|
||||
|
||||
context.connectionRef.connection?.send(
|
||||
PerfStatsEvent.name, Json.encodeToString(PerfStatsEvent.serializer(), perfStats))
|
||||
} catch (e: CancellationException) {} catch (e: java.lang.Exception) {
|
||||
Log.e(LogTag, "Unexpected Error in channel ", e)
|
||||
}
|
||||
@@ -121,9 +88,58 @@ class TreeObserverManager(val context: Context) {
|
||||
}
|
||||
}
|
||||
|
||||
fun sendSubtreeUpdate(treeUpdate: SubtreeUpdate) {
|
||||
val onWorkerThread = System.currentTimeMillis()
|
||||
val txId = txId.getAndIncrement().toLong()
|
||||
|
||||
var serialized: String?
|
||||
if (treeUpdate.snapshot == null) {
|
||||
serialized =
|
||||
Json.encodeToString(
|
||||
SubtreeUpdateEvent.serializer(),
|
||||
SubtreeUpdateEvent(
|
||||
txId, treeUpdate.observerType, treeUpdate.rootId, treeUpdate.nodes))
|
||||
} else {
|
||||
val stream = ByteArrayOutputStream()
|
||||
val base64Stream = Base64OutputStream(stream, Base64.DEFAULT)
|
||||
treeUpdate.snapshot.bitmap?.compress(Bitmap.CompressFormat.JPEG, 100, base64Stream)
|
||||
val snapshot = stream.toString()
|
||||
serialized =
|
||||
Json.encodeToString(
|
||||
SubtreeUpdateEvent.serializer(),
|
||||
SubtreeUpdateEvent(
|
||||
txId, treeUpdate.observerType, treeUpdate.rootId, treeUpdate.nodes, snapshot))
|
||||
|
||||
treeUpdate.snapshot.readyForReuse()
|
||||
}
|
||||
|
||||
val serializationEnd = System.currentTimeMillis()
|
||||
|
||||
context.connectionRef.connection?.send(SubtreeUpdateEvent.name, serialized)
|
||||
val socketEnd = System.currentTimeMillis()
|
||||
Log.i(
|
||||
LogTag,
|
||||
"Sent event for ${treeUpdate.observerType} root ID ${treeUpdate.rootId} nodes ${treeUpdate.nodes.size}")
|
||||
|
||||
val perfStats =
|
||||
PerfStatsEvent(
|
||||
txId = txId,
|
||||
observerType = treeUpdate.observerType,
|
||||
start = treeUpdate.startTime,
|
||||
traversalComplete = treeUpdate.traversalCompleteTime,
|
||||
snapshotComplete = treeUpdate.snapshotComplete,
|
||||
queuingComplete = onWorkerThread,
|
||||
serializationComplete = serializationEnd,
|
||||
socketComplete = socketEnd,
|
||||
nodesCount = treeUpdate.nodes.size)
|
||||
|
||||
context.connectionRef.connection?.send(
|
||||
PerfStatsEvent.name, Json.encodeToString(PerfStatsEvent.serializer(), perfStats))
|
||||
}
|
||||
|
||||
fun stop() {
|
||||
rootObserver.cleanUpRecursive()
|
||||
job?.cancel()
|
||||
treeUpdates.cancel()
|
||||
updates.cancel()
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user