Add Android SysUi updateNotifOnUiModeChanged Metric

Introduce a metric for the performance of the Android Notification Pipeline ViewConfigCoordinator#updateNotifOnUiModeChanged. Counts the average and max time, and count for all slices.

Bug: 217799515
Test: tools/diff_test_trace_processor.py out/linux_clang_release/trace_processor_shell --name-filter AndroidMetrics:sysui_update_notif_on_ui_mode_changed --keep-input
Change-Id: Ibc14817fd84d6ff88a5c4c8fc649623ef50d2d47
diff --git a/Android.bp b/Android.bp
index 76264d1..8c2c414 100644
--- a/Android.bp
+++ b/Android.bp
@@ -5053,6 +5053,8 @@
         "protos/perfetto/metrics/android/startup_metric.proto",
         "protos/perfetto/metrics/android/surfaceflinger.proto",
         "protos/perfetto/metrics/android/sysui_notif_shade_list_builder_metric.proto",
+        "protos/perfetto/metrics/android/sysui_slice_performance_statistical_data.proto",
+        "protos/perfetto/metrics/android/sysui_update_notif_on_ui_mode_changed_metric.proto",
         "protos/perfetto/metrics/android/task_names.proto",
         "protos/perfetto/metrics/android/thread_time_in_state_metric.proto",
         "protos/perfetto/metrics/android/trace_quality.proto",
@@ -5136,6 +5138,8 @@
         "protos/perfetto/metrics/android/startup_metric.proto",
         "protos/perfetto/metrics/android/surfaceflinger.proto",
         "protos/perfetto/metrics/android/sysui_notif_shade_list_builder_metric.proto",
+        "protos/perfetto/metrics/android/sysui_slice_performance_statistical_data.proto",
+        "protos/perfetto/metrics/android/sysui_update_notif_on_ui_mode_changed_metric.proto",
         "protos/perfetto/metrics/android/task_names.proto",
         "protos/perfetto/metrics/android/thread_time_in_state_metric.proto",
         "protos/perfetto/metrics/android/trace_quality.proto",
@@ -5202,6 +5206,8 @@
         "protos/perfetto/metrics/android/startup_metric.proto",
         "protos/perfetto/metrics/android/surfaceflinger.proto",
         "protos/perfetto/metrics/android/sysui_notif_shade_list_builder_metric.proto",
+        "protos/perfetto/metrics/android/sysui_slice_performance_statistical_data.proto",
+        "protos/perfetto/metrics/android/sysui_update_notif_on_ui_mode_changed_metric.proto",
         "protos/perfetto/metrics/android/task_names.proto",
         "protos/perfetto/metrics/android/thread_time_in_state_metric.proto",
         "protos/perfetto/metrics/android/trace_quality.proto",
@@ -11507,6 +11513,7 @@
         "src/trace_processor/metrics/sql/android/startup/thread_state_breakdown.sql",
         "src/trace_processor/metrics/sql/android/sysui_notif_shade_list_builder_metric.sql",
         "src/trace_processor/metrics/sql/android/sysui_notif_shade_list_builder_slices.sql",
+        "src/trace_processor/metrics/sql/android/sysui_update_notif_on_ui_mode_changed_metric.sql",
         "src/trace_processor/metrics/sql/android/unsymbolized_frames.sql",
         "src/trace_processor/metrics/sql/chrome/actual_power_by_category.sql",
         "src/trace_processor/metrics/sql/chrome/actual_power_by_rail_mode.sql",
diff --git a/BUILD b/BUILD
index 26b5fac..300819c 100644
--- a/BUILD
+++ b/BUILD
@@ -1923,6 +1923,7 @@
         "src/trace_processor/metrics/sql/android/startup/thread_state_breakdown.sql",
         "src/trace_processor/metrics/sql/android/sysui_notif_shade_list_builder_metric.sql",
         "src/trace_processor/metrics/sql/android/sysui_notif_shade_list_builder_slices.sql",
+        "src/trace_processor/metrics/sql/android/sysui_update_notif_on_ui_mode_changed_metric.sql",
         "src/trace_processor/metrics/sql/android/unsymbolized_frames.sql",
     ],
 )
