tracing prototype: guest-side changes for gfxstream

Bug: 168843698

Change-Id: I22a7568bb8b28b8b3bafda7100dee4c2d7a6fe50
diff --git a/android-emu/android/base/Tracing.cpp b/android-emu/android/base/Tracing.cpp
index 0e635db..dd8e44b 100644
--- a/android-emu/android/base/Tracing.cpp
+++ b/android-emu/android/base/Tracing.cpp
@@ -25,6 +25,10 @@
 namespace android {
 namespace base {
 
+bool isTracingEnabled() {
+    return atrace_is_tag_enabled(ATRACE_TAG_GRAPHICS);
+}
+
 void ScopedTraceGuest::beginTraceImpl(const char* name) {
     atrace_begin(VK_TRACE_TAG, name);
 }
@@ -47,6 +51,11 @@
 namespace android {
 namespace base {
 
+bool isTracingEnabled() {
+    // TODO: Fuchsia
+    return false;
+}
+
 void ScopedTraceGuest::beginTraceImpl(const char* name) {
 #ifndef FUCHSIA_NO_TRACE
     TRACE_DURATION_BEGIN(VK_TRACE_TAG, name);
diff --git a/android-emu/android/base/Tracing.h b/android-emu/android/base/Tracing.h
index 3a78726..e13d202 100644
--- a/android-emu/android/base/Tracing.h
+++ b/android-emu/android/base/Tracing.h
@@ -16,6 +16,7 @@
 
 // Library to perform tracing. Talks to platform-specific
 // tracing libraries.
+
 namespace android {
 namespace base {
 
@@ -23,6 +24,11 @@
 void initializeTracing();
 void enableTracing();
 void disableTracing();
+// Some platform tracing libraries such as Perfetto can be enabled/disabled at
+// runtime. Allow the user to query if they are disabled or not, and take
+// further action based on it. The use case is to enable/disable tracing on the
+// host alongside.
+bool isTracingEnabled();
 
 class ScopedTrace {
 public:
@@ -36,6 +42,8 @@
 };
 #endif
 
+bool isTracingEnabled();
+
 class ScopedTraceGuest {
 public:
     ScopedTraceGuest(const char* name) : name_(name) {
diff --git a/system/OpenglSystemCommon/EmulatorFeatureInfo.h b/system/OpenglSystemCommon/EmulatorFeatureInfo.h
index 304ab36..da15346 100644
--- a/system/OpenglSystemCommon/EmulatorFeatureInfo.h
+++ b/system/OpenglSystemCommon/EmulatorFeatureInfo.h
@@ -117,6 +117,9 @@
 // A flag to _not_ ignore host opengl errors (now host opengl errors are ignored by default)
 static const char kGLESUseHostError[] = "ANDROID_EMU_gles_use_host_error";
 
+// Host side tracing
+static const char kHostSideTracing[] = "ANDROID_EMU_host_side_tracing";
+
 // Struct describing available emulator features
 struct EmulatorFeatureInfo {
 
@@ -138,7 +141,8 @@
         hasVulkanFreeMemorySync(false),
         hasVirtioGpuNativeSync(false),
         hasVulkanShaderFloat16Int8(false),
-        hasVulkanAsyncQueueSubmit(false)
+        hasVulkanAsyncQueueSubmit(false),
+        hasHostSideTracing(false)
     { }
 
     SyncImpl syncImpl;
@@ -159,6 +163,7 @@
     bool hasVirtioGpuNativeSync;
     bool hasVulkanShaderFloat16Int8;
     bool hasVulkanAsyncQueueSubmit;
+    bool hasHostSideTracing;
 };
 
 enum HostConnectionType {
diff --git a/system/OpenglSystemCommon/HostConnection.cpp b/system/OpenglSystemCommon/HostConnection.cpp
index 7ddf277..540f6c4 100644
--- a/system/OpenglSystemCommon/HostConnection.cpp
+++ b/system/OpenglSystemCommon/HostConnection.cpp
@@ -655,6 +655,7 @@
         queryAndSetVirtioGpuNativeSync(rcEnc);
         queryAndSetVulkanShaderFloat16Int8Support(rcEnc);
         queryAndSetVulkanAsyncQueueSubmitSupport(rcEnc);
+        queryAndSetHostSideTracingSupport(rcEnc);
         if (m_processPipe) {
             m_processPipe->processPipeInit(m_connectionType, rcEnc);
         }
@@ -917,3 +918,10 @@
         rcEnc->featureInfo()->hasVulkanAsyncQueueSubmit = true;
     }
 }
+
+void HostConnection::queryAndSetHostSideTracingSupport(ExtendedRCEncoderContext* rcEnc) {
+    std::string glExtensions = queryGLExtensions(rcEnc);
+    if (glExtensions.find(kHostSideTracing) != std::string::npos) {
+        rcEnc->featureInfo()->hasHostSideTracing = true;
+    }
+}
diff --git a/system/OpenglSystemCommon/HostConnection.h b/system/OpenglSystemCommon/HostConnection.h
index 32a1521..1220628 100644
--- a/system/OpenglSystemCommon/HostConnection.h
+++ b/system/OpenglSystemCommon/HostConnection.h
@@ -65,6 +65,9 @@
         return m_featureInfo.hasYUVCache; }
     bool hasAsyncUnmapBuffer() const {
         return m_featureInfo.hasAsyncUnmapBuffer; }
+    bool hasHostSideTracing() const {
+        return m_featureInfo.hasHostSideTracing;
+    }
     DmaImpl getDmaVersion() const { return m_featureInfo.dmaImpl; }
     void bindDmaContext(struct goldfish_dma_context* cxt) { m_dmaCxt = cxt; }
     void bindDmaDirectly(void* dmaPtr, uint64_t dmaPhysAddr) {
@@ -217,6 +220,7 @@
     void queryAndSetVirtioGpuNativeSync(ExtendedRCEncoderContext *rcEnc);
     void queryAndSetVulkanShaderFloat16Int8Support(ExtendedRCEncoderContext *rcEnc);
     void queryAndSetVulkanAsyncQueueSubmitSupport(ExtendedRCEncoderContext *rcEnc);
+    void queryAndSetHostSideTracingSupport(ExtendedRCEncoderContext *rcEnc);
 
 private:
     HostConnectionType m_connectionType;
diff --git a/system/OpenglSystemCommon/ProcessPipe.cpp b/system/OpenglSystemCommon/ProcessPipe.cpp
index c79bf17..bca6388 100644
--- a/system/OpenglSystemCommon/ProcessPipe.cpp
+++ b/system/OpenglSystemCommon/ProcessPipe.cpp
@@ -208,3 +208,7 @@
     rcEnc->rcSetPuid(rcEnc, sProcUID);
     return true;
 }
+
+uint64_t getPuid() {
+    return sProcUID;
+}
diff --git a/system/OpenglSystemCommon/ProcessPipe.h b/system/OpenglSystemCommon/ProcessPipe.h
index dea2a3f..20f7c9f 100644
--- a/system/OpenglSystemCommon/ProcessPipe.h
+++ b/system/OpenglSystemCommon/ProcessPipe.h
@@ -34,3 +34,4 @@
 struct renderControl_encoder_context_t;
 
 extern bool processPipeInit(HostConnectionType connType, renderControl_encoder_context_t *rcEnc);
+extern uint64_t getPuid();
diff --git a/system/egl/egl.cpp b/system/egl/egl.cpp
index 601ad9d..7d140a9 100644
--- a/system/egl/egl.cpp
+++ b/system/egl/egl.cpp
@@ -14,6 +14,11 @@
 * limitations under the License.
 */
 
+#ifdef GFXSTREAM
+#include <atomic>
+#include <time.h>
+#endif
+
 #include <assert.h>
 #include "HostConnection.h"
 #include "ThreadInfo.h"
@@ -49,6 +54,11 @@
 #include <poll.h>
 #endif // VIRTIO_GPU
 
+#ifdef GFXSTREAM
+#include "android/base/Tracing.h"
+#endif
+#include <cutils/trace.h>
+
 #if PLATFORM_SDK_VERSION < 18
 #define override
 #endif
@@ -611,6 +621,68 @@
                      fd_out);
 }
 
+uint64_t currGuestTimeNs() {
+    struct timespec ts;
+#ifdef __APPLE__
+    clock_gettime(CLOCK_REALTIME, &ts);
+#else
+    clock_gettime(CLOCK_BOOTTIME, &ts);
+#endif
+    uint64_t res = (uint64_t)(ts.tv_sec * 1000000000ULL + ts.tv_nsec);
+    return res;
+}
+
+struct FrameTracingState {
+    uint32_t frameNumber = 0;
+    bool tracingEnabled = false;
+    void onSwapBuffersSuccesful(ExtendedRCEncoderContext* rcEnc) {
+#ifdef GFXSTREAM
+        bool current = android::base::isTracingEnabled();
+        // edge trigger
+        if (android::base::isTracingEnabled() && !tracingEnabled) {
+            if (rcEnc->hasHostSideTracing()) {
+                rcEnc->rcSetTracingForPuid(rcEnc, getPuid(), 1, currGuestTimeNs());
+            }
+        }
+        if (!android::base::isTracingEnabled() && tracingEnabled) {
+            if (rcEnc->hasHostSideTracing()) {
+                rcEnc->rcSetTracingForPuid(rcEnc, getPuid(), 0, currGuestTimeNs());
+            }
+        }
+        tracingEnabled = android::base::isTracingEnabled();
+#endif
+        ++frameNumber;
+    }
+};
+
+static FrameTracingState sFrameTracingState;
+
+static void sFlushBufferAndCreateFence(
+    HostConnection* hostCon, ExtendedRCEncoderContext* rcEnc, uint32_t rcSurface, uint32_t frameNumber, int* presentFenceFd) {
+    atrace_int(ATRACE_TAG_GRAPHICS, "gfxstreamFrameNumber", (int32_t)frameNumber);
+
+    if (rcEnc->hasHostSideTracing()) {
+        rcEnc->rcFlushWindowColorBufferAsyncWithFrameNumber(rcEnc, rcSurface, frameNumber);
+    } else {
+        rcEnc->rcFlushWindowColorBufferAsync(rcEnc, rcSurface);
+    }
+
+    if (rcEnc->hasVirtioGpuNativeSync()) {
+        createNativeSync_virtioGpu(EGL_SYNC_NATIVE_FENCE_ANDROID,
+                     NULL /* empty attrib list */,
+                     0 /* 0 attrib count */,
+                     true /* destroy when signaled. this is host-only
+                             and there will only be one waiter */,
+                     -1 /* we want a new fd */,
+                     presentFenceFd);
+    } else if (rcEnc->hasNativeSync()) {
+        createGoldfishOpenGLNativeSync(presentFenceFd);
+    } else {
+        // equivalent to glFinish if no native sync
+        eglWaitClient();
+    }
+}
+
 EGLBoolean egl_window_surface_t::swapBuffers()
 {
 
@@ -645,23 +717,9 @@
     eglWaitClient();
     nativeWindow->queueBuffer(nativeWindow, buffer);
 #else
-    if (rcEnc->hasVirtioGpuNativeSync()) {
-        rcEnc->rcFlushWindowColorBufferAsync(rcEnc, rcSurface);
-        createNativeSync_virtioGpu(EGL_SYNC_NATIVE_FENCE_ANDROID,
-                     NULL /* empty attrib list */,
-                     0 /* 0 attrib count */,
-                     true /* destroy when signaled. this is host-only
-                             and there will only be one waiter */,
-                     -1 /* we want a new fd */,
-                     &presentFenceFd);
-    } else if (rcEnc->hasNativeSync()) {
-        rcEnc->rcFlushWindowColorBufferAsync(rcEnc, rcSurface);
-        createGoldfishOpenGLNativeSync(&presentFenceFd);
-    } else {
-        rcEnc->rcFlushWindowColorBuffer(rcEnc, rcSurface);
-        // equivalent to glFinish if no native sync
-        eglWaitClient();
-    }
+    sFlushBufferAndCreateFence(
+        hostCon, rcEnc, rcSurface,
+        sFrameTracingState.frameNumber, &presentFenceFd);
 
     DPRINT("queueBuffer with fence %d", presentFenceFd);
     nativeWindow->queueBuffer(nativeWindow, buffer, presentFenceFd);
@@ -694,6 +752,7 @@
     setWidth(buffer->width);
     setHeight(buffer->height);
 
+    sFrameTracingState.onSwapBuffersSuccesful(rcEnc);
     return EGL_TRUE;
 }
 
diff --git a/system/renderControl_enc/renderControl_client_context.cpp b/system/renderControl_enc/renderControl_client_context.cpp
index 5b1f14e..5804699 100644
--- a/system/renderControl_enc/renderControl_client_context.cpp
+++ b/system/renderControl_enc/renderControl_client_context.cpp
@@ -65,6 +65,8 @@
 	rcMapGpaToBufferHandle = (rcMapGpaToBufferHandle_client_proc_t) getProc("rcMapGpaToBufferHandle", userData);
 	rcCreateBuffer2 = (rcCreateBuffer2_client_proc_t) getProc("rcCreateBuffer2", userData);
 	rcMapGpaToBufferHandle2 = (rcMapGpaToBufferHandle2_client_proc_t) getProc("rcMapGpaToBufferHandle2", userData);
+	rcFlushWindowColorBufferAsyncWithFrameNumber = (rcFlushWindowColorBufferAsyncWithFrameNumber_client_proc_t) getProc("rcFlushWindowColorBufferAsyncWithFrameNumber", userData);
+	rcSetTracingForPuid = (rcSetTracingForPuid_client_proc_t) getProc("rcSetTracingForPuid", userData);
 	return 0;
 }
 
diff --git a/system/renderControl_enc/renderControl_client_context.h b/system/renderControl_enc/renderControl_client_context.h
index 2032a32..786a9cd 100644
--- a/system/renderControl_enc/renderControl_client_context.h
+++ b/system/renderControl_enc/renderControl_client_context.h
@@ -65,6 +65,8 @@
 	rcMapGpaToBufferHandle_client_proc_t rcMapGpaToBufferHandle;
 	rcCreateBuffer2_client_proc_t rcCreateBuffer2;
 	rcMapGpaToBufferHandle2_client_proc_t rcMapGpaToBufferHandle2;
+	rcFlushWindowColorBufferAsyncWithFrameNumber_client_proc_t rcFlushWindowColorBufferAsyncWithFrameNumber;
+	rcSetTracingForPuid_client_proc_t rcSetTracingForPuid;
 	virtual ~renderControl_client_context_t() {}
 
 	typedef renderControl_client_context_t *CONTEXT_ACCESSOR_TYPE(void);
diff --git a/system/renderControl_enc/renderControl_client_proc.h b/system/renderControl_enc/renderControl_client_proc.h
index c0b9a7f..92b6b60 100644
--- a/system/renderControl_enc/renderControl_client_proc.h
+++ b/system/renderControl_enc/renderControl_client_proc.h
@@ -67,6 +67,8 @@
 typedef int (renderControl_APIENTRY *rcMapGpaToBufferHandle_client_proc_t) (void * ctx, uint32_t, uint64_t);
 typedef uint32_t (renderControl_APIENTRY *rcCreateBuffer2_client_proc_t) (void * ctx, uint64_t, uint32_t);
 typedef int (renderControl_APIENTRY *rcMapGpaToBufferHandle2_client_proc_t) (void * ctx, uint32_t, uint64_t, uint64_t);
+typedef void (renderControl_APIENTRY *rcFlushWindowColorBufferAsyncWithFrameNumber_client_proc_t) (void * ctx, uint32_t, uint32_t);
+typedef void (renderControl_APIENTRY *rcSetTracingForPuid_client_proc_t) (void * ctx, uint64_t, uint32_t, uint64_t);
 
 
 #endif
diff --git a/system/renderControl_enc/renderControl_enc.cpp b/system/renderControl_enc/renderControl_enc.cpp
index 6b2680c..d3abbd8 100644
--- a/system/renderControl_enc/renderControl_enc.cpp
+++ b/system/renderControl_enc/renderControl_enc.cpp
@@ -2188,6 +2188,61 @@
 	return retval;
 }
 
+void rcFlushWindowColorBufferAsyncWithFrameNumber_enc(void *self , uint32_t windowSurface, uint32_t frameNumber)
+{
+	AEMU_SCOPED_TRACE("rcFlushWindowColorBufferAsyncWithFrameNumber encode");
+
+	renderControl_encoder_context_t *ctx = (renderControl_encoder_context_t *)self;
+	IOStream *stream = ctx->m_stream;
+	ChecksumCalculator *checksumCalculator = ctx->m_checksumCalculator;
+	bool useChecksum = checksumCalculator->getVersion() > 0;
+
+	 unsigned char *ptr;
+	 unsigned char *buf;
+	 const size_t sizeWithoutChecksum = 8 + 4 + 4;
+	 const size_t checksumSize = checksumCalculator->checksumByteSize();
+	 const size_t totalSize = sizeWithoutChecksum + checksumSize;
+	buf = stream->alloc(totalSize);
+	ptr = buf;
+	int tmp = OP_rcFlushWindowColorBufferAsyncWithFrameNumber;memcpy(ptr, &tmp, 4); ptr += 4;
+	memcpy(ptr, &totalSize, 4);  ptr += 4;
+
+		memcpy(ptr, &windowSurface, 4); ptr += 4;
+		memcpy(ptr, &frameNumber, 4); ptr += 4;
+
+	if (useChecksum) checksumCalculator->addBuffer(buf, ptr-buf);
+	if (useChecksum) checksumCalculator->writeChecksum(ptr, checksumSize); ptr += checksumSize;
+
+}
+
+void rcSetTracingForPuid_enc(void *self , uint64_t puid, uint32_t enable, uint64_t guestTime)
+{
+	AEMU_SCOPED_TRACE("rcSetTracingForPuid encode");
+
+	renderControl_encoder_context_t *ctx = (renderControl_encoder_context_t *)self;
+	IOStream *stream = ctx->m_stream;
+	ChecksumCalculator *checksumCalculator = ctx->m_checksumCalculator;
+	bool useChecksum = checksumCalculator->getVersion() > 0;
+
+	 unsigned char *ptr;
+	 unsigned char *buf;
+	 const size_t sizeWithoutChecksum = 8 + 8 + 4 + 8;
+	 const size_t checksumSize = checksumCalculator->checksumByteSize();
+	 const size_t totalSize = sizeWithoutChecksum + checksumSize;
+	buf = stream->alloc(totalSize);
+	ptr = buf;
+	int tmp = OP_rcSetTracingForPuid;memcpy(ptr, &tmp, 4); ptr += 4;
+	memcpy(ptr, &totalSize, 4);  ptr += 4;
+
+		memcpy(ptr, &puid, 8); ptr += 8;
+		memcpy(ptr, &enable, 4); ptr += 4;
+		memcpy(ptr, &guestTime, 8); ptr += 8;
+
+	if (useChecksum) checksumCalculator->addBuffer(buf, ptr-buf);
+	if (useChecksum) checksumCalculator->writeChecksum(ptr, checksumSize); ptr += checksumSize;
+
+}
+
 }  // namespace
 
 renderControl_encoder_context_t::renderControl_encoder_context_t(IOStream *stream, ChecksumCalculator *checksumCalculator)
@@ -2250,5 +2305,7 @@
 	this->rcMapGpaToBufferHandle = &rcMapGpaToBufferHandle_enc;
 	this->rcCreateBuffer2 = &rcCreateBuffer2_enc;
 	this->rcMapGpaToBufferHandle2 = &rcMapGpaToBufferHandle2_enc;
+	this->rcFlushWindowColorBufferAsyncWithFrameNumber = &rcFlushWindowColorBufferAsyncWithFrameNumber_enc;
+	this->rcSetTracingForPuid = &rcSetTracingForPuid_enc;
 }
 
diff --git a/system/renderControl_enc/renderControl_entry.cpp b/system/renderControl_enc/renderControl_entry.cpp
index 0ea37d6..5f695ab 100644
--- a/system/renderControl_enc/renderControl_entry.cpp
+++ b/system/renderControl_enc/renderControl_entry.cpp
@@ -60,6 +60,8 @@
 	int rcMapGpaToBufferHandle(uint32_t bufferHandle, uint64_t gpa);
 	uint32_t rcCreateBuffer2(uint64_t size, uint32_t memoryProperty);
 	int rcMapGpaToBufferHandle2(uint32_t bufferHandle, uint64_t gpa, uint64_t size);
+	void rcFlushWindowColorBufferAsyncWithFrameNumber(uint32_t windowSurface, uint32_t frameNumber);
+	void rcSetTracingForPuid(uint64_t puid, uint32_t enable, uint64_t guestTime);
 };
 
 #ifndef GET_CONTEXT
