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

Commit 31caca1b authored by Stefan Andonian's avatar Stefan Andonian Committed by Android (Google) Code Review
Browse files

Merge changes from topic "vc-proto-lite" into tm-qpr-dev

* changes:
  Migrating MotionLib tool from Protobuf-nano to Protobuf-lite.
  Migrating ViewCapture tool from Protobuf-nano to Protobuf-lite.
parents 01f2673a 3e6ed2b6
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -20,7 +20,7 @@ java_library {
    name: "motion_tool_proto",
    srcs: ["src/com/android/app/motiontool/proto/*.proto"],
    proto: {
        type: "nano",
        type: "lite",
        local_include_dirs:[
            "src/com/android/app/motiontool/proto"
        ],
@@ -29,7 +29,7 @@ java_library {
        ],
    },
    static_libs: [
        "libprotobuf-java-nano",
        "libprotobuf-java-lite",
        "view_capture_proto",
    ],
    java_version: "1.8",
+15 −9
Original line number Diff line number Diff line
@@ -38,7 +38,7 @@ android {

dependencies {
    implementation "androidx.core:core:1.9.0"
    implementation PROTOBUF_DEPENDENCY
    implementation "com.google.protobuf:protobuf-lite:${protobuf_version}"
    api project(":ViewCaptureLib")
    androidTestImplementation project(':SharedTestLib')
    androidTestImplementation 'androidx.test.ext:junit:1.1.3'
@@ -49,14 +49,20 @@ protobuf {
    // Configure the protoc executable
    protoc {
        artifact = "com.google.protobuf:protoc:${protobuf_version}${PROTO_ARCH_SUFFIX}"
    }
    plugins {
        javalite {
            // The codegen for lite comes as a separate artifact
            artifact = "com.google.protobuf:protoc-gen-javalite:${protobuf_version}${PROTO_ARCH_SUFFIX}"
        }
    }
    generateProtoTasks {
        all().each { task ->
            task.builtins {
                remove java
                    javanano {
                        option "enum_style=c"
                    }
            }
            task.plugins {
                javalite { }
            }
        }
    }
+48 −62
Original line number Diff line number Diff line
@@ -17,9 +17,7 @@
package com.android.app.motiontool

import android.ddm.DdmHandle
import com.android.app.motiontool.nano.*
import com.google.protobuf.nano.InvalidProtocolBufferNanoException
import com.google.protobuf.nano.MessageNano
import com.google.protobuf.InvalidProtocolBufferException
import org.apache.harmony.dalvik.ddmc.Chunk
import org.apache.harmony.dalvik.ddmc.ChunkHandler
import org.apache.harmony.dalvik.ddmc.DdmServer
@@ -67,19 +65,18 @@ class DdmHandleMotionTool private constructor(
        val protoRequest =
            try {
                MotionToolsRequest.parseFrom(requestDataBuffer.array())
            } catch (e: InvalidProtocolBufferNanoException) {
                val parseErrorResponse =
                    ErrorResponse().apply {
                        code = ErrorResponse.INVALID_REQUEST
                        message = "Invalid request format (Protobuf parse exception)"
                    }
                val wrappedResponse = MotionToolsResponse().apply { error = parseErrorResponse }
                val responseData = MessageNano.toByteArray(wrappedResponse)
            } catch (e: InvalidProtocolBufferException) {
                val responseData: ByteArray = MotionToolsResponse.newBuilder()
                        .setError(ErrorResponse.newBuilder()
                                .setCode(ErrorResponse.Code.INVALID_REQUEST)
                                .setMessage("Invalid request format (Protobuf parse exception)"))
                        .build()
                        .toByteArray()
                return Chunk(CHUNK_MOTO, responseData, 0, responseData.size)
            }

        val response =
            when (protoRequest.typeCase) {
            when (protoRequest.typeCase.number) {
                MotionToolsRequest.HANDSHAKE_FIELD_NUMBER ->
                    handleHandshakeRequest(protoRequest.handshake)
                MotionToolsRequest.BEGIN_TRACE_FIELD_NUMBER ->
@@ -89,61 +86,50 @@ class DdmHandleMotionTool private constructor(
                MotionToolsRequest.END_TRACE_FIELD_NUMBER ->
                    handleEndTraceRequest(protoRequest.endTrace)
                else ->
                    MotionToolsResponse().apply {
                        error =
                            ErrorResponse().apply {
                                code = ErrorResponse.INVALID_REQUEST
                                message = "Unknown request type"
                            }
                    }
                    MotionToolsResponse.newBuilder().setError(ErrorResponse.newBuilder()
                            .setCode(ErrorResponse.Code.INVALID_REQUEST)
                            .setMessage("Unknown request type")).build()
            }

        val responseData = MessageNano.toByteArray(response)
        val responseData = response.toByteArray()
        return Chunk(CHUNK_MOTO, responseData, 0, responseData.size)
    }

    private fun handleBeginTraceRequest(beginTraceRequest: BeginTraceRequest) =
        MotionToolsResponse().apply {
    private fun handleBeginTraceRequest(beginTraceRequest: BeginTraceRequest): MotionToolsResponse =
        MotionToolsResponse.newBuilder().apply {
            tryCatchingMotionToolManagerExceptions {
                beginTrace =
                    BeginTraceResponse().apply {
                        traceId = motionToolManager.beginTrace(beginTraceRequest.window.rootWindow)
                    }
            }
                setBeginTrace(BeginTraceResponse.newBuilder().setTraceId(
                        motionToolManager.beginTrace(beginTraceRequest.window.rootWindow)))
            }
        }.build()

    private fun handlePollTraceRequest(pollTraceRequest: PollTraceRequest) =
        MotionToolsResponse().apply {
    private fun handlePollTraceRequest(pollTraceRequest: PollTraceRequest): MotionToolsResponse =
        MotionToolsResponse.newBuilder().apply {
            tryCatchingMotionToolManagerExceptions {
                pollTrace =
                    PollTraceResponse().apply {
                        exportedData = motionToolManager.pollTrace(pollTraceRequest.traceId)
                    }
            }
                setPollTrace(PollTraceResponse.newBuilder()
                        .setExportedData(motionToolManager.pollTrace(pollTraceRequest.traceId)))
            }
        }.build()

    private fun handleEndTraceRequest(endTraceRequest: EndTraceRequest) =
        MotionToolsResponse().apply {
    private fun handleEndTraceRequest(endTraceRequest: EndTraceRequest): MotionToolsResponse =
        MotionToolsResponse.newBuilder().apply {
            tryCatchingMotionToolManagerExceptions {
                endTrace =
                    EndTraceResponse().apply {
                        exportedData = motionToolManager.endTrace(endTraceRequest.traceId)
                    }
            }
                setEndTrace(EndTraceResponse.newBuilder()
                        .setExportedData(motionToolManager.endTrace(endTraceRequest.traceId)))
            }
        }.build()

    private fun handleHandshakeRequest(handshakeRequest: HandshakeRequest) =
        MotionToolsResponse().apply {
            handshake =
                HandshakeResponse().apply {
                    serverVersion = SERVER_VERSION
                    status =
                        if (motionToolManager.hasWindow(handshakeRequest.window)) {
                            HandshakeResponse.OK
                        } else {
                            HandshakeResponse.WINDOW_NOT_FOUND
                        }
                }
    private fun handleHandshakeRequest(handshakeRequest: HandshakeRequest): MotionToolsResponse {
        val status = if (motionToolManager.hasWindow(handshakeRequest.window))
            HandshakeResponse.Status.OK
        else
            HandshakeResponse.Status.WINDOW_NOT_FOUND

        return MotionToolsResponse.newBuilder()
                .setHandshake(HandshakeResponse.newBuilder()
                        .setServerVersion(SERVER_VERSION)
                        .setStatus(status))
                .build()
    }

    /**
@@ -151,25 +137,25 @@ class DdmHandleMotionTool private constructor(
     * exception being caught, the error response field of the [MotionToolsResponse] is being set
     * with the according [ErrorResponse].
     */
    private fun MotionToolsResponse.tryCatchingMotionToolManagerExceptions(block: () -> Unit) {
    private fun MotionToolsResponse.Builder.tryCatchingMotionToolManagerExceptions(block: () -> Unit) {
        try {
            block()
        } catch (e: UnknownTraceIdException) {
            error = createUnknownTraceIdResponse(e.traceId)
            setError(createUnknownTraceIdResponse(e.traceId))
        } catch (e: WindowNotFoundException) {
            error = createWindowNotFoundResponse(e.windowId)
            setError(createWindowNotFoundResponse(e.windowId))
        }
    }

    private fun createUnknownTraceIdResponse(traceId: Int) =
        ErrorResponse().apply {
            this.code = ErrorResponse.UNKNOWN_TRACE_ID
        ErrorResponse.newBuilder().apply {
            this.code = ErrorResponse.Code.UNKNOWN_TRACE_ID
            this.message = "No running Trace found with traceId $traceId"
        }

    private fun createWindowNotFoundResponse(windowId: String) =
        ErrorResponse().apply {
            this.code = ErrorResponse.WINDOW_NOT_FOUND
        ErrorResponse.newBuilder().apply {
            this.code = ErrorResponse.Code.WINDOW_NOT_FOUND
            this.message = "No window found with windowId $windowId"
        }

+13 −10
Original line number Diff line number Diff line
@@ -22,9 +22,8 @@ import android.view.Choreographer
import android.view.View
import android.view.WindowManagerGlobal
import androidx.annotation.VisibleForTesting
import com.android.app.motiontool.nano.WindowIdentifier
import com.android.app.viewcapture.ViewCapture
import com.android.app.viewcapture.data.nano.ExportedData
import com.android.app.viewcapture.data.ExportedData

/**
 * Singleton to manage motion tracing sessions.
@@ -120,15 +119,19 @@ class MotionToolManager private constructor(private val windowManagerGlobal: Win
        val rootView =
            getRootView(traceMetadata.windowId)
                ?: throw WindowNotFoundException(traceMetadata.windowId)
        return viewCapture

        val exportedData = viewCapture
            .getDumpTask(rootView)
            ?.orElse(null)
            ?.get()
            ?.apply {
                frameData = frameData?.filter { it.timestamp > traceMetadata.lastPolledTime }
                    ?.toTypedArray()
            }
            ?: ExportedData()
            ?.get() ?: return ExportedData.newBuilder().build()

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

        return exportedData.toBuilder()
                .clearFrameData()
                .addAllFrameData(filteredFrameData)
                .build()
    }

    private fun getRootView(windowId: String): View? {
@@ -146,7 +149,7 @@ private data class TraceMetadata(
    var stopTrace: () -> Unit
) {
    fun updateLastPolledTime(exportedData: ExportedData?) {
        exportedData?.frameData?.maxOfOrNull { it.timestamp }?.let { maxFrameTimestamp ->
        exportedData?.frameDataList?.maxOfOrNull { it.timestamp }?.let { maxFrameTimestamp ->
            lastPolledTime = maxFrameTimestamp
        }
    }
+31 −47
Original line number Diff line number Diff line
@@ -25,17 +25,7 @@ import androidx.test.ext.junit.rules.ActivityScenarioRule
import androidx.test.filters.SmallTest
import androidx.test.platform.app.InstrumentationRegistry
import com.android.app.motiontool.DdmHandleMotionTool.Companion.CHUNK_MOTO
import com.android.app.motiontool.nano.BeginTraceRequest
import com.android.app.motiontool.nano.EndTraceRequest
import com.android.app.motiontool.nano.ErrorResponse
import com.android.app.motiontool.nano.HandshakeRequest
import com.android.app.motiontool.nano.HandshakeResponse
import com.android.app.motiontool.nano.MotionToolsRequest
import com.android.app.motiontool.nano.MotionToolsResponse
import com.android.app.motiontool.nano.PollTraceRequest
import com.android.app.motiontool.nano.WindowIdentifier
import com.android.app.motiontool.util.TestActivity
import com.google.protobuf.nano.MessageNano
import junit.framework.Assert
import junit.framework.Assert.assertEquals
import org.apache.harmony.dalvik.ddmc.Chunk
@@ -74,45 +64,45 @@ class DdmHandleMotionToolTest {
    @Test
    fun testHandshakeErrorWithInvalidWindowId() {
        val handshakeResponse = performHandshakeRequest("InvalidWindowId")
        assertEquals(HandshakeResponse.WINDOW_NOT_FOUND, handshakeResponse.handshake.status)
        assertEquals(HandshakeResponse.Status.WINDOW_NOT_FOUND, handshakeResponse.handshake.status)
    }

    @Test
    fun testHandshakeOkWithValidWindowId() {
        val handshakeResponse = performHandshakeRequest(getActivityViewRootId())
        assertEquals(HandshakeResponse.OK, handshakeResponse.handshake.status)
        assertEquals(HandshakeResponse.Status.OK, handshakeResponse.handshake.status)
    }

    @Test
    fun testBeginFailsWithInvalidWindowId() {
        val errorResponse = performBeginTraceRequest("InvalidWindowId")
        assertEquals(ErrorResponse.WINDOW_NOT_FOUND, errorResponse.error.code)
        assertEquals(ErrorResponse.Code.WINDOW_NOT_FOUND, errorResponse.error.code)
    }

    @Test
    fun testEndTraceFailsWithoutPrecedingBeginTrace() {
        val errorResponse = performEndTraceRequest(0)
        assertEquals(ErrorResponse.UNKNOWN_TRACE_ID, errorResponse.error.code)
        assertEquals(ErrorResponse.Code.UNKNOWN_TRACE_ID, errorResponse.error.code)
    }

    @Test
    fun testPollTraceFailsWithoutPrecedingBeginTrace() {
        val errorResponse = performPollTraceRequest(0)
        assertEquals(ErrorResponse.UNKNOWN_TRACE_ID, errorResponse.error.code)
        assertEquals(ErrorResponse.Code.UNKNOWN_TRACE_ID, errorResponse.error.code)
    }

    @Test
    fun testEndTraceFailsWithInvalidTraceId() {
        val beginTraceResponse = performBeginTraceRequest(getActivityViewRootId())
        val endTraceResponse = performEndTraceRequest(beginTraceResponse.beginTrace.traceId + 1)
        assertEquals(ErrorResponse.UNKNOWN_TRACE_ID, endTraceResponse.error.code)
        assertEquals(ErrorResponse.Code.UNKNOWN_TRACE_ID, endTraceResponse.error.code)
    }

    @Test
    fun testPollTraceFailsWithInvalidTraceId() {
        val beginTraceResponse = performBeginTraceRequest(getActivityViewRootId())
        val endTraceResponse = performPollTraceRequest(beginTraceResponse.beginTrace.traceId + 1)
        assertEquals(ErrorResponse.UNKNOWN_TRACE_ID, endTraceResponse.error.code)
        assertEquals(ErrorResponse.Code.UNKNOWN_TRACE_ID, endTraceResponse.error.code)
    }

    @Test
@@ -121,7 +111,7 @@ class DdmHandleMotionToolTest {
        val requestChunk = Chunk(CHUNK_MOTO, requestBytes, 0, requestBytes.size)
        val responseChunk = ddmHandleMotionTool.handleChunk(requestChunk)
        val response = MotionToolsResponse.parseFrom(wrapChunk(responseChunk).array()).error
        assertEquals(ErrorResponse.INVALID_REQUEST, response.code)
        assertEquals(ErrorResponse.Code.INVALID_REQUEST, response.code)
    }

    @Test
@@ -129,7 +119,7 @@ class DdmHandleMotionToolTest {
        activityScenarioRule.scenario.onActivity {
            val beginTraceResponse = performBeginTraceRequest(getActivityViewRootId())
            val endTraceResponse = performEndTraceRequest(beginTraceResponse.beginTrace.traceId)
            Assert.assertTrue(endTraceResponse.endTrace.exportedData.frameData.isEmpty())
            Assert.assertTrue(endTraceResponse.endTrace.exportedData.frameDataList.isEmpty())
        }
    }

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

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

                // Verify that frameData is only included once and is not returned again
                val endTraceResponse = performEndTraceRequest(traceId)
                assertEquals(0, endTraceResponse.endTrace.exportedData.frameData.size)
                assertEquals(0, endTraceResponse.endTrace.exportedData.frameDataList.size)
            }
        }
    }

    private fun performPollTraceRequest(requestTraceId: Int): MotionToolsResponse {
        val pollTraceRequest = MotionToolsRequest().apply {
            pollTrace = PollTraceRequest().apply {
                traceId = requestTraceId
            }
        }
        val pollTraceRequest = MotionToolsRequest.newBuilder()
                .setPollTrace(PollTraceRequest.newBuilder()
                        .setTraceId(requestTraceId))
                .build()
        return performRequest(pollTraceRequest)
    }

    private fun performEndTraceRequest(requestTraceId: Int): MotionToolsResponse {
        val endTraceRequest = MotionToolsRequest().apply {
            endTrace = EndTraceRequest().apply {
                traceId = requestTraceId
            }
        }
        val endTraceRequest = MotionToolsRequest.newBuilder()
                .setEndTrace(EndTraceRequest.newBuilder()
                        .setTraceId(requestTraceId))
                .build()
        return performRequest(endTraceRequest)
    }

    private fun performBeginTraceRequest(windowId: String): MotionToolsResponse {
        val beginTraceRequest = MotionToolsRequest().apply {
            beginTrace = BeginTraceRequest().apply {
                window = WindowIdentifier().apply {
                    rootWindow = windowId
                }
            }
        }
        val beginTraceRequest = MotionToolsRequest.newBuilder()
                .setBeginTrace(BeginTraceRequest.newBuilder()
                        .setWindow(WindowIdentifier.newBuilder()
                                .setRootWindow(windowId)))
                .build()
        return performRequest(beginTraceRequest)
    }

    private fun performHandshakeRequest(windowId: String): MotionToolsResponse {
        val handshakeRequest = MotionToolsRequest().apply {
            handshake = HandshakeRequest().apply {
                window = WindowIdentifier().apply {
                    rootWindow = windowId
                }
                clientVersion = CLIENT_VERSION
            }
        }
        val handshakeRequest = MotionToolsRequest.newBuilder()
                .setHandshake(HandshakeRequest.newBuilder()
                        .setWindow(WindowIdentifier.newBuilder()
                                .setRootWindow(windowId))
                        .setClientVersion(CLIENT_VERSION))
                .build()
        return performRequest(handshakeRequest)
    }

    private fun performRequest(motionToolsRequest: MotionToolsRequest): MotionToolsResponse {
        val requestBytes = MessageNano.toByteArray(motionToolsRequest)
        val requestBytes = motionToolsRequest.toByteArray()
        val requestChunk = Chunk(CHUNK_MOTO, requestBytes, 0, requestBytes.size)
        val responseChunk = ddmHandleMotionTool.handleChunk(requestChunk)
        return MotionToolsResponse.parseFrom(wrapChunk(responseChunk).array())
Loading