Add message for logging GPU message

Test: gpu_log.sql

Change-Id: I13a2f4481497d4b4a2c6b86188b0e95ca51476be
diff --git a/Android.bp b/Android.bp
index 83e180e..d11a528 100644
--- a/Android.bp
+++ b/Android.bp
@@ -2542,6 +2542,7 @@
   name: "perfetto_protos_perfetto_trace_gpu_lite_gen",
   srcs: [
     "protos/perfetto/trace/gpu/gpu_counter_event.proto",
+    "protos/perfetto/trace/gpu/gpu_log.proto",
     "protos/perfetto/trace/gpu/gpu_render_stage_event.proto",
     "protos/perfetto/trace/gpu/vulkan_memory_event.proto",
   ],
@@ -2551,6 +2552,7 @@
   cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/ --proto_path=external/perfetto $(in)",
   out: [
     "external/perfetto/protos/perfetto/trace/gpu/gpu_counter_event.pb.cc",
+    "external/perfetto/protos/perfetto/trace/gpu/gpu_log.pb.cc",
     "external/perfetto/protos/perfetto/trace/gpu/gpu_render_stage_event.pb.cc",
     "external/perfetto/protos/perfetto/trace/gpu/vulkan_memory_event.pb.cc",
   ],
@@ -2561,6 +2563,7 @@
   name: "perfetto_protos_perfetto_trace_gpu_lite_gen_headers",
   srcs: [
     "protos/perfetto/trace/gpu/gpu_counter_event.proto",
+    "protos/perfetto/trace/gpu/gpu_log.proto",
     "protos/perfetto/trace/gpu/gpu_render_stage_event.proto",
     "protos/perfetto/trace/gpu/vulkan_memory_event.proto",
   ],
@@ -2570,6 +2573,7 @@
   cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/ --proto_path=external/perfetto $(in)",
   out: [
     "external/perfetto/protos/perfetto/trace/gpu/gpu_counter_event.pb.h",
+    "external/perfetto/protos/perfetto/trace/gpu/gpu_log.pb.h",
     "external/perfetto/protos/perfetto/trace/gpu/gpu_render_stage_event.pb.h",
     "external/perfetto/protos/perfetto/trace/gpu/vulkan_memory_event.pb.h",
   ],
@@ -2584,6 +2588,7 @@
   name: "perfetto_protos_perfetto_trace_gpu_zero_gen",
   srcs: [
     "protos/perfetto/trace/gpu/gpu_counter_event.proto",
+    "protos/perfetto/trace/gpu/gpu_log.proto",
     "protos/perfetto/trace/gpu/gpu_render_stage_event.proto",
     "protos/perfetto/trace/gpu/vulkan_memory_event.proto",
   ],
@@ -2594,6 +2599,7 @@
   cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/ --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location protozero_plugin) --plugin_out=wrapper_namespace=pbzero:$(genDir)/external/perfetto/ $(in)",
   out: [
     "external/perfetto/protos/perfetto/trace/gpu/gpu_counter_event.pbzero.cc",
+    "external/perfetto/protos/perfetto/trace/gpu/gpu_log.pbzero.cc",
     "external/perfetto/protos/perfetto/trace/gpu/gpu_render_stage_event.pbzero.cc",
     "external/perfetto/protos/perfetto/trace/gpu/vulkan_memory_event.pbzero.cc",
   ],
@@ -2604,6 +2610,7 @@
   name: "perfetto_protos_perfetto_trace_gpu_zero_gen_headers",
   srcs: [
     "protos/perfetto/trace/gpu/gpu_counter_event.proto",
+    "protos/perfetto/trace/gpu/gpu_log.proto",
     "protos/perfetto/trace/gpu/gpu_render_stage_event.proto",
     "protos/perfetto/trace/gpu/vulkan_memory_event.proto",
   ],