@@ -398,3 +400,15 @@
 	return ctx->rcMapGpaToBufferHandle2(ctx, bufferHandle, gpa, size);
 }
 
+void rcFlushWindowColorBufferAsyncWithFrameNumber(uint32_t windowSurface, uint32_t frameNumber)
+{
+	GET_CONTEXT;
+	ctx->rcFlushWindowColorBufferAsyncWithFrameNumber(ctx, windowSurface, frameNumber);
+}
+
+void rcSetTracingForPuid(uint64_t puid, uint32_t enable, uint64_t guestTime)
+{
+	GET_CONTEXT;
+	ctx->rcSetTracingForPuid(ctx, puid, enable, guestTime);
+}
+
diff --git a/system/renderControl_enc/renderControl_ftable.h b/system/renderControl_enc/renderControl_ftable.h
index 247a0bd..38dbc85 100644
--- a/system/renderControl_enc/renderControl_ftable.h
+++ b/system/renderControl_enc/renderControl_ftable.h
@@ -63,6 +63,8 @@
 	{"rcMapGpaToBufferHandle", (void*)rcMapGpaToBufferHandle},
 	{"rcCreateBuffer2", (void*)rcCreateBuffer2},
 	{"rcMapGpaToBufferHandle2", (void*)rcMapGpaToBufferHandle2},
+	{"rcFlushWindowColorBufferAsyncWithFrameNumber", (void*)rcFlushWindowColorBufferAsyncWithFrameNumber},
+	{"rcSetTracingForPuid", (void*)rcSetTracingForPuid},
 };
 static const int renderControl_num_funcs = sizeof(renderControl_funcs_by_name) / sizeof(struct _renderControl_funcs_by_name);
 
diff --git a/system/renderControl_enc/renderControl_opcodes.h b/system/renderControl_enc/renderControl_opcodes.h
index 16c0214..5b8844e 100644
--- a/system/renderControl_enc/renderControl_opcodes.h
+++ b/system/renderControl_enc/renderControl_opcodes.h
@@ -58,7 +58,9 @@
 #define OP_rcMapGpaToBufferHandle 					10052
 #define OP_rcCreateBuffer2 					10053
 #define OP_rcMapGpaToBufferHandle2 					10054
-#define OP_last 					10055
+#define OP_rcFlushWindowColorBufferAsyncWithFrameNumber 					10055
+#define OP_rcSetTracingForPuid 					10056
+#define OP_last 					10057
 
 
 #endif