Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 701bbd6b authored by Stefan Andonian's avatar Stefan Andonian
Browse files

Write ViewCapture data to WmTrace when LauncherAppService dumps.

This allows apps like the Launcher to write ViewCapture data to the
wmtrace directory so it can be shown in their UI. Normally, Launcher
doesn't have the correct file permissions. Also, Launcher's dump method
is called after the wmtrace dir is written to the bug report, so we need
to dump sooner via a callback method.

Bug: 224595733
Test: Latency tested this change and verified that a bugreport generated
the file properly, moved it to the wmtrace directory, and was picked up
properly by the go/web-hv tool.

Change-Id: Id3ee275b33de04c4cfabbb4debc9bf90adb3fe16
parent 59dca6a3
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -107,7 +107,7 @@ class DdmHandleMotionTool private constructor(
        MotionToolsResponse.newBuilder().apply {
            tryCatchingMotionToolManagerExceptions {
                setPollTrace(PollTraceResponse.newBuilder()
                        .setExportedData(motionToolManager.pollTrace(pollTraceRequest.traceId)))
                        .setData(motionToolManager.pollTrace(pollTraceRequest.traceId)))
            }
        }.build()

@@ -115,7 +115,7 @@ class DdmHandleMotionTool private constructor(
        MotionToolsResponse.newBuilder().apply {
            tryCatchingMotionToolManagerExceptions {
                setEndTrace(EndTraceResponse.newBuilder()
                        .setExportedData(motionToolManager.endTrace(endTraceRequest.traceId)))
                        .setData(motionToolManager.endTrace(endTraceRequest.traceId)))
            }
        }.build()

+25 −27
Original line number Diff line number Diff line
@@ -23,7 +23,7 @@ import android.view.View
import android.view.WindowManagerGlobal
import androidx.annotation.VisibleForTesting
import com.android.app.viewcapture.ViewCapture
import com.android.app.viewcapture.data.ExportedData
import com.android.app.viewcapture.data.MotionWindowData