@@ -2614,6 +2621,7 @@
   cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/ --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location protozero_plugin) --plugin_out=wrapper_namespace=pbzero:$(genDir)/external/perfetto/ $(in)",
   out: [
     "external/perfetto/protos/perfetto/trace/gpu/gpu_counter_event.pbzero.h",
+    "external/perfetto/protos/perfetto/trace/gpu/gpu_log.pbzero.h",
     "external/perfetto/protos/perfetto/trace/gpu/gpu_render_stage_event.pbzero.h",
     "external/perfetto/protos/perfetto/trace/gpu/vulkan_memory_event.pbzero.h",
   ],
diff --git a/BUILD b/BUILD
index a0229d6..825f6a3 100644
--- a/BUILD
+++ b/BUILD
@@ -1590,6 +1590,7 @@
     name = "protos_perfetto_trace_gpu_protos",
     srcs = [
         "protos/perfetto/trace/gpu/gpu_counter_event.proto",
+        "protos/perfetto/trace/gpu/gpu_log.proto",
         "protos/perfetto/trace/gpu/gpu_render_stage_event.proto",
         "protos/perfetto/trace/gpu/vulkan_memory_event.proto",
     ],
diff --git a/protos/perfetto/trace/gpu/BUILD.gn b/protos/perfetto/trace/gpu/BUILD.gn
index c271bc7..64b913a 100644
--- a/protos/perfetto/trace/gpu/BUILD.gn
+++ b/protos/perfetto/trace/gpu/BUILD.gn
@@ -20,6 +20,7 @@
   ]
   sources = [
     "gpu_counter_event.proto",
+    "gpu_log.proto",
     "gpu_render_stage_event.proto",
     "vulkan_memory_event.proto",
   ]
diff --git a/protos/perfetto/trace/gpu/gpu_log.proto b/protos/perfetto/trace/gpu/gpu_log.proto
new file mode 100644
index 0000000..0c37847
--- /dev/null
+++ b/protos/perfetto/trace/gpu/gpu_log.proto
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+syntax = "proto2";
+option optimize_for = LITE_RUNTIME;
+
+package perfetto.protos;
+
+// Message for logging events GPU data producer.
+message GpuLog {
+  enum Severity {
+    VERBOSE = 0;
+    DEBUG = 1;
+    INFO = 2;
+    WARNING = 3;
+    ERROR = 4;
+  };
+  optional Severity severity = 1;
+
+  optional string tag = 2;
+
+  optional string log_message = 3;
+}
diff --git a/protos/perfetto/trace/perfetto_trace.proto b/protos/perfetto/trace/perfetto_trace.proto
index 11d801c..8d0e03d 100644
--- a/protos/perfetto/trace/perfetto_trace.proto
+++ b/protos/perfetto/trace/perfetto_trace.proto
@@ -3482,7 +3482,7 @@
 // TracePacket(s).
 //
 // Next reserved id: 13 (up to 15).
