diff --git a/android/src/main/java/com/facebook/flipper/plugins/uidebugger/core/ActivityTracker.kt b/android/src/main/java/com/facebook/flipper/plugins/uidebugger/core/ActivityTracker.kt index 15e707cb8..0fa8745f8 100644 --- a/android/src/main/java/com/facebook/flipper/plugins/uidebugger/core/ActivityTracker.kt +++ b/android/src/main/java/com/facebook/flipper/plugins/uidebugger/core/ActivityTracker.kt @@ -12,6 +12,7 @@ import android.app.Activity import android.app.Application import android.os.Build import android.os.Bundle +import android.view.View import java.lang.ref.WeakReference import java.lang.reflect.Field import java.lang.reflect.Method @@ -103,6 +104,11 @@ object ActivityTracker : Application.ActivityLifecycleCallbacks { return stack } + val decorViewToActivityMap: Map + get() { + return activitiesStack.toList().associateBy { it.window.decorView } + } + /** * Activity tracker is used to track activities. However, it cannot track via life-cycle events * all those activities that were created prior to initialisation via the `start(application: diff --git a/android/src/main/java/com/facebook/flipper/plugins/uidebugger/core/ApplicationRef.kt b/android/src/main/java/com/facebook/flipper/plugins/uidebugger/core/ApplicationRef.kt index 69f4e307d..52bf230d1 100644 --- a/android/src/main/java/com/facebook/flipper/plugins/uidebugger/core/ApplicationRef.kt +++ b/android/src/main/java/com/facebook/flipper/plugins/uidebugger/core/ApplicationRef.kt @@ -9,6 +9,7 @@ package com.facebook.flipper.plugins.uidebugger.core import android.app.Activity import android.app.Application +import android.view.View class ApplicationRef(val application: Application) { init { diff --git a/android/src/main/java/com/facebook/flipper/plugins/uidebugger/core/DecorViewTracker.kt b/android/src/main/java/com/facebook/flipper/plugins/uidebugger/core/DecorViewTracker.kt index 64a7fab24..25f57ac69 100644 --- a/android/src/main/java/com/facebook/flipper/plugins/uidebugger/core/DecorViewTracker.kt +++ b/android/src/main/java/com/facebook/flipper/plugins/uidebugger/core/DecorViewTracker.kt @@ -7,6 +7,7 @@ package com.facebook.flipper.plugins.uidebugger.core +import android.app.Activity import android.util.Log import android.view.View import android.view.ViewTreeObserver @@ -58,7 +59,14 @@ class DecorViewTracker(private val context: UIDContext, private val snapshotter: currentDecorView?.viewTreeObserver?.removeOnPreDrawListener(preDrawListener) // setup new listener on top most view, that will be the active child in traversal - val topView = rootViews.lastOrNull(ApplicationRefDescriptor::isUsefulRoot) + + val decorViewToActivity: Map = ActivityTracker.decorViewToActivityMap + + val topView = + rootViews.lastOrNull { view -> + val activityOrView = decorViewToActivity[view] ?: view + ApplicationRefDescriptor.isUsefulRoot(activityOrView) + } if (topView != null) { val throttler = diff --git a/android/src/main/java/com/facebook/flipper/plugins/uidebugger/core/Snapshot.kt b/android/src/main/java/com/facebook/flipper/plugins/uidebugger/core/Snapshot.kt index fb38f0130..24c564944 100644 --- a/android/src/main/java/com/facebook/flipper/plugins/uidebugger/core/Snapshot.kt +++ b/android/src/main/java/com/facebook/flipper/plugins/uidebugger/core/Snapshot.kt @@ -104,8 +104,8 @@ class PixelCopySnapshotter( bitmap: BitmapPool.ReusableBitmap ): Boolean { - val decorViewToActivity: Map = - applicationRef.activitiesStack.toList().associateBy { it.window.decorView } + + val decorViewToActivity: Map = ActivityTracker.decorViewToActivityMap val activityForDecorView = decorViewToActivity[view] ?: return false diff --git a/android/src/main/java/com/facebook/flipper/plugins/uidebugger/descriptors/ApplicationRefDescriptor.kt b/android/src/main/java/com/facebook/flipper/plugins/uidebugger/descriptors/ApplicationRefDescriptor.kt index b5a2cde29..3195c5409 100644 --- a/android/src/main/java/com/facebook/flipper/plugins/uidebugger/descriptors/ApplicationRefDescriptor.kt +++ b/android/src/main/java/com/facebook/flipper/plugins/uidebugger/descriptors/ApplicationRefDescriptor.kt @@ -10,6 +10,7 @@ package com.facebook.flipper.plugins.uidebugger.descriptors import android.app.Activity import android.view.View import android.view.ViewGroup +import com.facebook.flipper.plugins.uidebugger.core.ActivityTracker import com.facebook.flipper.plugins.uidebugger.core.ApplicationRef import com.facebook.flipper.plugins.uidebugger.model.Bounds import com.facebook.flipper.plugins.uidebugger.util.DisplayMetrics @@ -33,12 +34,11 @@ object ApplicationRefDescriptor : ChainedDescriptor() { override fun onGetChildren(node: ApplicationRef): List { val children = mutableListOf() - val activeRoots = node.rootsResolver.rootViews() + val rootViews = node.rootsResolver.rootViews() - val decorViewToActivity: Map = - node.activitiesStack.toList().associateBy { it.window.decorView } + val decorViewToActivity: Map = ActivityTracker.decorViewToActivityMap - for (root in activeRoots) { + for (root in rootViews) { // if there is an activity for this root view use that, // if not just return the root view that was added directly to the window manager val activity = decorViewToActivity[root] @@ -52,16 +52,31 @@ object ApplicationRefDescriptor : ChainedDescriptor() { return children } - fun isUsefulRoot(obj: Any): Boolean { - if (obj is Activity) { + /** + * arg is either an acitivity if the root view has one other views the root view attached to the + * window manager returns boolean indicating whether we are interested in it and whether we should + * track, traverse and snapshot it + */ + fun isUsefulRoot(rootViewOrActivity: Any): Boolean { + val className = rootViewOrActivity.javaClass.name + + if (className.contains("mediagallery.ui.MediaGalleryActivity")) { + // this activity doesn't contain the content and its actually in the decor view behind it, so + // skip it :/ + return false + } + + if (rootViewOrActivity is Activity) { + // in general we want views attached to activities return true } - val isFoldableOverlayInfraView = javaClass.simpleName.contains("OverlayHandlerView") + + val isFoldableOverlayInfraView = className.contains("OverlayHandlerView") return if (isFoldableOverlayInfraView) { false - } else if (obj is ViewGroup) { + } else if (rootViewOrActivity is ViewGroup) { // sometimes there is a root view on top that has no children that isn't useful to inspect - obj.childCount > 0 + rootViewOrActivity.childCount > 0 } else { false }