Merge "Add frame_times metric to experimental/"
diff --git a/Android.bp b/Android.bp
index 6654141..6bca042 100644
--- a/Android.bp
+++ b/Android.bp
@@ -3579,6 +3579,7 @@
     "protos/perfetto/metrics/android/thread_time_in_state_metric.proto",
     "protos/perfetto/metrics/android/unsymbolized_frames.proto",
     "protos/perfetto/metrics/chrome/all_chrome_metrics.proto",
+    "protos/perfetto/metrics/chrome/frame_times.proto",
     "protos/perfetto/metrics/chrome/test_chrome_metric.proto",
     "protos/perfetto/metrics/custom_options.proto",
     "protos/perfetto/metrics/metrics.proto",
@@ -7592,6 +7593,7 @@
     "src/trace_processor/metrics/chrome/scroll_jank_cause_get_bitmap.sql",
     "src/trace_processor/metrics/chrome/scroll_jank_cause_queuing_delay.sql",
     "src/trace_processor/metrics/chrome/test_chrome_metric.sql",
+    "src/trace_processor/metrics/experimental/frame_times.sql",
     "src/trace_processor/metrics/trace_metadata.sql",
     "src/trace_processor/metrics/webview/webview_power_usage.sql",
   ],
diff --git a/BUILD b/BUILD
index 6b1204d..4ad0b3a 100644
--- a/BUILD
+++ b/BUILD
@@ -942,6 +942,7 @@
         "src/trace_processor/metrics/chrome/scroll_jank_cause_get_bitmap.sql",
         "src/trace_processor/metrics/chrome/scroll_jank_cause_queuing_delay.sql",
         "src/trace_processor/metrics/chrome/test_chrome_metric.sql",
+        "src/trace_processor/metrics/experimental/frame_times.sql",
         "src/trace_processor/metrics/trace_metadata.sql",
         "src/trace_processor/metrics/webview/webview_power_usage.sql",
     ],
@@ -2328,6 +2329,7 @@
     name = "protos_perfetto_metrics_chrome_protos",
     srcs = [
         "protos/perfetto/metrics/chrome/all_chrome_metrics.proto",
+        "protos/perfetto/metrics/chrome/frame_times.proto",
         "protos/perfetto/metrics/chrome/test_chrome_metric.proto",
     ],
     visibility = [
diff --git a/protos/perfetto/metrics/chrome/BUILD.gn b/protos/perfetto/metrics/chrome/BUILD.gn
index 6287d8c..a30c131 100644
--- a/protos/perfetto/metrics/chrome/BUILD.gn
+++ b/protos/perfetto/metrics/chrome/BUILD.gn
@@ -22,6 +22,7 @@
   ]
   sources = [
     "all_chrome_metrics.proto",
+    "frame_times.proto",
     "test_chrome_metric.proto",
   ]
 }
diff --git a/protos/perfetto/metrics/chrome/all_chrome_metrics.proto b/protos/perfetto/metrics/chrome/all_chrome_metrics.proto
index 6863170..442cba3 100644
--- a/protos/perfetto/metrics/chrome/all_chrome_metrics.proto
+++ b/protos/perfetto/metrics/chrome/all_chrome_metrics.proto
@@ -19,8 +19,10 @@
 package perfetto.protos;
 
 import "protos/perfetto/metrics/metrics.proto";
+import "protos/perfetto/metrics/chrome/frame_times.proto";
 import "protos/perfetto/metrics/chrome/test_chrome_metric.proto";
 
 extend TraceMetrics {
   optional TestChromeMetric test_chrome_metric = 1001;
+  optional FrameTimes frame_times = 1002;
 }
diff --git a/protos/perfetto/metrics/chrome/frame_times.proto b/protos/perfetto/metrics/chrome/frame_times.proto
new file mode 100644
index 0000000..5206a1c
--- /dev/null
+++ b/protos/perfetto/metrics/chrome/frame_times.proto
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2021 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";
+
+package perfetto.protos;
+
+import "protos/perfetto/metrics/custom_options.proto";
+
+message FrameTimes {
+  repeated double frame_time = 1 [(unit) = "ms_smallerIsBetter"];
+  repeated double exp_frame_time = 2 [(unit) = "ms_smallerIsBetter"];
+  optional double avg_surface_fps = 3 [(unit) = "unitless_biggerIsBetter"];
+  optional double exp_avg_surface_fps = 4 [(unit) = "unitless_biggerIsBetter"];
+}
diff --git a/src/trace_processor/metrics/BUILD.gn b/src/trace_processor/metrics/BUILD.gn
index 7b3f630..500d1a8 100644
--- a/src/trace_processor/metrics/BUILD.gn
+++ b/src/trace_processor/metrics/BUILD.gn
@@ -79,6 +79,7 @@
   "chrome/scroll_flow_event.sql",
   "chrome/scroll_flow_event_queuing_delay.sql",
   "chrome/test_chrome_metric.sql",