-// Next id: 63.
+// Next id: 64.
 message TracePacket {
   // The timestamp of the TracePacket.
   // By default this timestamps refers to the trace clock (CLOCK_BOOTTIME on
@@ -3531,6 +3531,7 @@
     HeapGraph heap_graph = 56;
     GraphicsFrameEvent graphics_frame_event = 57;
     // removed field with id 62
+    GpuLog gpu_log = 63;
 
     // Only used in profile packets.
     ProfiledFrameSymbols profiled_frame_symbols = 55;
@@ -4143,6 +4144,26 @@
 
 // End of protos/perfetto/trace/gpu/gpu_counter_event.proto
 
+// Begin of protos/perfetto/trace/gpu/gpu_log.proto
+
+// Message for logging events GPU data producer.
+message GpuLog {
+  enum Severity {
+    VERBOSE = 0;
+    DEBUG = 1;
+    INFO = 2;
+    WARNING = 3;
+    ERROR = 4;
+  };
+  optional Severity severity = 1;
+
+  optional string tag = 2;
+
+  optional string log_message = 3;
+}
+
+// End of protos/perfetto/trace/gpu/gpu_log.proto
+
 // Begin of protos/perfetto/trace/gpu/gpu_render_stage_event.proto
 
 // next id: 12
diff --git a/protos/perfetto/trace/trace_packet.proto b/protos/perfetto/trace/trace_packet.proto
index 48d86f6..b23c98b 100644
--- a/protos/perfetto/trace/trace_packet.proto
+++ b/protos/perfetto/trace/trace_packet.proto
@@ -30,6 +30,7 @@
 import "protos/perfetto/trace/ftrace/ftrace_event_bundle.proto";
 import "protos/perfetto/trace/ftrace/ftrace_stats.proto";
 import "protos/perfetto/trace/gpu/gpu_counter_event.proto";
+import "protos/perfetto/trace/gpu/gpu_log.proto";
 import "protos/perfetto/trace/gpu/gpu_render_stage_event.proto";
 import "protos/perfetto/trace/gpu/vulkan_memory_event.proto";
 import "protos/perfetto/trace/interned_data/interned_data.proto";
@@ -57,7 +58,7 @@
 // TracePacket(s).
 //
 // Next reserved id: 13 (up to 15).
-// Next id: 63.
+// Next id: 64.
 message TracePacket {
   // The timestamp of the TracePacket.
   // By default this timestamps refers to the trace clock (CLOCK_BOOTTIME on
@@ -106,6 +107,7 @@
     HeapGraph heap_graph = 56;
     GraphicsFrameEvent graphics_frame_event = 57;
     VulkanMemoryEvent vulkan_memory_event = 62;
+    GpuLog gpu_log = 63;
 
     // Only used in profile packets.
     ProfiledFrameSymbols profiled_frame_symbols = 55;
diff --git a/src/trace_processor/graphics_event_parser.cc b/src/trace_processor/graphics_event_parser.cc
index 86b67be..a8caea5 100644
--- a/src/trace_processor/graphics_event_parser.cc
+++ b/src/trace_processor/graphics_event_parser.cc
@@ -28,6 +28,7 @@
 #include "protos/perfetto/common/gpu_counter_descriptor.pbzero.h"
 #include "protos/perfetto/trace/android/graphics_frame_event.pbzero.h"
 #include "protos/perfetto/trace/gpu/gpu_counter_event.pbzero.h"
+#include "protos/perfetto/trace/gpu/gpu_log.pbzero.h"
 #include "protos/perfetto/trace/gpu/gpu_render_stage_event.pbzero.h"
 #include "protos/perfetto/trace/gpu/vulkan_memory_event.pbzero.h"
 
@@ -80,7 +81,17 @@
       vulkan_live_image_objects_(0),
       vulkan_live_buffer_objects_(0),
       vulkan_bound_image_objects_(0),
-      vulkan_bound_buffer_objects_(0) {}
+      vulkan_bound_buffer_objects_(0),
+      gpu_log_track_name_id_(context_->storage->InternString("GPU Log")),
+      gpu_log_scope_id_(context_->storage->InternString("gpu_log")),
+      tag_id_(context_->storage->InternString("tag")),
+      log_message_id_(context->storage->InternString("message")),
+      log_severity_ids_{{context_->storage->InternString("VERBOSE"),
+                         context_->storage->InternString("DEBUG"),
+                         context_->storage->InternString("INFO"),
+                         context_->storage->InternString("WARNING"),
+                         context_->storage->InternString("ERROR"),
+                         context_->storage->InternString("UNKNOWN_SEVERITY") /* must be last */}} {}
 
 void GraphicsEventParser::ParseGpuCounterEvent(int64_t ts, ConstBytes blob) {
   protos::pbzero::GpuCounterEvent::Decoder event(blob.data, blob.size);
@@ -468,5 +479,39 @@
   }
 }
 
+void GraphicsEventParser::ParseGpuLog(int64_t ts, ConstBytes blob) {
+  protos::pbzero::GpuLog::Decoder event(blob.data, blob.size);
+
+  tables::GpuTrackTable::Row track(gpu_log_track_name_id_.id);
+  track.scope = gpu_log_scope_id_;
+  TrackId track_id = context_->track_tracker->InternGpuTrack(track);
+
+  auto args_callback = [this, &event](ArgsTracker* args_tracker, RowId row_id) {
+    if (event.has_tag()) {
+      args_tracker->AddArg(
+          row_id, tag_id_, tag_id_,
+          Variadic::String(context_->storage->InternString(event.tag())));
+    }
+    if (event.has_log_message()) {
+      args_tracker->AddArg(row_id, log_message_id_, log_message_id_,
+                           Variadic::String(context_->storage->InternString(
+                               event.log_message())));
+    }
+  };
+
+  auto severity = static_cast<size_t>(event.severity());
+  StringId severity_id =
+      severity < log_severity_ids_.size()
+          ? log_severity_ids_[static_cast<size_t>(event.severity())]
+          : log_severity_ids_[log_severity_ids_.size() - 1];
+  const auto slice_id = context_->slice_tracker->Scoped(ts, track_id, track_id, RefType::kRefTrack,
+                                  0 /* cat */, severity_id, 0 /* duration */,
+                                  args_callback);
+
+  tables::GpuSliceTable::Row row;
+  row.slice_id = slice_id.value();
+  context_->storage->mutable_gpu_slice_table()->Insert(row);
+}
+
 }  // namespace trace_processor
 }  // namespace perfetto