/**
 * Singleton to manage motion tracing sessions.
@@ -77,29 +77,29 @@ class MotionToolManager private constructor(private val windowManagerGlobal: Win
    }

    /**
     * Ends [ViewCapture] and returns the captured [ExportedData] since the [beginTrace] call or the
     * last [pollTrace] call.
     * Ends [ViewCapture] and returns the captured [MotionWindowData] since the [beginTrace] call or
     * the last [pollTrace] call.
     */
    @Synchronized
    fun endTrace(traceId: Int): ExportedData {
    fun endTrace(traceId: Int): MotionWindowData {
        Log.d(TAG, "End Trace for id: $traceId")
        val traceMetadata = traces.getOrElse(traceId) { throw UnknownTraceIdException(traceId) }
        val exportedData = pollTrace(traceId)
        val data = pollTrace(traceId)
        traceMetadata.stopTrace()
        traces.remove(traceId)
        return exportedData
        return data
    }

    /**
     * Returns the [ExportedData] captured since the [beginTrace] call or the last [pollTrace] call.
     * Returns the [MotionWindowData] captured since the [beginTrace] call or last [pollTrace] call.
     * This function can only be used after [beginTrace] is called and before [endTrace] is called.
     */
    @Synchronized
    fun pollTrace(traceId: Int): ExportedData {
    fun pollTrace(traceId: Int): MotionWindowData {
        val traceMetadata = traces.getOrElse(traceId) { throw UnknownTraceIdException(traceId) }
        val exportedData = getExportedDataFromViewCapture(traceMetadata)
        traceMetadata.updateLastPolledTime(exportedData)
        return exportedData
        val data = getDataFromViewCapture(traceMetadata)
        traceMetadata.updateLastPolledTime(data)
        return data
    }

    /**
@@ -115,20 +115,18 @@ class MotionToolManager private constructor(private val windowManagerGlobal: Win
        traceIdCounter = 0
    }

    private fun getExportedDataFromViewCapture(traceMetadata: TraceMetadata): ExportedData {
    private fun getDataFromViewCapture(traceMetadata: TraceMetadata): MotionWindowData {
        val rootView =
            getRootView(traceMetadata.windowId)
                ?: throw WindowNotFoundException(traceMetadata.windowId)

        val exportedData = viewCapture
            .getDumpTask(rootView)
            ?.orElse(null)
            ?.get() ?: return ExportedData.newBuilder().build()

        val filteredFrameData = exportedData.frameDataList
                ?.filter { it.timestamp > traceMetadata.lastPolledTime }

        return exportedData.toBuilder()
        val data: MotionWindowData = viewCapture
            .getDumpTask(rootView).get()
            ?.orElse(null) ?: return MotionWindowData.newBuilder().build()
        val filteredFrameData = data.frameDataList.filter {
            it.timestamp > traceMetadata.lastPolledTime
        }
        return data.toBuilder()
            .clearFrameData()
            .addAllFrameData(filteredFrameData)
            .build()
@@ -148,9 +146,9 @@ private data class TraceMetadata(
    var lastPolledTime: Long,
    var stopTrace: () -> Unit
) {
    fun updateLastPolledTime(exportedData: ExportedData?) {
        exportedData?.frameDataList?.maxOfOrNull { it.timestamp }?.let { maxFrameTimestamp ->
            lastPolledTime = maxFrameTimestamp
    fun updateLastPolledTime(data: MotionWindowData?) {
        data?.frameDataList?.maxOfOrNull { it.timestamp }?.let {
            lastPolledTime = it
        }
    }
}
+2 −2
Original line number Diff line number Diff line
@@ -98,7 +98,7 @@ message EndTraceRequest {
}

message EndTraceResponse {
  optional com.android.app.viewcapture.data.ExportedData exported_data = 1;
  optional com.android.app.viewcapture.data.MotionWindowData data = 1;
}

// Polls collected motion trace data collected since the last PollTraceRequest (or the
@@ -108,6 +108,6 @@ message PollTraceRequest {
}

message PollTraceResponse {
  optional com.android.app.viewcapture.data.ExportedData exported_data = 1;
  optional com.android.app.viewcapture.data.MotionWindowData data = 1;
}
+3 −3
Original line number Diff line number Diff line
@@ -119,7 +119,7 @@ class DdmHandleMotionToolTest {
        activityScenarioRule.scenario.onActivity {
            val beginTraceResponse = performBeginTraceRequest(getActivityViewRootId())
            val endTraceResponse = performEndTraceRequest(beginTraceResponse.beginTrace.traceId)
            Assert.assertTrue(endTraceResponse.endTrace.exportedData.frameDataList.isEmpty())
            Assert.assertTrue(endTraceResponse.endTrace.data.frameDataList.isEmpty())
        }
    }

@@ -133,11 +133,11 @@ class DdmHandleMotionToolTest {
                activity.findViewById<View>(android.R.id.content).viewTreeObserver.dispatchOnDraw()

                val pollTraceResponse = performPollTraceRequest(traceId)
                assertEquals(1, pollTraceResponse.pollTrace.exportedData.frameDataList.size)
                assertEquals(1, pollTraceResponse.pollTrace.data.frameDataList.size)

                // Verify that frameData is only included once and is not returned again
                val endTraceResponse = performEndTraceRequest(traceId)
                assertEquals(0, endTraceResponse.endTrace.exportedData.frameDataList.size)
                assertEquals(0, endTraceResponse.endTrace.data.frameDataList.size)
            }
        }
    }
+4 −4
Original line number Diff line number Diff line
@@ -87,12 +87,12 @@ class MotionToolManagerTest {
            Choreographer.getInstance().postFrameCallback {
                activity.findViewById<View>(android.R.id.content).viewTreeObserver.dispatchOnDraw()

                val polledExportedData = motionToolManager.pollTrace(traceId)
                assertEquals(1, polledExportedData.frameDataList.size)
                val polledData = motionToolManager.pollTrace(traceId)
                assertEquals(1, polledData.frameDataList.size)

                // Verify that frameData is only included once and is not returned again
                val endExportedData = motionToolManager.endTrace(traceId)
                assertEquals(0, endExportedData.frameDataList.size)
                val endData = motionToolManager.endTrace(traceId)
                assertEquals(0, endData.frameDataList.size)
            }
        }
    }
Loading