summaryrefslogtreecommitdiff
path: root/layout-inspector/src
diff options
context:
space:
mode:
authorPierfrancesco Soffritti <psoffritti@google.com>2022-02-23 16:39:45 +0000
committerPierfrancesco Soffritti <psoffritti@google.com>2022-03-08 15:09:35 +0000
commitf1ec2d9c6ee7a37fd71213490116081c9e353f19 (patch)
tree72ff649535f4821c9a134a6f3639dea8eae7bb3d /layout-inspector/src
parent27891d95e92ff4944891a65fcba8a1e235a61c33 (diff)
downloadidea-f1ec2d9c6ee7a37fd71213490116081c9e353f19.tar.gz
Update spinner message during connection
When connecting to AppInspectionInspectorClient we have a 30 seconds timeout. When the timeout is reached we fallback to the LegacyClient. This change updates the UI so that the user is updated every time we make progress in the connection process. By doing this the user will know that something is happening. Test: InspectorClientLaunchMonitorTest, InspectorModelTest Bug: 209700484 Change-Id: I1d2b804df06f7bd63d8e25556bdc3d24a6ad993d
Diffstat (limited to 'layout-inspector/src')
-rw-r--r--layout-inspector/src/com/android/tools/idea/layoutinspector/LayoutInspector.kt1
-rw-r--r--layout-inspector/src/com/android/tools/idea/layoutinspector/model/InspectorModel.kt8
-rw-r--r--layout-inspector/src/com/android/tools/idea/layoutinspector/pipeline/AbstractInspectorClient.kt7
-rw-r--r--layout-inspector/src/com/android/tools/idea/layoutinspector/pipeline/InspectorClient.kt7
-rw-r--r--layout-inspector/src/com/android/tools/idea/layoutinspector/pipeline/InspectorClientLaunchMonitor.kt4
-rw-r--r--layout-inspector/src/com/android/tools/idea/layoutinspector/ui/DeviceViewPanel.kt39
6 files changed, 63 insertions, 3 deletions
diff --git a/layout-inspector/src/com/android/tools/idea/layoutinspector/LayoutInspector.kt b/layout-inspector/src/com/android/tools/idea/layoutinspector/LayoutInspector.kt
index c169e3f49f3..95088661707 100644
--- a/layout-inspector/src/com/android/tools/idea/layoutinspector/LayoutInspector.kt
+++ b/layout-inspector/src/com/android/tools/idea/layoutinspector/LayoutInspector.kt
@@ -92,6 +92,7 @@ class LayoutInspector private constructor(
client.registerErrorCallback(::logError)
client.registerTreeEventCallback(::loadComponentTree)
client.registerStateCallback { state -> if (state == InspectorClient.State.CONNECTED) updateConnection(client) }
+ client.registerConnectionTimeoutCallback { state -> layoutInspectorModel.fireAttachStateEvent(state) }
stats.start(client.isCapturing)
}
else {
diff --git a/layout-inspector/src/com/android/tools/idea/layoutinspector/model/InspectorModel.kt b/layout-inspector/src/com/android/tools/idea/layoutinspector/model/InspectorModel.kt
index b57938c36a6..22df6436bca 100644
--- a/layout-inspector/src/com/android/tools/idea/layoutinspector/model/InspectorModel.kt
+++ b/layout-inspector/src/com/android/tools/idea/layoutinspector/model/InspectorModel.kt
@@ -20,6 +20,7 @@ import com.android.tools.idea.layoutinspector.pipeline.InspectorClient
import com.android.tools.idea.layoutinspector.properties.ViewNodeAndResourceLookup
import com.android.tools.idea.layoutinspector.resource.ResourceLookup
import com.android.tools.idea.util.ListenerCollection
+import com.google.wireless.android.sdk.stats.DynamicLayoutInspectorErrorInfo
import com.intellij.openapi.project.Project
import layoutinspector.view.inspection.LayoutInspectorViewProtocol
import layoutinspector.view.inspection.LayoutInspectorViewProtocol.FoldEvent.SpecialAngles.NO_FOLD_ANGLE_VALUE
@@ -66,6 +67,9 @@ class InspectorModel(val project: Project) : ViewNodeAndResourceLookup {
}
}
+ // TODO: update all listeners to use ListenerCollection
+ val attachStageListeners = ListenerCollection.createWithDirectExecutor<(DynamicLayoutInspectorErrorInfo.AttachErrorState) -> Unit>()
+
val windows = mutableMapOf<Any, AndroidWindow>()
// synthetic node to hold the roots of the current windows.
val root = ViewNode("android.root - hide")
@@ -132,6 +136,10 @@ class InspectorModel(val project: Project) : ViewNodeAndResourceLookup {
*/
operator fun get(id: String) = ViewNode.readAccess { root.flatten().find { it.viewId?.name == id } }
+ fun fireAttachStateEvent(state: DynamicLayoutInspectorErrorInfo.AttachErrorState) {
+ attachStageListeners.forEach { it.invoke(state) }
+ }
+
/**
* Get the root of the view tree that the [view] parameter lives in.
*
diff --git a/layout-inspector/src/com/android/tools/idea/layoutinspector/pipeline/AbstractInspectorClient.kt b/layout-inspector/src/com/android/tools/idea/layoutinspector/pipeline/AbstractInspectorClient.kt
index b3740644305..a8c50e083e5 100644
--- a/layout-inspector/src/com/android/tools/idea/layoutinspector/pipeline/AbstractInspectorClient.kt
+++ b/layout-inspector/src/com/android/tools/idea/layoutinspector/pipeline/AbstractInspectorClient.kt
@@ -54,8 +54,9 @@ abstract class AbstractInspectorClient(
private val stateCallbacks = ListenerCollection.createWithDirectExecutor<(InspectorClient.State) -> Unit>()
private val errorCallbacks = ListenerCollection.createWithDirectExecutor<(String) -> Unit>()
private val treeEventCallbacks = ListenerCollection.createWithDirectExecutor<(Any) -> Unit>()
+ private val attachStateListeners = ListenerCollection.createWithDirectExecutor<(DynamicLayoutInspectorErrorInfo.AttachErrorState) -> Unit>()
- var launchMonitor: InspectorClientLaunchMonitor = InspectorClientLaunchMonitor()
+ var launchMonitor: InspectorClientLaunchMonitor = InspectorClientLaunchMonitor(attachStateListeners)
@TestOnly set
override fun dispose() {
@@ -74,6 +75,10 @@ abstract class AbstractInspectorClient(
treeEventCallbacks.add(callback)
}
+ final override fun registerConnectionTimeoutCallback(callback: (DynamicLayoutInspectorErrorInfo.AttachErrorState) -> Unit) {
+ attachStateListeners.add(callback)
+ }
+
/**
* Fire relevant callbacks registered with [registerStateCallback], if present.
*/
diff --git a/layout-inspector/src/com/android/tools/idea/layoutinspector/pipeline/InspectorClient.kt b/layout-inspector/src/com/android/tools/idea/layoutinspector/pipeline/InspectorClient.kt
index 7fd8df33d85..18a5fad2266 100644
--- a/layout-inspector/src/com/android/tools/idea/layoutinspector/pipeline/InspectorClient.kt
+++ b/layout-inspector/src/com/android/tools/idea/layoutinspector/pipeline/InspectorClient.kt
@@ -94,6 +94,11 @@ interface InspectorClient: Disposable {
fun registerTreeEventCallback(callback: (Any) -> Unit)
/**
+ * Register a handle that is triggered when this client receives a launch event.
+ */
+ fun registerConnectionTimeoutCallback(callback: (DynamicLayoutInspectorErrorInfo.AttachErrorState) -> Unit)
+
+ /**
* Connect this client to the device.
*
* Use [registerStateCallback] and check for [State.CONNECTED] if you need to know when this has
@@ -214,6 +219,8 @@ object DisconnectedClient : InspectorClient {
override fun registerStateCallback(callback: (InspectorClient.State) -> Unit) = Unit
override fun registerErrorCallback(callback: (String) -> Unit) = Unit
override fun registerTreeEventCallback(callback: (Any) -> Unit) = Unit
+ override fun registerConnectionTimeoutCallback(callback: (DynamicLayoutInspectorErrorInfo.AttachErrorState) -> Unit) = Unit
+
override fun startFetching(): CompletableFuture<Unit> = CompletableFuture.completedFuture(Unit)
override fun stopFetching(): CompletableFuture<Unit> = CompletableFuture.completedFuture(Unit)
override fun refresh() {}
diff --git a/layout-inspector/src/com/android/tools/idea/layoutinspector/pipeline/InspectorClientLaunchMonitor.kt b/layout-inspector/src/com/android/tools/idea/layoutinspector/pipeline/InspectorClientLaunchMonitor.kt
index adcc24f7f7f..da130174865 100644
--- a/layout-inspector/src/com/android/tools/idea/layoutinspector/pipeline/InspectorClientLaunchMonitor.kt
+++ b/layout-inspector/src/com/android/tools/idea/layoutinspector/pipeline/InspectorClientLaunchMonitor.kt
@@ -16,6 +16,7 @@
package com.android.tools.idea.layoutinspector.pipeline
import com.android.tools.idea.layoutinspector.metrics.LayoutInspectorMetrics
+import com.android.tools.idea.util.ListenerCollection
import com.google.wireless.android.sdk.stats.DynamicLayoutInspectorErrorInfo.AttachErrorState
import com.google.wireless.android.sdk.stats.DynamicLayoutInspectorEvent
import com.intellij.openapi.diagnostic.Logger
@@ -30,6 +31,7 @@ import java.util.concurrent.TimeUnit
@VisibleForTesting const val CONNECT_TIMEOUT_SECONDS: Long = 30L
class InspectorClientLaunchMonitor(
+ private val attachErrorStateListeners: ListenerCollection<(AttachErrorState) -> Unit>,
@TestOnly private val executorService: ScheduledExecutorService = AppExecutorUtil.getAppScheduledExecutorService()
) {
private var lastUpdate: Long = 0L
@@ -44,6 +46,8 @@ class InspectorClientLaunchMonitor(
}
fun updateProgress(progress: AttachErrorState) {
+ attachErrorStateListeners.forEach { it.invoke(progress) }
+
if (progress <= currentProgress) {
return
}
diff --git a/layout-inspector/src/com/android/tools/idea/layoutinspector/ui/DeviceViewPanel.kt b/layout-inspector/src/com/android/tools/idea/layoutinspector/ui/DeviceViewPanel.kt
index 3b206579304..040cd7e8e2a 100644
--- a/layout-inspector/src/com/android/tools/idea/layoutinspector/ui/DeviceViewPanel.kt
+++ b/layout-inspector/src/com/android/tools/idea/layoutinspector/ui/DeviceViewPanel.kt
@@ -33,7 +33,6 @@ import com.android.tools.idea.appinspection.ide.ui.SelectProcessAction
import com.android.tools.idea.appinspection.ide.ui.buildDeviceName
import com.android.tools.idea.appinspection.inspector.api.process.DeviceDescriptor
import com.android.tools.idea.concurrency.AndroidExecutors
-import com.android.tools.idea.flags.StudioFlags
import com.android.tools.idea.layoutinspector.LayoutInspector
import com.android.tools.idea.layoutinspector.model.REBOOT_FOR_LIVE_INSPECTOR_MESSAGE_KEY
import com.android.tools.idea.layoutinspector.model.ViewNode
@@ -43,6 +42,7 @@ import com.android.tools.idea.layoutinspector.pipeline.InspectorClient.Capabilit
import com.android.tools.idea.layoutinspector.pipeline.InspectorClientSettings
import com.android.tools.idea.layoutinspector.snapshots.CaptureSnapshotAction
import com.google.common.annotations.VisibleForTesting
+import com.google.wireless.android.sdk.stats.DynamicLayoutInspectorErrorInfo
import com.intellij.icons.AllIcons
import com.intellij.ide.BrowserUtil
import com.intellij.openapi.Disposable
@@ -67,6 +67,7 @@ import icons.StudioIcons
import icons.StudioIcons.LayoutInspector.LIVE_UPDATES
import org.jetbrains.android.util.AndroidBundle
import org.jetbrains.annotations.TestOnly
+import org.jetbrains.kotlin.idea.actions.internal.refactoringTesting.edtExecute
import java.awt.BorderLayout
import java.awt.Container
import java.awt.Cursor
@@ -304,6 +305,40 @@ class DeviceViewPanel(
loadingPane.add(layeredPane, BorderLayout.CENTER)
add(loadingPane, BorderLayout.CENTER)
val model = layoutInspector.layoutInspectorModel
+
+ model.attachStageListeners.add { state ->
+ val text = when (state) {
+ DynamicLayoutInspectorErrorInfo.AttachErrorState.UNKNOWN_ATTACH_ERROR_STATE -> "Unknown state"
+ DynamicLayoutInspectorErrorInfo.AttachErrorState.NOT_STARTED -> "Starting"
+ DynamicLayoutInspectorErrorInfo.AttachErrorState.ADB_PING -> "Adb ping success"
+ DynamicLayoutInspectorErrorInfo.AttachErrorState.ATTACH_SUCCESS -> "Attach success"
+ DynamicLayoutInspectorErrorInfo.AttachErrorState.START_REQUEST_SENT -> "Start request sent"
+ DynamicLayoutInspectorErrorInfo.AttachErrorState.START_RECEIVED -> "Start request received"
+ DynamicLayoutInspectorErrorInfo.AttachErrorState.STARTED -> "Started"
+ DynamicLayoutInspectorErrorInfo.AttachErrorState.ROOTS_EVENT_SENT -> "Roots sent"
+ DynamicLayoutInspectorErrorInfo.AttachErrorState.ROOTS_EVENT_RECEIVED -> "Roots received"
+ DynamicLayoutInspectorErrorInfo.AttachErrorState.VIEW_INVALIDATION_CALLBACK -> "Capture started"
+ DynamicLayoutInspectorErrorInfo.AttachErrorState.SCREENSHOT_CAPTURED -> "Screenshot captured"
+ DynamicLayoutInspectorErrorInfo.AttachErrorState.VIEW_HIERARCHY_CAPTURED -> "Hierarchy captured"
+ DynamicLayoutInspectorErrorInfo.AttachErrorState.RESPONSE_SENT -> "Response sent"
+ DynamicLayoutInspectorErrorInfo.AttachErrorState.LAYOUT_EVENT_RECEIVED -> "View information received"
+ DynamicLayoutInspectorErrorInfo.AttachErrorState.COMPOSE_REQUEST_SENT -> "Compose information request"
+ DynamicLayoutInspectorErrorInfo.AttachErrorState.COMPOSE_RESPONSE_RECEIVED -> "Compose information received"
+ DynamicLayoutInspectorErrorInfo.AttachErrorState.LEGACY_WINDOW_LIST_REQUESTED -> "Legacy window list requested"
+ DynamicLayoutInspectorErrorInfo.AttachErrorState.LEGACY_WINDOW_LIST_RECEIVED -> "Legacy window list received"
+ DynamicLayoutInspectorErrorInfo.AttachErrorState.LEGACY_HIERARCHY_REQUESTED -> "Legacy hierarchy requested"
+ DynamicLayoutInspectorErrorInfo.AttachErrorState.LEGACY_HIERARCHY_RECEIVED -> "Legacy hierarchy received"
+ DynamicLayoutInspectorErrorInfo.AttachErrorState.LEGACY_SCREENSHOT_REQUESTED -> "Legacy screenshot requested"
+ DynamicLayoutInspectorErrorInfo.AttachErrorState.LEGACY_SCREENSHOT_RECEIVED -> "Legacy screenshot received"
+ DynamicLayoutInspectorErrorInfo.AttachErrorState.PARSED_COMPONENT_TREE -> "Compose tree parsed"
+ DynamicLayoutInspectorErrorInfo.AttachErrorState.MODEL_UPDATED -> "Update complete"
+ }
+
+ if (text.isNotEmpty()) {
+ loadingPane.setLoadingText(text)
+ }
+ }
+
processes?.addSelectedProcessListeners(newSingleThreadExecutor()) {
if (processes.selectedProcess?.isRunning == true) {
if (model.isEmpty) {
@@ -311,7 +346,7 @@ class DeviceViewPanel(
}
}
if (processes.selectedProcess == null) {
- loadingPane.stopLoading()
+ loadingPane.stopLoading()
}
}
model.modificationListeners.add { old, new, _ ->