Remove warnings

Summary: ^

Reviewed By: LukeDefeo

Differential Revision: D39573417

fbshipit-source-id: 241ecdddaf43020923046b0b5c35656bc8ffad34
This commit is contained in:
Lorenzo Blasa
2022-09-20 05:15:50 -07:00
committed by Facebook GitHub Bot
parent 3a4286b2ba
commit d8e47efb81
9 changed files with 119 additions and 86 deletions

View File

@@ -9,10 +9,8 @@ package com.facebook.flipper.plugins.uidebugger.commands
import com.facebook.flipper.core.FlipperConnection import com.facebook.flipper.core.FlipperConnection
sealed class CommandRegister { object CommandRegister {
companion object {
fun <T> register(connection: FlipperConnection, cmd: T) where T : Command { fun <T> register(connection: FlipperConnection, cmd: T) where T : Command {
connection.receive(cmd.identifier(), cmd.receiver()) connection.receive(cmd.identifier(), cmd.receiver())
} }
}
} }

View File

@@ -11,32 +11,30 @@ import android.util.Log
import com.facebook.flipper.plugins.uidebugger.LogTag import com.facebook.flipper.plugins.uidebugger.LogTag
// Maintains 2 way mapping between some enum value and a readable string representation // Maintains 2 way mapping between some enum value and a readable string representation
open class EnumMapping<T>(val mapping: Map<String, T>) { open class EnumMapping<T>(private val mapping: Map<String, T>) {
fun getStringRepresentation(enumValue: T): String { fun getStringRepresentation(enumValue: T): String {
val entry = mapping.entries.find { (_, value) -> value == enumValue } val entry = mapping.entries.find { (_, value) -> value == enumValue }
if (entry != null) { return if (entry != null) {
return entry.key entry.key
} else { } else {
Log.v( Log.v(
LogTag, LogTag,
"Could not convert enum value ${enumValue.toString()} to string, known values ${mapping.entries}") "Could not convert enum value ${enumValue.toString()} to string, known values ${mapping.entries}")
return NoMapping NoMapping
} }
} }
fun getEnumValue(key: String): T { fun getEnumValue(key: String): T {
val value = return mapping[key]
mapping[key]
?: throw UIDebuggerException( ?: throw UIDebuggerException(
"Could not convert string ${key} to enum value, possible values ${mapping.entries} ") "Could not convert string $key to enum value, possible values ${mapping.entries} ")
return value
} }
fun toInspectable(value: T, mutable: Boolean): InspectableValue.Enum { fun toInspectable(value: T, mutable: Boolean): InspectableValue.Enum {
return InspectableValue.Enum(EnumData(mapping.keys, getStringRepresentation(value)), mutable) return InspectableValue.Enum(EnumData(mapping.keys, getStringRepresentation(value)), mutable)
} }
companion object { companion object {
val NoMapping = "__UNKNOWN_ENUM_VALUE__" const val NoMapping = "__UNKNOWN_ENUM_VALUE__"
} }
} }

View File

@@ -18,7 +18,8 @@ class LayoutTraversal(
val root: ApplicationRef val root: ApplicationRef
) { ) {
internal inline fun NodeDescriptor<*>.asAny(): NodeDescriptor<Any> = this as NodeDescriptor<Any> @Suppress("unchecked_cast")
internal fun NodeDescriptor<*>.asAny(): NodeDescriptor<Any> = this as NodeDescriptor<Any>
/** Traverses the native android hierarchy */ /** Traverses the native android hierarchy */
fun traverse(): List<Node> { fun traverse(): List<Node> {
@@ -69,7 +70,7 @@ class LayoutTraversal(
childrenIds, childrenIds,
activeChildId)) activeChildId))
} catch (exception: Exception) { } catch (exception: Exception) {
Log.e(LogTag, "Error while processing node ${node.javaClass.name} ${node} ", exception) Log.e(LogTag, "Error while processing node ${node.javaClass.name} $node", exception)
} }
} }