+  "experimental/frame_times.sql",
   "webview/webview_power_usage.sql",
 ]
 
diff --git a/src/trace_processor/metrics/experimental/frame_times.sql b/src/trace_processor/metrics/experimental/frame_times.sql
new file mode 100644
index 0000000..b43ad74
--- /dev/null
+++ b/src/trace_processor/metrics/experimental/frame_times.sql
@@ -0,0 +1,168 @@
+--
+-- Copyright 2021 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
+--
+--     https://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.
+
+CREATE VIEW InteractionEvents AS
+SELECT
+  ts, dur, ts AS ts_ir, dur AS dur_ir
+FROM slice WHERE name LIKE 'Interaction.%';
+
+CREATE VIEW GestureLegacyEvents AS
+SELECT
+  ts,
+  EXTRACT_ARG(arg_set_id, 'legacy_event.phase') AS phase
+FROM raw
+WHERE EXTRACT_ARG(arg_set_id, 'legacy_event.name') = 'SyntheticGestureController::running';
+
+-- Convert pairs of 'S' and 'F' events into slices with ts and dur.
+CREATE VIEW GestureEvents AS
+SELECT
+  ts, dur, ts AS ts_ge, dur AS dur_ge
+FROM (
+  SELECT
+    ts,
+    phase,
+    LEAD(ts) OVER (ORDER BY ts) - ts as dur
+  FROM GestureLegacyEvents
+)
+WHERE phase = 'S';
+
+CREATE VIRTUAL TABLE InteractionEventsJoinGestureEvents
+USING SPAN_LEFT_JOIN(InteractionEvents, GestureEvents);
+
+--------------------------------------------------------------------------------
+-- Interesting segments are:
+-- 1) If there's a gesture overlapping with interaction, then gesture's range.
+-- 2) Else, interaction's range.
+
+CREATE VIEW InterestingSegments AS
+SELECT  -- 1) Gestures overlapping interactions.
+  ts_ge AS ts,
+  dur_ge AS dur
+FROM InteractionEventsJoinGestureEvents
+WHERE ts_ge IS NOT NULL
+GROUP BY ts_ge
+UNION ALL
+SELECT  -- 2) Interactions without gestures.
+  ts_ir AS ts,
+  dur_ir AS dur
+FROM InteractionEventsJoinGestureEvents
+WHERE ts_ge IS NULL
+GROUP BY ts_ir
+HAVING COUNT(*) = 1;
+
+--------------------------------------------------------------------------------
+-- On ChromeOS, DRM events, if they exist, are the source of truth. Otherwise,
+-- look for display rendering stats.
+-- On Android, the TBMv2 version relied on Surface Flinger events that are
+-- currently unavailable in proto traces. So results may be different from
+-- the TBMv2 version on this platform.
+
+CREATE TABLE DisplayCompositorPresentationEvents AS
+SELECT ts, FALSE AS exp
+FROM slice
+WHERE name = 'DrmEventFlipComplete'
+GROUP BY ts;
+
+INSERT INTO DisplayCompositorPresentationEvents
+SELECT ts, FALSE AS exp
+FROM slice
+WHERE
+  name = 'vsync_before'
+  AND NOT EXISTS (SELECT * FROM DisplayCompositorPresentationEvents)
+GROUP BY ts;
+
+INSERT INTO DisplayCompositorPresentationEvents
+SELECT ts, FALSE AS exp
+FROM slice
+WHERE
+  name = 'BenchmarkInstrumentation::DisplayRenderingStats'
+  AND NOT EXISTS (SELECT * FROM DisplayCompositorPresentationEvents)
+GROUP BY ts;
+
+INSERT INTO DisplayCompositorPresentationEvents
+SELECT ts, TRUE AS exp
+FROM slice
+WHERE name = 'Display::FrameDisplayed'
+GROUP BY ts;
+
+CREATE VIEW FrameSegments AS
+SELECT
+  ts,
+  LEAD(ts) OVER wnd - ts as dur,
+  ts as ts_fs,
+  LEAD(ts) OVER wnd - ts as dur_fs,
+  exp
+FROM DisplayCompositorPresentationEvents
+WINDOW wnd AS (PARTITION BY exp ORDER BY ts);
+
+CREATE VIRTUAL TABLE FrameSegmentsJoinInterestingSegments USING
+SPAN_JOIN(FrameSegments, InterestingSegments);
+
+CREATE VIEW FrameTimes AS
+SELECT dur / 1e6 AS dur_ms, exp
+FROM FrameSegmentsJoinInterestingSegments
+WHERE ts = ts_fs AND dur = dur_fs;
+
+--------------------------------------------------------------------------------
+-- Determine frame rate
+
+CREATE VIEW RefreshPeriodAndroid AS
+-- Not implemented yet.
+SELECT NULL AS interval_ms
+;
+
+CREATE VIEW RefreshPeriodNonAndroid AS
+SELECT EXTRACT_ARG(arg_set_id, 'debug.args.interval_us') / 1e3 AS interval_ms
+FROM slice
+JOIN thread_track ON (slice.track_id = thread_track.id)
+JOIN thread ON (thread_track.utid = thread.utid)
+WHERE thread.name = 'Compositor' AND slice.name = 'Scheduler::BeginFrame'
+LIMIT 1;
+
+CREATE VIEW RefreshPeriodDefault AS
+SELECT 1000.0 / 60 AS interval_ms;
+
+CREATE TABLE RefreshPeriod AS
+SELECT COALESCE(
+  (SELECT interval_ms FROM RefreshPeriodAndroid),
+  (SELECT interval_ms FROM RefreshPeriodNonAndroid),
+  (SELECT interval_ms FROM RefreshPeriodDefault)
+) AS interval_ms;
+
+--------------------------------------------------------------------------------
+-- Compute average FPS
+
+CREATE VIEW ValidFrameTimes AS
+SELECT
+  dur_ms / (SELECT interval_ms FROM RefreshPeriod) AS length,
+  exp
+FROM FrameTimes
+WHERE dur_ms / (SELECT interval_ms FROM RefreshPeriod) >= 0.5;
+
+CREATE VIEW AvgSurfaceFps AS
+SELECT
+  exp,
+  1e3 * COUNT(*) / (SELECT SUM(dur_ms) FROM FrameTimes WHERE exp = valid.exp) AS fps
+FROM ValidFrameTimes valid
+GROUP BY exp;
+
+CREATE VIEW frame_times_output AS
+SELECT FrameTimes(
+  'frame_time', (SELECT RepeatedField(dur_ms) FROM FrameTimes WHERE NOT exp),
+  'exp_frame_time', (SELECT RepeatedField(dur_ms) FROM FrameTimes WHERE exp),
+  'avg_surface_fps', (SELECT fps FROM AvgSurfaceFps WHERE NOT exp),
+  'exp_avg_surface_fps', (SELECT fps FROM AvgSurfaceFps WHERE exp)
+);
+
diff --git a/test/trace_processor/chrome/frame_times_metric.out b/test/trace_processor/chrome/frame_times_metric.out
new file mode 100644
index 0000000..447a2e4
--- /dev/null
+++ b/test/trace_processor/chrome/frame_times_metric.out
@@ -0,0 +1,4 @@
+
+"exp","fps"
+0,59.860088
+1,59.861592
diff --git a/test/trace_processor/chrome/frame_times_metric.sql b/test/trace_processor/chrome/frame_times_metric.sql
new file mode 100644
index 0000000..28c0c42
--- /dev/null
+++ b/test/trace_processor/chrome/frame_times_metric.sql
@@ -0,0 +1,18 @@
+--
+-- Copyright 2021 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
+--
+--     https://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.
+
+SELECT RUN_METRIC('experimental/frame_times.sql') AS suppress_query_output;
+
+SELECT * FROM AvgSurfaceFps;
diff --git a/test/trace_processor/chrome/index b/test/trace_processor/chrome/index
index fffc0a8..005a948 100644
--- a/test/trace_processor/chrome/index
+++ b/test/trace_processor/chrome/index
@@ -12,6 +12,7 @@
 ../../data/chrome_scroll_without_vsync.pftrace scroll_jank_cause_queuing_delay_general_validation.sql scroll_jank_cause_queuing_delay_general_validation.out
 ../../data/chrome_scroll_without_vsync.pftrace chrome_thread_slice_with_cpu_time.sql chrome_thread_slice_with_cpu_time.out
 ../track_event/track_event_counters.textproto chrome_thread_slice_with_cpu_time_repeated.sql chrome_thread_slice_with_cpu_time_repeated.out
+../../data/chrome_rendering_desktop.pftrace frame_times_metric.sql frame_times_metric.out
 
 # Chrome memory snapshots.
 ../../data/chrome_memory_snapshot.pftrace memory_snapshot_general_validation.sql memory_snapshot_general_validation.out
diff --git a/tools/install-build-deps b/tools/install-build-deps
index 81534a6..44bfc4a 100755
--- a/tools/install-build-deps
+++ b/tools/install-build-deps
@@ -229,8 +229,8 @@
     # Example traces for regression tests.
     Dependency(
         'test/data.zip',
-        'https://storage.googleapis.com/perfetto/test-data-20210105-174747.zip',
-        'e4fe27c8aad5bf0c447b2e853302d5431d0f134e368b73b68e5f56a293945d52',
+        'https://storage.googleapis.com/perfetto/test-data-20210128-172149.zip',
+        'f83f9336a2d0d9ac5c3154b949e3237a6c7119b2e8a70b31c7789aff0066b9eb',
         'all',
     ),