@@ -4125,6 +4126,8 @@
         "protos/perfetto/metrics/android/startup_metric.proto",
         "protos/perfetto/metrics/android/surfaceflinger.proto",
         "protos/perfetto/metrics/android/sysui_notif_shade_list_builder_metric.proto",
+        "protos/perfetto/metrics/android/sysui_slice_performance_statistical_data.proto",
+        "protos/perfetto/metrics/android/sysui_update_notif_on_ui_mode_changed_metric.proto",
         "protos/perfetto/metrics/android/task_names.proto",
         "protos/perfetto/metrics/android/thread_time_in_state_metric.proto",
         "protos/perfetto/metrics/android/trace_quality.proto",
diff --git a/protos/perfetto/metrics/android/BUILD.gn b/protos/perfetto/metrics/android/BUILD.gn
index df31abf..d7771af 100644
--- a/protos/perfetto/metrics/android/BUILD.gn
+++ b/protos/perfetto/metrics/android/BUILD.gn
@@ -23,7 +23,9 @@
     "ad_services_metric.proto",
     "android_blocking_call.proto",
     "android_blocking_calls_cuj_metric.proto",
+    "sysui_slice_performance_statistical_data.proto",
     "sysui_notif_shade_list_builder_metric.proto",
+    "sysui_update_notif_on_ui_mode_changed_metric.proto",
     "android_boot.proto",
     "android_frame_timeline_metric.proto",
     "android_sysui_notifications_blocking_calls_metric.proto",
diff --git a/protos/perfetto/metrics/android/sysui_notif_shade_list_builder_metric.proto b/protos/perfetto/metrics/android/sysui_notif_shade_list_builder_metric.proto
index 0ead104..485be64 100644
--- a/protos/perfetto/metrics/android/sysui_notif_shade_list_builder_metric.proto
+++ b/protos/perfetto/metrics/android/sysui_notif_shade_list_builder_metric.proto
@@ -17,22 +17,7 @@
 syntax = "proto2";
 
 package perfetto.protos;
-
-// Statistical performance data row for a set of slices
-message SysUiSlicePerformanceStatisticalData {
-  // Name of the Slice
-  optional string name = 1;
-  // Number of times it happened within the CUJ
-  optional int64 cnt = 2;
-  // Average duration within the CUJ
-  optional int64 avg_dur_ms = 3;
-  // Maximal duration within the CUJ
-  optional int64 max_dur_ms = 4;
-  // Average duration within the CUJ in nanoseconds
-  optional int64 avg_dur_ns = 6;
-  // Maximal duration within the CUJ in nanoseconds
-  optional int64 max_dur_ns = 7;
-}
+import "protos/perfetto/metrics/android/sysui_slice_performance_statistical_data.proto";
 
 // System UI Notifications ShadeListBuilder.buildList slices.
 // Shows count, average duration, and max duration for each.