View File

@@ -9,6 +9,7 @@ package com.facebook.flipper.plugins.uidebugger.core
import android.os.Looper import android.os.Looper
import android.util.Log import android.util.Log
import com.facebook.flipper.plugins.uidebugger.LogTag
import com.facebook.flipper.plugins.uidebugger.model.NativeScanEvent import com.facebook.flipper.plugins.uidebugger.model.NativeScanEvent
import com.facebook.flipper.plugins.uidebugger.model.Node import com.facebook.flipper.plugins.uidebugger.model.Node
import com.facebook.flipper.plugins.uidebugger.model.PerfStatsEvent import com.facebook.flipper.plugins.uidebugger.model.PerfStatsEvent
@@ -23,26 +24,24 @@ data class ScanResult(
) )
class NativeScanScheduler(val context: Context) : Scheduler.Task<ScanResult> { class NativeScanScheduler(val context: Context) : Scheduler.Task<ScanResult> {
val traversal = LayoutTraversal(context.descriptorRegister, context.applicationRef) private val traversal = LayoutTraversal(context.descriptorRegister, context.applicationRef)
var txId = 0L private var txId = 0L
override fun execute(): ScanResult {
override fun execute(): ScanResult {
val start = System.currentTimeMillis() val start = System.currentTimeMillis()
val nodes = traversal.traverse() val nodes = traversal.traverse()
val scanEnd = System.currentTimeMillis() val scanEnd = System.currentTimeMillis()
Log.d( Log.d(
"LAYOUT_SCHEDULER", LogTag,
"${Thread.currentThread().name}${Looper.myLooper()} produced: ${nodes.count()} nodes") "${Thread.currentThread().name}${Looper.myLooper()} produced: ${nodes.count()} nodes")
return ScanResult(txId++, start, scanEnd, nodes) return ScanResult(txId++, start, scanEnd, nodes)
} }
override fun process(result: ScanResult) { override fun process(input: ScanResult) {
val serialized = val serialized =
Json.encodeToString( Json.encodeToString(NativeScanEvent.serializer(), NativeScanEvent(input.txId, input.nodes))
NativeScanEvent.serializer(), NativeScanEvent(result.txId, result.nodes))
val serializationEnd = System.currentTimeMillis() val serializationEnd = System.currentTimeMillis()
context.connectionRef.connection?.send( context.connectionRef.connection?.send(
NativeScanEvent.name, NativeScanEvent.name,
@@ -56,13 +55,13 @@ class NativeScanScheduler(val context: Context) : Scheduler.Task<ScanResult> {
Json.encodeToString( Json.encodeToString(
PerfStatsEvent.serializer(), PerfStatsEvent.serializer(),
PerfStatsEvent( PerfStatsEvent(
result.txId, input.txId,
"FullScan", "FullScan",
result.scanStart, input.scanStart,
result.scanEnd, input.scanEnd,
result.scanEnd, input.scanEnd,
serializationEnd, serializationEnd,
socketEnd, socketEnd,
result.nodes.size))) input.nodes.size)))
} }
} }

View File

@@ -120,25 +120,28 @@ class RootViewResolver {
if (null == paramsField) { if (null == paramsField) {
return null return null
} }
var views: List<View>? = null var maybeViews: List<View>? = null
var params: List<WindowManager.LayoutParams>? = null var maybeParams: List<WindowManager.LayoutParams>? = null
try { try {
viewsField?.let { field -> viewsField?.let { field ->
views = maybeViews =
if (Build.VERSION.SDK_INT < 19) { if (Build.VERSION.SDK_INT < 19) {
val arr = field[windowManagerObj] as Array<View> @Suppress("unchecked_cast") val arr = field[windowManagerObj] as Array<View>
arr.toList() arr.toList()
} else { } else {
@Suppress("unchecked_cast")
field[windowManagerObj] as List<View> field[windowManagerObj] as List<View>
} }
} }
paramsField?.let { field -> paramsField?.let { field ->
params = maybeParams =
if (Build.VERSION.SDK_INT < 19) { if (Build.VERSION.SDK_INT < 19) {
@Suppress("unchecked_cast")
val arr = field[windowManagerObj] as Array<WindowManager.LayoutParams> val arr = field[windowManagerObj] as Array<WindowManager.LayoutParams>
arr.toList() as List<WindowManager.LayoutParams> arr.toList()
} else { } else {
@Suppress("unchecked_cast")
field[windowManagerObj] as List<WindowManager.LayoutParams> field[windowManagerObj] as List<WindowManager.LayoutParams>
} }
} }
@@ -149,8 +152,8 @@ class RootViewResolver {
} }
val roots = mutableListOf<RootView>() val roots = mutableListOf<RootView>()
views?.let { views -> maybeViews?.let { views ->
params?.let { params -> maybeParams?.let { params ->
if (views.size == params.size) { if (views.size == params.size) {
for (i in views.indices) { for (i in views.indices) {
val view = views[i] val view = views[i]
@@ -174,16 +177,15 @@ class RootViewResolver {
val getMethod = clazz.getMethod(instanceMethod) val getMethod = clazz.getMethod(instanceMethod)
windowManagerObj = getMethod.invoke(null) windowManagerObj = getMethod.invoke(null)
viewsField = clazz.getDeclaredField(VIEWS_FIELD) viewsField = clazz.getDeclaredField(VIEWS_FIELD)
viewsField?.let { vf -> vf.setAccessible(true) } viewsField?.let { vf -> vf.isAccessible = true }
paramsField = clazz.getDeclaredField(WINDOW_PARAMS_FIELD) paramsField = clazz.getDeclaredField(WINDOW_PARAMS_FIELD)
paramsField?.let { pf -> pf.setAccessible(true) } paramsField?.let { pf -> pf.isAccessible = true }
} catch (ite: InvocationTargetException) {} catch (cnfe: ClassNotFoundException) {} catch ( } catch (ite: InvocationTargetException) {} catch (cnfe: ClassNotFoundException) {} catch (
nsfe: NoSuchFieldException) {} catch (nsme: NoSuchMethodException) {} catch ( nsfe: NoSuchFieldException) {} catch (nsme: NoSuchMethodException) {} catch (
re: RuntimeException) {} catch (iae: IllegalAccessException) {} re: RuntimeException) {} catch (iae: IllegalAccessException) {}
} }
companion object { companion object {
private val TAG = RootViewResolver::class.java.simpleName
private const val WINDOW_MANAGER_IMPL_CLAZZ = "android.view.WindowManagerImpl" private const val WINDOW_MANAGER_IMPL_CLAZZ = "android.view.WindowManagerImpl"
private const val WINDOW_MANAGER_GLOBAL_CLAZZ = "android.view.WindowManagerGlobal" private const val WINDOW_MANAGER_GLOBAL_CLAZZ = "android.view.WindowManagerGlobal"
private const val VIEWS_FIELD = "mViews" private const val VIEWS_FIELD = "mViews"

View File

@@ -36,7 +36,7 @@ class DescriptorRegister {
mapping.register(android.app.Fragment::class.java, FragmentFrameworkDescriptor) mapping.register(android.app.Fragment::class.java, FragmentFrameworkDescriptor)
mapping.register(androidx.fragment.app.Fragment::class.java, FragmentSupportDescriptor) mapping.register(androidx.fragment.app.Fragment::class.java, FragmentSupportDescriptor)
@Suppress("UNCHECKED_CAST") @Suppress("unchecked_cast")
for (clazz in mapping.register.keys) { for (clazz in mapping.register.keys) {
val maybeDescriptor: NodeDescriptor<*>? = mapping.register[clazz] val maybeDescriptor: NodeDescriptor<*>? = mapping.register[clazz]
maybeDescriptor?.let { descriptor -> maybeDescriptor?.let { descriptor ->
@@ -69,7 +69,7 @@ class DescriptorRegister {
} }
return if (register[clazz] != null) { return if (register[clazz] != null) {
@Suppress("UNCHECKED_CAST") @Suppress("unchecked_cast")
register[clazz] as NodeDescriptor<T> register[clazz] as NodeDescriptor<T>
} else { } else {
null null

View File

@@ -10,6 +10,7 @@ package com.facebook.flipper.plugins.uidebugger.descriptors
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.graphics.drawable.ColorDrawable import android.graphics.drawable.ColorDrawable
import android.graphics.drawable.Drawable import android.graphics.drawable.Drawable
import android.os.Build
import android.util.SparseArray import android.util.SparseArray
import android.view.Gravity import android.view.Gravity
import android.view.View import android.view.View
@@ -23,7 +24,6 @@ import com.facebook.flipper.plugins.uidebugger.common.InspectableValue
import com.facebook.flipper.plugins.uidebugger.stetho.ResourcesUtil import com.facebook.flipper.plugins.uidebugger.stetho.ResourcesUtil
import java.lang.reflect.Field import java.lang.reflect.Field
@SuppressLint("DiscouragedPrivateApi")
object ViewDescriptor : ChainedDescriptor<View>() { object ViewDescriptor : ChainedDescriptor<View>() {
override fun onGetId(node: View): String { override fun onGetId(node: View): String {
@@ -167,6 +167,7 @@ object ViewDescriptor : ChainedDescriptor<View>() {
"MATCH_PARENT" to ViewGroup.LayoutParams.MATCH_PARENT, "MATCH_PARENT" to ViewGroup.LayoutParams.MATCH_PARENT,
"FILL_PARENT" to ViewGroup.LayoutParams.FILL_PARENT, "FILL_PARENT" to ViewGroup.LayoutParams.FILL_PARENT,
)) {} )) {}
private val VisibilityMapping: EnumMapping<Int> = private val VisibilityMapping: EnumMapping<Int> =
object : object :
EnumMapping<Int>( EnumMapping<Int>(
@@ -177,6 +178,8 @@ object ViewDescriptor : ChainedDescriptor<View>() {
)) {} )) {}
private val LayoutDirectionMapping: EnumMapping<Int> = private val LayoutDirectionMapping: EnumMapping<Int> =
when {
Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1 -> {
object : object :
EnumMapping<Int>( EnumMapping<Int>(
mapOf( mapOf(
@@ -185,8 +188,27 @@ object ViewDescriptor : ChainedDescriptor<View>() {
"LAYOUT_DIRECTION_LTR" to View.LAYOUT_DIRECTION_LTR, "LAYOUT_DIRECTION_LTR" to View.LAYOUT_DIRECTION_LTR,
"LAYOUT_DIRECTION_RTL" to View.LAYOUT_DIRECTION_RTL, "LAYOUT_DIRECTION_RTL" to View.LAYOUT_DIRECTION_RTL,
)) {} )) {}
}
else -> {
object : EnumMapping<Int>(emptyMap()) {}
}
}
private val TextDirectionMapping: EnumMapping<Int> = private val TextDirectionMapping: EnumMapping<Int> =
when {
Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1 -> {
object :
EnumMapping<Int>(
mapOf(
"TEXT_DIRECTION_INHERIT" to View.TEXT_DIRECTION_INHERIT,
"TEXT_DIRECTION_FIRST_STRONG" to View.TEXT_DIRECTION_FIRST_STRONG,
"TEXT_DIRECTION_ANY_RTL" to View.TEXT_DIRECTION_ANY_RTL,
"TEXT_DIRECTION_LTR" to View.TEXT_DIRECTION_LTR,
"TEXT_DIRECTION_RTL" to View.TEXT_DIRECTION_RTL,
"TEXT_DIRECTION_LOCALE" to View.TEXT_DIRECTION_LOCALE,
)) {}
}
Build.VERSION.SDK_INT >= Build.VERSION_CODES.M -> {
object : object :
EnumMapping<Int>( EnumMapping<Int>(
mapOf( mapOf(
@@ -199,8 +221,15 @@ object ViewDescriptor : ChainedDescriptor<View>() {
"TEXT_DIRECTION_FIRST_STRONG_LTR" to View.TEXT_DIRECTION_FIRST_STRONG_LTR, "TEXT_DIRECTION_FIRST_STRONG_LTR" to View.TEXT_DIRECTION_FIRST_STRONG_LTR,
"TEXT_DIRECTION_FIRST_STRONG_RTL" to View.TEXT_DIRECTION_FIRST_STRONG_RTL, "TEXT_DIRECTION_FIRST_STRONG_RTL" to View.TEXT_DIRECTION_FIRST_STRONG_RTL,
)) {} )) {}
}
else -> {
object : EnumMapping<Int>(emptyMap()) {}
}
}
private val TextAlignmentMapping: EnumMapping<Int> = private val TextAlignmentMapping: EnumMapping<Int> =
when {
Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1 -> {
object : object :
EnumMapping<Int>( EnumMapping<Int>(
mapOf( mapOf(
@@ -212,6 +241,11 @@ object ViewDescriptor : ChainedDescriptor<View>() {
"TEXT_ALIGNMENT_VIEW_START" to View.TEXT_ALIGNMENT_VIEW_START, "TEXT_ALIGNMENT_VIEW_START" to View.TEXT_ALIGNMENT_VIEW_START,
"TEXT_ALIGNMENT_VIEW_END" to View.TEXT_ALIGNMENT_VIEW_END, "TEXT_ALIGNMENT_VIEW_END" to View.TEXT_ALIGNMENT_VIEW_END,
)) {} )) {}
}
else -> {
object : EnumMapping<Int>(emptyMap()) {}
}
}
private val GravityMapping = private val GravityMapping =
object : object :
@@ -235,8 +269,10 @@ object ViewDescriptor : ChainedDescriptor<View>() {
init { init {
try { try {
@SuppressLint("DiscouragedPrivateApi")
KeyedTagsField = View::class.java.getDeclaredField("mKeyedTags") KeyedTagsField = View::class.java.getDeclaredField("mKeyedTags")
KeyedTagsField?.let { field -> field.isAccessible = true } KeyedTagsField?.let { field -> field.isAccessible = true }
@SuppressLint("DiscouragedPrivateApi")
ListenerInfoField = View::class.java.getDeclaredField("mListenerInfo") ListenerInfoField = View::class.java.getDeclaredField("mListenerInfo")
ListenerInfoField?.let { field -> field.isAccessible = true } ListenerInfoField?.let { field -> field.isAccessible = true }
val viewInfoClassName = View::class.java.name + "\$ListenerInfo" val viewInfoClassName = View::class.java.name + "\$ListenerInfo"

View File

@@ -14,15 +14,16 @@ import com.facebook.flipper.plugins.uidebugger.descriptors.NodeDescriptor
import com.facebook.flipper.plugins.uidebugger.model.Node import com.facebook.flipper.plugins.uidebugger.model.Node
/** /**
* This will traverse the layout hierarchy untill it sees a node that has an observer registered for * This will traverse the layout hierarchy until it sees a node that has an observer registered for
* it. The first item in the pair is the visited nodes The second item are any observable roots * it. The first item in the pair is the visited nodes The second item are any observable roots
* discovered * discovered
*/ */
class PartialLayoutTraversal( class PartialLayoutTraversal(
private val descriptorRegister: DescriptorRegister, private val descriptorRegister: DescriptorRegister,
private val treeObserverfactory: TreeObserverFactory, private val treeObserverFactory: TreeObserverFactory,
) { ) {
@Suppress("unchecked_cast")
internal fun NodeDescriptor<*>.asAny(): NodeDescriptor<Any> = this as NodeDescriptor<Any> internal fun NodeDescriptor<*>.asAny(): NodeDescriptor<Any> = this as NodeDescriptor<Any>
fun traverse(root: Any): Pair<MutableList<Node>, List<Any>> { fun traverse(root: Any): Pair<MutableList<Node>, List<Any>> {
@@ -37,9 +38,8 @@ class PartialLayoutTraversal(
val node = stack.removeLast() val node = stack.removeLast()
try { try {
// If we encounter a node that has it own observer, don't traverse
// if we encounter a node that has it own observer, dont traverse if (node != root && treeObserverFactory.hasObserverFor(node)) {
if (node != root && treeObserverfactory.hasObserverFor(node)) {
observableRoots.add(node) observableRoots.add(node)
continue continue
} }
@@ -52,12 +52,12 @@ class PartialLayoutTraversal(
val activeChild = descriptor.getActiveChild(node) val activeChild = descriptor.getActiveChild(node)
for (child in children) { for (child in children) {
// it might make sense one day to remove id from the descriptor since its always the // It might make sense one day to remove id from the descriptor since its always the
// hash code // hash code
val childDescriptor = val childDescriptor =
descriptorRegister.descriptorForClassUnsafe(child::class.java).asAny() descriptorRegister.descriptorForClassUnsafe(child::class.java).asAny()
childrenIds.add(childDescriptor.getId(child)) childrenIds.add(childDescriptor.getId(child))
// if there is an active child then dont traverse it // If there is an active child then don't traverse it
if (activeChild == null) { if (activeChild == null) {
stack.add(child) stack.add(child)
} }
@@ -79,7 +79,7 @@ class PartialLayoutTraversal(
childrenIds, childrenIds,
activeChildId)) activeChildId))
} catch (exception: Exception) { } catch (exception: Exception) {
Log.e(LogTag, "Error while processing node ${node.javaClass.name} ${node} ", exception) Log.e(LogTag, "Error while processing node ${node.javaClass.name} $node", exception)
} }
} }

View File

@@ -42,7 +42,7 @@ abstract class TreeObserver<T> {
val start = System.currentTimeMillis() val start = System.currentTimeMillis()
val (visitedNodes, observerRootsNodes) = context.layoutTraversal.traverse(root) val (visitedNodes, observerRootsNodes) = context.layoutTraversal.traverse(root)
// Add any new Observers // Add any new observers
for (observerRoot in observerRootsNodes) { for (observerRoot in observerRootsNodes) {
if (!children.containsKey(observerRoot.identityHashCode())) { if (!children.containsKey(observerRoot.identityHashCode())) {
@@ -55,7 +55,7 @@ abstract class TreeObserver<T> {
} }
} }
// remove any old observers // Remove any old observers
val observerRootIds = observerRootsNodes.map { it.identityHashCode() } val observerRootIds = observerRootsNodes.map { it.identityHashCode() }
for (childKey in children.keys) { for (childKey in children.keys) {
if (!observerRootIds.contains(childKey)) { if (!observerRootIds.contains(childKey)) {
@@ -68,7 +68,6 @@ abstract class TreeObserver<T> {
} }
} }
// send
Log.d(LogTag, "For Observer ${this.type} Sending ${visitedNodes.size} ") Log.d(LogTag, "For Observer ${this.type} Sending ${visitedNodes.size} ")
context.treeObserverManager.send( context.treeObserverManager.send(
SubtreeUpdate(type, visitedNodes, start, System.currentTimeMillis())) SubtreeUpdate(type, visitedNodes, start, System.currentTimeMillis()))