Merge "ui: Remove the "null track" plugin" into main
diff --git a/ui/src/common/actions.ts b/ui/src/common/actions.ts
index 4f16d80..f99ae5c 100644
--- a/ui/src/common/actions.ts
+++ b/ui/src/common/actions.ts
@@ -256,7 +256,7 @@
     args: {
       name: string;
       id: string;
-      summaryTrackKey: string;
+      summaryTrackKey?: string;
       collapsed: boolean;
       fixedOrdering?: boolean;
     },
@@ -265,7 +265,8 @@
       name: args.name,
       id: args.id,
       collapsed: args.collapsed,
-      tracks: [args.summaryTrackKey],
+      tracks: [],
+      summaryTrack: args.summaryTrackKey,
       fixedOrdering: args.fixedOrdering,
     };
   },
diff --git a/ui/src/common/state.ts b/ui/src/common/state.ts
index 43f205e..396df65 100644
--- a/ui/src/common/state.ts
+++ b/ui/src/common/state.ts
@@ -148,7 +148,8 @@
 // 49. Remove currentTab, which is only relevant to TabsV1.
 // 50. Remove ftrace filter state.
 // 51. Changed structure of FlamegraphState.expandedCallsiteByViewingOption.
-export const STATE_VERSION = 51;
+// 52. Update track group state - don't make the summary track the first track.
+export const STATE_VERSION = 52;
 
 export const SCROLLING_TRACK_GROUP = 'ScrollingTracks';
 
@@ -290,6 +291,7 @@
   collapsed: boolean;
   tracks: string[]; // Child track ids.
   fixedOrdering?: boolean; // Render tracks without sorting.
+  summaryTrack: string | undefined;
 }
 
 export interface EngineConfig {
diff --git a/ui/src/controller/track_decider.ts b/ui/src/controller/track_decider.ts
index 06e6823..3f942e9 100644
--- a/ui/src/controller/track_decider.ts
+++ b/ui/src/controller/track_decider.ts
@@ -41,7 +41,6 @@
   ACTUAL_FRAMES_SLICE_TRACK_KIND,
   EXPECTED_FRAMES_SLICE_TRACK_KIND,
 } from '../tracks/frames';
-import {NULL_TRACK_URI} from '../tracks/null_track';
 import {decideTracks as screenshotDecideTracks} from '../tracks/screenshots';
 import {THREAD_STATE_TRACK_KIND} from '../tracks/thread_state';
 
@@ -233,19 +232,8 @@
           parentIdToGroupId.set(parentTrackId, trackGroup);
 
           const parentName = getTrackName({name: rawParentName, kind});