diff --git a/src/trace_processor/graphics_event_parser.h b/src/trace_processor/graphics_event_parser.h
index 4ca7b87..fa3f83a 100644
--- a/src/trace_processor/graphics_event_parser.h
+++ b/src/trace_processor/graphics_event_parser.h
@@ -37,6 +37,7 @@
   void ParseGpuCounterEvent(int64_t ts, ConstBytes);
   void ParseGpuRenderStageEvent(int64_t ts, ConstBytes);
   void ParseGraphicsFrameEvent(int64_t timestamp, ConstBytes);
+  void ParseGpuLog(int64_t ts, ConstBytes);
 
   void ParseVulkanMemoryEvent(ConstBytes);
   void UpdateVulkanMemoryAllocationCounters(
@@ -70,6 +71,12 @@
   int64_t vulkan_live_buffer_objects_;
   int64_t vulkan_bound_image_objects_;
   int64_t vulkan_bound_buffer_objects_;
+  // For GpuLog
+  const StringId gpu_log_track_name_id_;
+  const StringId gpu_log_scope_id_;
+  const StringId tag_id_;
+  const StringId log_message_id_;
+  std::array<StringId, 6> log_severity_ids_;
 };
 }  // namespace trace_processor
 }  // namespace perfetto
diff --git a/src/trace_processor/proto_trace_parser.cc b/src/trace_processor/proto_trace_parser.cc
index c564ef1..5fbb119 100644
--- a/src/trace_processor/proto_trace_parser.cc
+++ b/src/trace_processor/proto_trace_parser.cc
@@ -484,6 +484,10 @@
     ParseTraceConfig(packet.trace_config());
   }
 
+  if (packet.has_gpu_log()) {
+    graphics_event_parser_->ParseGpuLog(ts, packet.gpu_log());
+  }
+
   if (packet.has_packages_list()) {
     ParseAndroidPackagesList(packet.packages_list());
   }
diff --git a/test/synth_common.py b/test/synth_common.py
index 57605f7..656faab 100644
--- a/test/synth_common.py
+++ b/test/synth_common.py
@@ -273,6 +273,14 @@
     gpu_counter.counter_id = counter_id
     gpu_counter.int_value = value
 
+  def add_gpu_log(self, ts, severity, tag, message):
+    packet = self.add_packet()
+    packet.timestamp = ts
+    gpu_log = self.packet.gpu_log
+    gpu_log.severity = severity
+    gpu_log.tag = tag
+    gpu_log.log_message = message
+
   def add_buffer_event_packet(self, ts, buffer_id, layer_name, frame_number,
                               event_type, duration):
     packet = self.add_packet()