diff --git a/protos/perfetto/metrics/android/sysui_slice_performance_statistical_data.proto b/protos/perfetto/metrics/android/sysui_slice_performance_statistical_data.proto
new file mode 100644
index 0000000..5fe588f
--- /dev/null
+++ b/protos/perfetto/metrics/android/sysui_slice_performance_statistical_data.proto
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2023 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;
+
+// Statistical performance data row for a set of slices
+message SysUiSlicePerformanceStatisticalData {
+  // Name of the Slice
+  optional string name = 1;
+  // Number of times it happened within the CUJ
+  optional int64 cnt = 2;
+  // Average duration within the CUJ
+  optional int64 avg_dur_ms = 3;
+  // Maximal duration within the CUJ
+  optional int64 max_dur_ms = 4;
+  // Average duration within the CUJ in nanoseconds
+  optional int64 avg_dur_ns = 6;
+  // Maximal duration within the CUJ in nanoseconds
+  optional int64 max_dur_ns = 7;
+}
\ No newline at end of file
diff --git a/protos/perfetto/metrics/android/sysui_update_notif_on_ui_mode_changed_metric.proto b/protos/perfetto/metrics/android/sysui_update_notif_on_ui_mode_changed_metric.proto
new file mode 100644
index 0000000..3128c32
--- /dev/null
+++ b/protos/perfetto/metrics/android/sysui_update_notif_on_ui_mode_changed_metric.proto
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2023 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/android/sysui_slice_performance_statistical_data.proto";
+
+// System UI Notifications ShadeListBuilder.buildList slices.
+// Shows count, average duration, and max duration for each.
+message SysuiUpdateNotifOnUiModeChangedMetric {
+  optional SysUiSlicePerformanceStatisticalData all_slices_performance = 1;
+  // Data row for a single slice
+  message SliceDuration {
+    // Name of the Slice
+    optional string name = 1;
+
+    // Duration in ms
+    optional int64 dur_ms = 2;
+
+    // Duration in ns
+    optional int64 dur_ns = 3;
+  }
+  repeated SliceDuration slice = 2;
+}
\ No newline at end of file
diff --git a/protos/perfetto/metrics/metrics.proto b/protos/perfetto/metrics/metrics.proto
index ec250f1..5587efa 100644
--- a/protos/perfetto/metrics/metrics.proto
+++ b/protos/perfetto/metrics/metrics.proto
@@ -21,6 +21,7 @@
 import "protos/perfetto/metrics/android/ad_services_metric.proto";
 import "protos/perfetto/metrics/android/android_boot.proto";
 import "protos/perfetto/metrics/android/sysui_notif_shade_list_builder_metric.proto";
+import "protos/perfetto/metrics/android/sysui_update_notif_on_ui_mode_changed_metric.proto";
 import "protos/perfetto/metrics/android/android_frame_timeline_metric.proto";
 import "protos/perfetto/metrics/android/anr_metric.proto";
 import "protos/perfetto/metrics/android/batt_metric.proto";
@@ -112,7 +113,7 @@
 
 // Root message for all Perfetto-based metrics.
 //