-
-          const summaryTrackKey = uuidv4();
-          this.tracksToAdd.push({
-            uri: NULL_TRACK_URI,
-            key: summaryTrackKey,
-            trackSortKey: PrimaryTrackSortKey.NULL_TRACK,
-            trackGroup: undefined,
-            name: parentName,
-          });
-
           this.addTrackGroupActions.push(
             Actions.addTrackGroup({
-              summaryTrackKey: summaryTrackKey,
               name: parentName,
               id: trackGroup,
               collapsed: true,
@@ -406,18 +394,7 @@
 
     for (const [key, value] of devMap) {
       const groupName = group + key;
-      const summaryTrackKey = uuidv4();
-
-      this.tracksToAdd.push({
-        uri: NULL_TRACK_URI,
-        key: summaryTrackKey,
-        trackSortKey: PrimaryTrackSortKey.NULL_TRACK,
-        name: groupName,
-        trackGroup: undefined,
-      });
-
       const addGroup = Actions.addTrackGroup({
-        summaryTrackKey,
         name: groupName,
         id: value,
         collapsed: true,
@@ -456,18 +433,7 @@
 
     for (const [key, value] of devMap) {
       const groupName = key;
-      const summaryTrackKey = uuidv4();
-
-      this.tracksToAdd.push({
-        uri: NULL_TRACK_URI,
-        key: summaryTrackKey,
-        trackSortKey: PrimaryTrackSortKey.NULL_TRACK,
-        name: groupName,
-        trackGroup: undefined,
-      });
-
       const addGroup = Actions.addTrackGroup({
-        summaryTrackKey,
         name: groupName,
         id: value,
         collapsed: true,
@@ -492,9 +458,6 @@
         ) {
           continue;
         }
-        if (track.uri === NULL_TRACK_URI) {
-          continue;
-        }
         if (groupUuid === undefined) {
           groupUuid = uuidv4();
         }
@@ -503,17 +466,7 @@
     }
 
     if (groupUuid !== undefined) {
-      const summaryTrackKey = uuidv4();
-      this.tracksToAdd.push({
-        uri: NULL_TRACK_URI,
-        key: summaryTrackKey,
-        trackSortKey: PrimaryTrackSortKey.NULL_TRACK,
-        name: groupName,
-        trackGroup: undefined,
-      });
-
       const addGroup = Actions.addTrackGroup({
-        summaryTrackKey,
         name: groupName,
         id: groupUuid,
         collapsed: true,
@@ -540,9 +493,6 @@
       ) {
         continue;
       }
-      if (track.uri === NULL_TRACK_URI) {
-        continue;
-      }
       let allowlisted = false;
       for (const regex of ALLOWLIST_REGEXES) {
         allowlisted = allowlisted || regex.test(track.name);
@@ -557,17 +507,7 @@
     }
 
     if (groupUuid !== undefined) {
-      const summaryTrackKey = uuidv4();
-      this.tracksToAdd.push({
-        uri: NULL_TRACK_URI,
-        key: summaryTrackKey,
-        trackSortKey: PrimaryTrackSortKey.NULL_TRACK,
-        name: groupName,
-        trackGroup: undefined,
-      });
-
       const addGroup = Actions.addTrackGroup({
-        summaryTrackKey,
         name: groupName,
         id: groupUuid,
         collapsed: true,
@@ -587,9 +527,6 @@
         ) {
           continue;
         }
-        if (track.uri === NULL_TRACK_URI) {
-          continue;
-        }
         if (groupUuid === undefined) {
           groupUuid = uuidv4();
         }
@@ -598,17 +535,7 @@
     }
 
     if (groupUuid !== undefined) {
-      const summaryTrackKey = uuidv4();
-      this.tracksToAdd.push({
-        uri: NULL_TRACK_URI,
-        key: summaryTrackKey,
-        trackSortKey: PrimaryTrackSortKey.NULL_TRACK,
-        name: groupName,
-        trackGroup: undefined,
-      });
-
       const addGroup = Actions.addTrackGroup({
-        summaryTrackKey: summaryTrackKey,
         name: groupName,
         id: groupUuid,
         collapsed: true,
@@ -962,7 +889,7 @@
     });
 
     // Map From [name] -> [uuid, key]
-    const groupMap = new Map<string, [string, string]>();
+    const groupMap = new Map<string, string>();
 
     for (; it.valid(); it.next()) {
       if (it.name == null || it.uid == null) {
@@ -975,16 +902,7 @@
 
       const groupUuid = `uid-track-group${rawName}`;
       if (groupMap.get(rawName) === undefined) {
-        const summaryTrackKey = uuidv4();
-        this.tracksToAdd.push({
-          uri: NULL_TRACK_URI,
-          trackSortKey: PrimaryTrackSortKey.NULL_TRACK,
-          name: `UID Tracks`,
-          trackGroup: undefined,
-          key: summaryTrackKey,
-        });
-
-        groupMap.set(rawName, [groupUuid, summaryTrackKey]);
+        groupMap.set(rawName, groupUuid);
       }
 
       this.tracksToAdd.push({
@@ -995,12 +913,11 @@
       });
     }
 
-    for (const [name, [groupUuid, summaryTrackKey]] of groupMap) {
+    for (const [name, groupUuid] of groupMap) {
       const addGroup = Actions.addTrackGroup({
         name: name,
         id: groupUuid,
         collapsed: true,
-        summaryTrackKey,
       });
       this.addTrackGroupActions.push(addGroup);
     }
@@ -1589,25 +1506,12 @@
         if (uuid) {
           groupUuid = uuid;
         } else {
-          console.log(`Creating group "${groupName}"`);
-
-          // Add the summary track
-          const summaryTrackKey = uuidv4();
-          this.tracksToAdd.push({
-            uri: NULL_TRACK_URI,
-            trackSortKey: PrimaryTrackSortKey.NULL_TRACK,
-            name: groupName,
-            trackGroup: undefined,
-            key: summaryTrackKey,
-          });
-
           // Add the group
           groupUuid = uuidv4();
           const addGroup = Actions.addTrackGroup({
             name: groupName,
             id: groupUuid,
             collapsed: true,
-            summaryTrackKey,
             fixedOrdering: true,
           });
           this.addTrackGroupActions.push(addGroup);
diff --git a/ui/src/frontend/viewer_page.ts b/ui/src/frontend/viewer_page.ts
index 34d1752..d4929d4 100644
--- a/ui/src/frontend/viewer_page.ts
+++ b/ui/src/frontend/viewer_page.ts
@@ -226,17 +226,27 @@
     );
 
     for (const group of Object.values(globals.state.trackGroups)) {
-      const key = group.tracks[0];
-      const trackBundle = this.resolveTrack(key);
-      const headerPanel = new TrackGroupPanel({
-        trackGroupId: group.id,
-        key: `trackgroup-${group.id}`,
-        trackFSM: trackBundle.trackFSM,
-        labels: trackBundle.labels,
-        tags: trackBundle.tags,
-        collapsed: group.collapsed,
-        title: group.name,
-      });
+      const key = group.summaryTrack;
+      let headerPanel;
+      if (key) {
+        const trackBundle = this.resolveTrack(key);
+        headerPanel = new TrackGroupPanel({
+          trackGroupId: group.id,
+          key: `trackgroup-${group.id}`,
+          trackFSM: trackBundle.trackFSM,
+          labels: trackBundle.labels,
+          tags: trackBundle.tags,
+          collapsed: group.collapsed,
+          title: group.name,
+        });
+      } else {
+        headerPanel = new TrackGroupPanel({
+          trackGroupId: group.id,
+          key: `trackgroup-${group.id}`,
+          collapsed: group.collapsed,
+          title: group.name,
+        });
+      }
 
       const childTracks: Panel[] = [];
       // The first track is the summary track, and is displayed as part of the
diff --git a/ui/src/tracks/chrome_scroll_jank/index.ts b/ui/src/tracks/chrome_scroll_jank/index.ts
index 212c3fa..41917bb 100644
--- a/ui/src/tracks/chrome_scroll_jank/index.ts
+++ b/ui/src/tracks/chrome_scroll_jank/index.ts
@@ -26,11 +26,9 @@
   PluginContext,
   PluginContextTrace,
   PluginDescriptor,
-  PrimaryTrackSortKey,
 } from '../../public';
 import {Engine, EngineProxy} from '../../trace_processor/engine';
 import {CustomSqlDetailsPanelConfig} from '../custom_sql_table_slices';
-import {NULL_TRACK_URI} from '../null_track';
 
 import {ChromeTasksScrollJankTrack} from './chrome_tasks_scroll_jank_track';
 import {EventLatencySliceDetailsPanel} from './event_latency_details_panel';
@@ -138,20 +136,10 @@
   const eventLatencies = await addLatencyTracks();
   result.tracksToAdd = result.tracksToAdd.concat(eventLatencies.tracksToAdd);
 
-  const summaryTrackKey = uuidv4();
-  result.tracksToAdd.push({
-    uri: NULL_TRACK_URI,
-    trackSortKey: PrimaryTrackSortKey.ASYNC_SLICE_TRACK,
-    name: '', // TODO(stevegolton): We should probably put some name here.
-    trackGroup: undefined,
-    key: summaryTrackKey,
-  });
-
   const addTrackGroup = Actions.addTrackGroup({
     name: 'Chrome Scroll Jank',
     id: SCROLL_JANK_GROUP_ID,
     collapsed: false,
-    summaryTrackKey,
     fixedOrdering: true,
   });
 
diff --git a/ui/src/tracks/null_track/index.ts b/ui/src/tracks/null_track/index.ts
deleted file mode 100644
index 540550e..0000000
--- a/ui/src/tracks/null_track/index.ts
+++ /dev/null
@@ -1,53 +0,0 @@
-// Copyright (C) 2022 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.
-
-import {
-  Plugin,
-  PluginContext,
-  PluginContextTrace,
-  PluginDescriptor,
-  Track,
-} from '../../public';
-
-export const NULL_TRACK_URI = 'perfetto.NullTrack';
-export const NULL_TRACK_KIND = 'NullTrack';
-
-export class NullTrack implements Track {
-  getHeight(): number {
-    return 30;
-  }
-
-  render(): void {}
-}
-
-class NullTrackPlugin implements Plugin {
-  onActivate(_ctx: PluginContext): void {}
-
-  async onTraceLoad(ctx: PluginContextTrace): Promise<void> {
-    // TODO(stevegolton): This is not the right way to handle blank tracks,
-    // instead we should probably just render some blank element at render time
-    // if no track uri is supplied.
-    ctx.registerTrack({
-      uri: NULL_TRACK_URI,
-      displayName: 'Null Track',
-      kind: NULL_TRACK_KIND,
-      trackFactory: () => new NullTrack(),
-    });
-  }
-}
-
-export const plugin: PluginDescriptor = {
-  pluginId: 'perfetto.NullTrack',
-  plugin: NullTrackPlugin,
-};