diff --git a/test/trace_processor/gpu_log.out b/test/trace_processor/gpu_log.out
new file mode 100644
index 0000000..61b1c09
--- /dev/null
+++ b/test/trace_processor/gpu_log.out
@@ -0,0 +1,13 @@
+"scope","track_name","ts","dur","slice_name","key","value"
+"gpu_log","GPU Log",1,0,"VERBOSE","message","message0"
+"gpu_log","GPU Log",1,0,"VERBOSE","tag","tag0"
+"gpu_log","GPU Log",2,0,"DEBUG","message","message1"
+"gpu_log","GPU Log",2,0,"DEBUG","tag","tag0"
+"gpu_log","GPU Log",3,0,"INFO","message","message2"
+"gpu_log","GPU Log",3,0,"INFO","tag","tag0"
+"gpu_log","GPU Log",4,0,"ERROR","message","message4"
+"gpu_log","GPU Log",4,0,"ERROR","tag","tag0"
+"gpu_log","GPU Log",4,0,"WARNING","message","message3"
+"gpu_log","GPU Log",4,0,"WARNING","tag","tag0"
+"gpu_log","GPU Log",5,0,"VERBOSE","message","message5"
+"gpu_log","GPU Log",5,0,"VERBOSE","tag","tag1"
diff --git a/test/trace_processor/gpu_log.py b/test/trace_processor/gpu_log.py
new file mode 100644
index 0000000..7720836
--- /dev/null
+++ b/test/trace_processor/gpu_log.py
@@ -0,0 +1,28 @@
+#!/usr/bin/python
+# Copyright (C) 2019 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+from os import sys, path
+sys.path.append(path.dirname(path.dirname(path.abspath(__file__))))
+import synth_common
+
+trace = synth_common.create_trace()
+trace.add_gpu_log(ts=1, severity=0, tag="tag0", message="message0")
+trace.add_gpu_log(ts=2, severity=1, tag="tag0", message="message1")
+trace.add_gpu_log(ts=3, severity=2, tag="tag0", message="message2")
+trace.add_gpu_log(ts=4, severity=3, tag="tag0", message="message3")
+trace.add_gpu_log(ts=4, severity=4, tag="tag0", message="message4")
+trace.add_gpu_log(ts=5, severity=0, tag="tag1", message="message5")
+
+print(trace.trace.SerializeToString())
diff --git a/test/trace_processor/gpu_log.sql b/test/trace_processor/gpu_log.sql
new file mode 100644
index 0000000..dd846e3
--- /dev/null
+++ b/test/trace_processor/gpu_log.sql
@@ -0,0 +1,7 @@
+select scope, track.name as track_name, ts, dur, gpu_slice.name as slice_name,
+    key, string_value as value
+from gpu_track
+left join track using (id)
+left join gpu_slice on gpu_track.id=gpu_slice.track_id
+left join args using (arg_set_id)
+order by ts, slice_name, key
diff --git a/test/trace_processor/index b/test/trace_processor/index
index 7bb14f4..3380c4f 100644
--- a/test/trace_processor/index
+++ b/test/trace_processor/index
@@ -117,6 +117,7 @@
 # GPU trace tests.
 gpu_counters.py gpu_counters.sql gpu_counters.out
 ../data/gpu_trace.pb gpu_render_stages.sql gpu_render_stages.out
+gpu_log.py gpu_log.sql gpu_log.out
 
 # Clock sync
 clock_sync.py clock_sync.sql clock_sync.out
diff --git a/tools/gen_merged_protos b/tools/gen_merged_protos
index 6001fc2..0603ae3 100755
--- a/tools/gen_merged_protos
+++ b/tools/gen_merged_protos
@@ -103,6 +103,7 @@
   'protos/perfetto/trace/track_event/track_event.proto',
   'protos/perfetto/trace/trigger.proto',
   'protos/perfetto/trace/gpu/gpu_counter_event.proto',
+  'protos/perfetto/trace/gpu/gpu_log.proto',
   'protos/perfetto/trace/gpu/gpu_render_stage_event.proto',
 )