-// Next id: 60
+// Next id: 61
 message TraceMetrics {
   reserved 4, 10, 13, 14, 16, 19;
 
@@ -274,6 +275,8 @@
   optional AdServicesMetric ad_services_metric = 58;
 
   optional SysuiNotifShadeListBuilderMetric sysui_notif_shade_list_builder_metric = 59;
+
+  optional SysuiUpdateNotifOnUiModeChangedMetric sysui_update_notif_on_ui_mode_changed_metric = 60;
   // Demo extensions.
   extensions 450 to 499;
 
diff --git a/protos/perfetto/metrics/perfetto_merged_metrics.proto b/protos/perfetto/metrics/perfetto_merged_metrics.proto
index 63fe631..abdbb2b 100644
--- a/protos/perfetto/metrics/perfetto_merged_metrics.proto
+++ b/protos/perfetto/metrics/perfetto_merged_metrics.proto
@@ -2210,22 +2210,10 @@
 
 // End of protos/perfetto/metrics/android/surfaceflinger.proto
 
-// Begin of protos/perfetto/metrics/android/sysui_notif_shade_list_builder_metric.proto
-
-// Data row for a single slice
-message SliceInfo {
-  // Name of the Slice
-  optional string name = 1;
-
-  // Duration in ms
-  optional int64 dur_ms = 2;
-
-  // Duration in ns
-  optional int64 dur_ns = 3;
-}
+// Begin of protos/perfetto/metrics/android/sysui_slice_performance_statistical_data.proto
 
 // Statistical performance data row for a set of slices
-message SlicePerformanceInfo {
+message SysUiSlicePerformanceStatisticalData {
   // Name of the Slice
   optional string name = 1;
   // Number of times it happened within the CUJ
@@ -2239,17 +2227,52 @@
   // Maximal duration within the CUJ in nanoseconds
   optional int64 max_dur_ns = 7;
 }
+// End of protos/perfetto/metrics/android/sysui_slice_performance_statistical_data.proto
 
+// Begin of protos/perfetto/metrics/android/sysui_notif_shade_list_builder_metric.proto
 // System UI Notifications ShadeListBuilder.buildList slices.
 // Shows count, average duration, and max duration for each.
 message SysuiNotifShadeListBuilderMetric {
-  optional SlicePerformanceInfo all_slices_performance = 1;
-  optional SlicePerformanceInfo slices_with_inflation_performance = 2;
-  optional SlicePerformanceInfo slices_with_modification_performance = 3;
-  repeated SliceInfo slice = 4;
+  optional SysUiSlicePerformanceStatisticalData all_slices_performance = 1;
+  optional SysUiSlicePerformanceStatisticalData slices_with_inflation_performance = 2;
+  optional SysUiSlicePerformanceStatisticalData slices_with_modification_performance = 3;
+
+  // Data row for a single slice
+  message SliceDuration {
+    // Name of the Slice
+    optional string name = 1;
+
+    // Duration in ms
+    optional int64 dur_ms = 2;
+
+    // Duration in ns
+    optional int64 dur_ns = 3;
+  }
+  repeated SliceDuration slice = 4;
 }
 // End of protos/perfetto/metrics/android/sysui_notif_shade_list_builder_metric.proto
 
+// Begin of protos/perfetto/metrics/android/sysui_update_notif_on_ui_mode_changed_metric.proto
+
+// System UI Notifications ShadeListBuilder.buildList slices.
+// Shows count, average duration, and max duration for each.
+message SysuiUpdateNotifOnUiModeChangedMetric {
+  optional SysUiSlicePerformanceStatisticalData all_slices_performance = 1;
+  // Data row for a single slice
+  message SliceDuration {
+    // Name of the Slice
+    optional string name = 1;
+
+    // Duration in ms
+    optional int64 dur_ms = 2;
+
+    // Duration in ns
+    optional int64 dur_ns = 3;
+  }
+  repeated SliceDuration slice = 2;
+}
+// End of protos/perfetto/metrics/android/sysui_update_notif_on_ui_mode_changed_metric.proto
+
 // Begin of protos/perfetto/metrics/android/task_names.proto
 
 message AndroidTaskNames {
@@ -2364,7 +2387,7 @@
 
 // Root message for all Perfetto-based metrics.
 //
-// Next id: 60
+// Next id: 61
 message TraceMetrics {
   reserved 4, 10, 13, 14, 16, 19;
 
@@ -2526,6 +2549,8 @@
   optional AdServicesMetric ad_services_metric = 58;
 
   optional SysuiNotifShadeListBuilderMetric sysui_notif_shade_list_builder_metric = 59;
+
+  optional SysuiUpdateNotifOnUiModeChangedMetric sysui_update_notif_on_ui_mode_changed_metric = 60;
   // Demo extensions.
   extensions 450 to 499;
 
diff --git a/python/perfetto/trace_processor/metrics.descriptor b/python/perfetto/trace_processor/metrics.descriptor
index 1fb3d89..b4c46bc 100644
--- a/python/perfetto/trace_processor/metrics.descriptor
+++ b/python/perfetto/trace_processor/metrics.descriptor
Binary files differ
diff --git a/src/trace_processor/metrics/sql/android/BUILD.gn b/src/trace_processor/metrics/sql/android/BUILD.gn
index e6247a2..54545cf 100644
--- a/src/trace_processor/metrics/sql/android/BUILD.gn
+++ b/src/trace_processor/metrics/sql/android/BUILD.gn
@@ -26,6 +26,7 @@
     "android_blocking_calls_cuj_metric.sql",
     "sysui_notif_shade_list_builder_metric.sql",
     "sysui_notif_shade_list_builder_slices.sql",
+    "sysui_update_notif_on_ui_mode_changed_metric.sql",
     "android_boot.sql",
     "android_camera.sql",
     "android_camera_unagg.sql",
diff --git a/src/trace_processor/metrics/sql/android/sysui_update_notif_on_ui_mode_changed_metric.sql b/src/trace_processor/metrics/sql/android/sysui_update_notif_on_ui_mode_changed_metric.sql
new file mode 100644
index 0000000..ef89a3e
--- /dev/null
+++ b/src/trace_processor/metrics/sql/android/sysui_update_notif_on_ui_mode_changed_metric.sql
@@ -0,0 +1,70 @@
+--
+-- Copyright 2023 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.
+
+INCLUDE PERFETTO MODULE android.slices;
+
+-- Table of updateNotifOnUiModeChanged slices
+DROP TABLE IF EXISTS sysui_update_notif_on_ui_mode_changed_slices;
+CREATE PERFETTO TABLE sysui_update_notif_on_ui_mode_changed_slices AS
+SELECT
+  s.name name,
+  dur,
+  s.id id
+FROM slice s
+  JOIN thread_track ON thread_track.id = s.track_id
+  JOIN thread USING (utid)
+WHERE
+  thread.is_main_thread AND
+  s.dur > 0 AND (
+    s.name GLOB 'updateNotifOnUiModeChanged'
+  );
+
+-- Table of updateNotifOnUiModeChanged slices statistical performance information
+DROP TABLE IF EXISTS sysui_update_notif_on_ui_mode_changed_metric;
+CREATE PERFETTO TABLE sysui_update_notif_on_ui_mode_changed_metric AS
+SELECT
+  s.name name,
+  COUNT(s.name) AS count,
+  cast(avg(dur) as int) average_dur_ns,
+  max(dur) maximum_dur_ns
+FROM sysui_update_notif_on_ui_mode_changed_slices s
+GROUP BY s.name;
+
+DROP VIEW IF EXISTS sysui_update_notif_on_ui_mode_changed_metric_output;
+CREATE PERFETTO VIEW sysui_update_notif_on_ui_mode_changed_metric_output AS
+SELECT SysuiUpdateNotifOnUiModeChangedMetric(
+        'all_slices_performance', (
+            SELECT SysUiSlicePerformanceStatisticalData(
+                'name', a.name,
+                'cnt', a.count,
+                'avg_dur_ms', cast (a.average_dur_ns / 1000000 as int),
+                'max_dur_ms', cast (a.maximum_dur_ns / 1000000 as int),
+                'avg_dur_ns', a.average_dur_ns,
+                'max_dur_ns', a.maximum_dur_ns
+            )
+            FROM sysui_update_notif_on_ui_mode_changed_metric a
+        ),
+        'slice', (
+            SELECT RepeatedField(
+                SysuiUpdateNotifOnUiModeChangedMetric_SliceDuration(
+                    'name', a.name,
+                    'dur_ms', cast (a.dur / 1000000 as int),
+                    'dur_ns', a.dur
+                )
+            )
+            FROM sysui_update_notif_on_ui_mode_changed_slices a
+            ORDER BY dur DESC
+        )
+);
\ No newline at end of file
diff --git a/test/trace_processor/diff_tests/metrics/android/sysui_update_notif_on_ui_mode_changed_metric.out b/test/trace_processor/diff_tests/metrics/android/sysui_update_notif_on_ui_mode_changed_metric.out
new file mode 100644
index 0000000..882253e
--- /dev/null
+++ b/test/trace_processor/diff_tests/metrics/android/sysui_update_notif_on_ui_mode_changed_metric.out
@@ -0,0 +1,20 @@
+sysui_update_notif_on_ui_mode_changed_metric {
+  all_slices_performance {
+    name: "updateNotifOnUiModeChanged"
+    cnt: 2
+    avg_dur_ms: 35
+    max_dur_ms: 40
+    avg_dur_ns: 35000002
+    max_dur_ns: 40000003
+  }
+  slice {
+  name: "updateNotifOnUiModeChanged"
+  dur_ms: 30
+  dur_ns: 30000002
+  }
+  slice {
+  name: "updateNotifOnUiModeChanged"
+  dur_ms: 40
+  dur_ns: 40000003
+  }
+}
\ No newline at end of file
diff --git a/test/trace_processor/diff_tests/metrics/android/sysui_update_notif_on_ui_mode_changed_metric.py b/test/trace_processor/diff_tests/metrics/android/sysui_update_notif_on_ui_mode_changed_metric.py
new file mode 100644
index 0000000..5892b09
--- /dev/null
+++ b/test/trace_processor/diff_tests/metrics/android/sysui_update_notif_on_ui_mode_changed_metric.py
@@ -0,0 +1,102 @@
+#!/usr/bin/env python3
+# Copyright (C) 2023 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
+import synth_common
+
+# com.android.systemui
+SYSUI_PID = 1000
+
+THIRD_PROCESS_PID = 3000
+
+# duration for each child slice
+child_slice_dur = 10_000_000
+
+# parent slice idle duration
+parent_slice_idle_dur = 10_000_000
+
+# List of inflation-related descendant slices of interesting slices
+inflation_child_slice_names = [
+    'HybridGroupManager#inflateHybridView',
+    'NotifChildCont#recreateHeader',
+]
+
+# List of Shade-node-modification-related descendant slices of interesting slices
+modification_child_slice_names = [
+    'ShadeNode#addChildAt',
+    'ShadeNode#removeChildAt',
+    'ShadeNode#moveChildTo',
+]
+
+
+def add_main_thread_atrace(trace, ts, ts_end, buf, pid):
+    trace.add_atrace_begin(ts=ts, tid=pid, pid=pid, buf=buf)
+    trace.add_atrace_end(ts=ts_end, tid=pid, pid=pid)
+
+
+# Creates a trace that has the interesting slices that we are querying for
+# A ShadeListBuilder.buildList slice that has one of each of the inflation_child_slice_names
+# A ShadeListBuilder.buildList slice that has one of each of the modification_child_slice_names
+def add_slices(trace, pid):
+    slice_ts = 2_000_000
+    slice_ts = add_slice_with_children(trace, pid, slice_ts, 'updateNotifOnUiModeChanged', inflation_child_slice_names)
+    add_slice_with_children(trace, pid, slice_ts, 'updateNotifOnUiModeChanged', modification_child_slice_names)
+
+# Add a slice with a set of children slices, return the parent slice's end ts
+def add_slice_with_children(trace, pid, current_ts, parent_name, children_list):
+    ts_end = current_ts + parent_slice_idle_dur + len(children_list) * (child_slice_dur + 1)
+    # add the parent slice
+    add_main_thread_atrace(
+        trace,
+        ts=current_ts,
+        ts_end=ts_end,
+        buf=parent_name,
+        pid=pid)
+    current_ts += parent_slice_idle_dur
+    # Add the children
+    for child_name in children_list:
+        ts_child_end = current_ts + child_slice_dur + 1
+        add_main_thread_atrace(
+            trace,
+            ts=current_ts,
+            ts_end=ts_child_end,
+            buf=child_name,
+            pid=pid)
+        current_ts = ts_child_end
+    return ts_end
+
+def add_process(trace, package_name, uid, pid):
+    trace.add_package_list(ts=0, name=package_name, uid=uid, version_code=1)
+    trace.add_process(
+        pid=pid, ppid=0, cmdline=package_name, uid=uid)
+    trace.add_thread(tid=pid, tgid=pid, cmdline="MainThread", name="MainThread")
+
+
+def setup_trace():
+    trace = synth_common.create_trace()
+    trace.add_packet()
+    add_process(trace, package_name="com.android.systemui", uid=10001,
+                pid=SYSUI_PID)
+    trace.add_ftrace_packet(cpu=0)
+    return trace
+
+
+trace = setup_trace()
+
+
+add_slices(trace, pid=SYSUI_PID)
+
+# See test_sysui_update_notif_on_ui_mode_changed.
+sys.stdout.buffer.write(trace.trace.SerializeToString())
\ No newline at end of file
diff --git a/test/trace_processor/diff_tests/metrics/android/tests.py b/test/trace_processor/diff_tests/metrics/android/tests.py
index 7774420..e2af7bb 100644
--- a/test/trace_processor/diff_tests/metrics/android/tests.py
+++ b/test/trace_processor/diff_tests/metrics/android/tests.py
@@ -139,6 +139,12 @@
           query=Metric('sysui_notif_shade_list_builder_metric'),
           out=Path('sysui_notif_shade_list_builder_metric.out'))
 
+  def test_sysui_update_notif_on_ui_mode_changed(self):
+      return DiffTestBlueprint(
+          trace=Path('sysui_update_notif_on_ui_mode_changed_metric.py'),
+          query=Metric('sysui_update_notif_on_ui_mode_changed_metric'),
+          out=Path('sysui_update_notif_on_ui_mode_changed_metric.out'))
+
   def test_monitor_contention_metric(self):
     return DiffTestBlueprint(
         trace=DataPath('android_monitor_contention_trace.atr'),