// Copyright (C) 2020 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 {assertExists} from '../base/logging';
import {globals} from '../frontend/globals';
import {TrackDescriptor} from '../public';
import {Engine, EngineBase} from '../trace_processor/engine';
import {NUM, STR, STR_NULL} from '../trace_processor/query_result';
import {
  ACTUAL_FRAMES_SLICE_TRACK_KIND,
  ASYNC_SLICE_TRACK_KIND,
  CHROME_EVENT_LATENCY_TRACK_KIND,
  CHROME_SCROLL_JANK_TRACK_KIND,
  CHROME_TOPLEVEL_SCROLLS_KIND,
  COUNTER_TRACK_KIND,
  CPU_FREQ_TRACK_KIND,
  CPU_PROFILE_TRACK_KIND,
  CPU_SLICE_TRACK_KIND,
  EXPECTED_FRAMES_SLICE_TRACK_KIND,
  HEAP_PROFILE_TRACK_KIND,
  PERF_SAMPLES_PROFILE_TRACK_KIND,
  SCROLL_JANK_V3_TRACK_KIND,
  THREAD_SLICE_TRACK_KIND,
  THREAD_STATE_TRACK_KIND,
} from '../core/track_kinds';
import {exists, Optional} from '../base/utils';
import {GroupNode, ContainerNode, TrackNode} from '../public/workspace';

const MEM_DMA_COUNTER_NAME = 'mem.dma_heap';
const MEM_DMA = 'mem.dma_buffer';
const MEM_ION = 'mem.ion';
const F2FS_IOSTAT_TAG = 'f2fs_iostat.';
const F2FS_IOSTAT_GROUP_NAME = 'f2fs_iostat';
const F2FS_IOSTAT_LAT_TAG = 'f2fs_iostat_latency.';
const F2FS_IOSTAT_LAT_GROUP_NAME = 'f2fs_iostat_latency';
const DISK_IOSTAT_TAG = 'diskstat.';
const DISK_IOSTAT_GROUP_NAME = 'diskstat';
const BUDDY_INFO_TAG = 'mem.buddyinfo';
const UFS_CMD_TAG_REGEX = new RegExp('^io.ufs.command.tag.*$');
const UFS_CMD_TAG_GROUP = 'io.ufs.command.tags';
// NB: Userspace wakelocks start with "WakeLock" not "Wakelock".
const KERNEL_WAKELOCK_REGEX = new RegExp('^Wakelock.*$');
const KERNEL_WAKELOCK_GROUP = 'Kernel wakelocks';
const NETWORK_TRACK_REGEX = new RegExp('^.* (Received|Transmitted)( KB)?$');
const NETWORK_TRACK_GROUP = 'Networking';
const ENTITY_RESIDENCY_REGEX = new RegExp('^Entity residency:');
const ENTITY_RESIDENCY_GROUP = 'Entity residency';
const UCLAMP_REGEX = new RegExp('^UCLAMP_');
const UCLAMP_GROUP = 'Scheduler Utilization Clamping';
const POWER_RAILS_GROUP = 'Power Rails';
const POWER_RAILS_REGEX = new RegExp('^power.');
const FREQUENCY_GROUP = 'Frequency Scaling';
const TEMPERATURE_REGEX = new RegExp('^.* Temperature$');
const TEMPERATURE_GROUP = 'Temperature';
const IRQ_GROUP = 'IRQs';
const IRQ_REGEX = new RegExp('^(Irq|SoftIrq) Cpu.*');
const CHROME_TRACK_REGEX = new RegExp('^Chrome.*|^InputLatency::.*');
const CHROME_TRACK_GROUP = 'Chrome Global Tracks';
const MISC_GROUP = 'Misc Global Tracks';

export async function decideTracks(engine: EngineBase): Promise<void> {
  await new TrackDecider(engine).decideTracks();
}

class TrackDecider {
  private engine: EngineBase;
  private threadGroups = new Map<number, GroupNode>();
  private processGroups = new Map<number, GroupNode>();

  constructor(engine: EngineBase) {
    this.engine = engine;
  }

  private groupGlobalIonTracks(): void {
    const ionTracks: TrackNode[] = [];
    let hasSummary = false;

    for (const track of globals.workspace.children) {
      if (!(track instanceof TrackNode)) continue;

      const isIon = track.displayName.startsWith(MEM_ION);
      const isIonCounter = track.displayName === MEM_ION;
      const isDmaHeapCounter = track.displayName === MEM_DMA_COUNTER_NAME;
      const isDmaBuffferSlices = track.displayName === MEM_DMA;
      if (isIon || isIonCounter || isDmaHeapCounter || isDmaBuffferSlices) {
        ionTracks.push(track);
      }
      hasSummary = hasSummary || isIonCounter;
      hasSummary = hasSummary || isDmaHeapCounter;
    }

    if (ionTracks.length === 0 || !hasSummary) {
      return;
    }

    let group: Optional<GroupNode>;
    for (const track of ionTracks) {
      if (!group && [MEM_DMA_COUNTER_NAME, MEM_ION].includes(track.uri)) {
        globals.workspace.removeChild(track);
        group = new GroupNode(track.displayName);
        group.headerTrackUri = track.uri;
        globals.workspace.addChild(group);
      } else {
        group?.addChild(track);
      }
    }
  }

  private groupGlobalIostatTracks(tag: string, groupName: string): void {
    const devMap = new Map<string, GroupNode>();

    for (const track of globals.workspace.children) {
      if (track instanceof TrackNode && track.displayName.startsWith(tag)) {
        const name = track.displayName.split('.', 3);
        const key = name[1];

        let parentGroup = devMap.get(key);
        if (!parentGroup) {
          const group = new GroupNode(groupName);
          globals.workspace.addChild(group);
          devMap.set(key, group);
          parentGroup = group;
        }

        track.displayName = name[2];
        parentGroup.addChild(track);
      }
    }
  }

  private groupGlobalBuddyInfoTracks(): void {
    const devMap = new Map<string, GroupNode>();

    for (const track of globals.workspace.children) {
      if (
        track instanceof TrackNode &&
        track.displayName.startsWith(BUDDY_INFO_TAG)
      ) {
        const tokens = track.uri.split('[');
        const node = tokens[1].slice(0, -1);
        const zone = tokens[2].slice(0, -1);
        const size = tokens[3].slice(0, -1);

        const groupName = 'Buddyinfo:  Node: ' + node + ' Zone: ' + zone;
        if (!devMap.has(groupName)) {
          const group = new GroupNode(groupName);
          devMap.set(groupName, group);
          globals.workspace.addChild(group);
        }
        track.displayName = 'Chunk size: ' + size;
        const group = devMap.get(groupName)!;
        group.addChild(track);
      }
    }
  }

  private groupFrequencyTracks(groupName: string): void {
    const group = new GroupNode(groupName);

    for (const track of globals.workspace.children) {
      if (!(track instanceof TrackNode)) continue;
      // Group all the frequency tracks together (except the CPU and GPU
      // frequency ones).
      if (
        track.displayName.endsWith('Frequency') &&
        !track.displayName.startsWith('Cpu') &&
        !track.displayName.startsWith('Gpu')
      ) {
        group.addChild(track);
      }
    }

    if (group.children.length > 0) {
      globals.workspace.addChild(group);
    }
  }

  private groupMiscNonAllowlistedTracks(groupName: string): void {
    // List of allowlisted track names.
    const ALLOWLIST_REGEXES = [
      new RegExp('^Cpu .*$', 'i'),
      new RegExp('^Gpu .*$', 'i'),
      new RegExp('^Trace Triggers$'),
      new RegExp('^Android App Startups$'),
      new RegExp('^Device State.*$'),
      new RegExp('^Android logs$'),
    ];

    const group = new GroupNode(groupName);
    for (const track of globals.workspace.children) {
      if (!(track instanceof TrackNode)) continue;
      let allowlisted = false;
      for (const regex of ALLOWLIST_REGEXES) {
        allowlisted = allowlisted || regex.test(track.displayName);
      }
      if (allowlisted) {
        continue;
      }
      group.addChild(track);
    }

    if (group.children.length > 0) {
      globals.workspace.addChild(group);
    }
  }

  private groupTracksByRegex(regex: RegExp, groupName: string): void {
    const group = new GroupNode(groupName);

    for (const track of globals.workspace.children) {
      if (track instanceof TrackNode && regex.test(track.displayName)) {
        group.addChild(track);
      }
    }

    if (group.children.length > 0) {
      globals.workspace.addChild(group);
    }
  }

  private addAnnotationTracks(tracks: ReadonlyArray<TrackDescriptor>): void {
    const annotationTracks = tracks.filter(
      ({tags}) => tags?.scope === 'annotation',
    );
    const groups = new Map<string, GroupNode>();

    annotationTracks
      .filter(({tags}) => tags?.kind === THREAD_SLICE_TRACK_KIND)
      .forEach((td) => {
        const upid = assertExists(td.tags?.upid);
        const groupName = td.tags?.groupName;

        // We want to try and find a group to put this track in. If groupName is
        // defined, create a new group or place in existing one if it already
        // exists Otherwise, try upid to see if we can put this in a process
        // group

        let container: ContainerNode;
        if (groupName) {
          const existingGroup = groups.get(groupName);
          if (!existingGroup) {
            const group = new GroupNode(groupName);
            group.headerTrackUri = td.uri;
            container = group;
            groups.set(groupName, group);
            globals.workspace.addChild(group);
          } else {
            container = existingGroup;
          }
        } else {
          const procGroup = this.processGroups.get(upid);
          if (upid !== 0 && procGroup) {
            container = procGroup;
          } else {
            container = globals.workspace;
          }
        }

        container.addChild(new TrackNode(td.uri, td.title));
      });

    annotationTracks
      .filter(({tags}) => tags?.kind === COUNTER_TRACK_KIND)
      .forEach((td) => {
        const upid = td.tags?.upid;
        const parent =
          (exists(upid) && this.processGroups.get(upid)) || globals.workspace;
        parent.addChild(new TrackNode(td.uri, td.title));
      });
  }

  private addThreadStateTracks(tracks: ReadonlyArray<TrackDescriptor>): void {
    tracks
      .filter(
        ({tags}) =>
          tags?.kind === THREAD_STATE_TRACK_KIND && tags?.utid !== undefined,
      )
      .forEach((td) => {
        const utid = assertExists(td.tags?.utid);
        const group = this.getThreadGroup(utid);
        group.addChild(new TrackNode(td.uri, td.title));
      });
  }

  private addThreadCpuSampleTracks(
    tracks: ReadonlyArray<TrackDescriptor>,
  ): void {
    tracks
      .filter(
        ({tags}) =>
          tags?.kind === CPU_PROFILE_TRACK_KIND && tags?.utid !== undefined,
      )
      .forEach((td) => {
        const utid = assertExists(td.tags?.utid);
        const group = this.getThreadGroup(utid);
        group.addChild(new TrackNode(td.uri, td.title));
      });
  }

  private addThreadCounterTracks(tracks: ReadonlyArray<TrackDescriptor>): void {
    tracks
      .filter(
        ({tags}) =>
          tags?.kind === COUNTER_TRACK_KIND &&
          tags?.utid !== undefined &&
          tags?.scope === 'thread',
      )
      .forEach((td) => {
        const utid = assertExists(td.tags?.utid);
        const group = this.getThreadGroup(utid);
        group.addChild(new TrackNode(td.uri, td.title));
      });
  }

  private addProcessAsyncSliceTracks(
    tracks: ReadonlyArray<TrackDescriptor>,
  ): void {
    tracks
      .filter(
        ({tags}) =>
          tags?.kind === ASYNC_SLICE_TRACK_KIND &&
          tags?.upid !== undefined &&
          tags?.scope === 'process',
      )
      .forEach((td) => {
        const upid = assertExists(td.tags?.upid);
        const group = this.getProcGroup(upid);
        group.addChild(new TrackNode(td.uri, td.title));
      });
  }

  private addUserAsyncSliceTracks(
    tracks: ReadonlyArray<TrackDescriptor>,
  ): void {
    const groupMap = new Map<string, GroupNode>();
    tracks
      .filter(
        ({tags}) =>
          tags?.kind === ASYNC_SLICE_TRACK_KIND &&
          tags?.scope === 'user' &&
          tags?.rawName !== undefined,
      )
      .forEach((td) => {
        const rawName = td.tags?.rawName;
        if (typeof rawName === 'string') {
          const track = new TrackNode(td.uri, td.title);
          const existingGroup = groupMap.get(rawName);
          if (existingGroup) {
            existingGroup.addChild(track);
          } else {
            const group = new GroupNode(rawName);
            globals.workspace.addChild(group);
            groupMap.set(rawName, group);
            group.addChild(track);
          }
        }
      });
  }

  private addActualFramesTracks(tracks: ReadonlyArray<TrackDescriptor>): void {
    tracks
      .filter(
        ({tags}) =>
          tags?.kind === ACTUAL_FRAMES_SLICE_TRACK_KIND &&
          tags?.upid !== undefined,
      )
      .forEach((td) => {
        const upid = assertExists(td.tags?.upid);
        const group = this.getProcGroup(upid);
        group.addChild(new TrackNode(td.uri, td.title));
      });
  }

  private addExpectedFramesTracks(
    tracks: ReadonlyArray<TrackDescriptor>,
  ): void {
    tracks
      .filter(
        ({tags}) =>
          tags?.kind === EXPECTED_FRAMES_SLICE_TRACK_KIND &&
          tags?.upid !== undefined,
      )
      .forEach((td) => {
        const upid = assertExists(td.tags?.upid);
        const group = this.getProcGroup(upid);
        group.addChild(new TrackNode(td.uri, td.title));
      });
  }

  private addThreadSliceTracks(tracks: ReadonlyArray<TrackDescriptor>): void {
    tracks
      .filter(
        ({tags}) =>
          tags?.kind === THREAD_SLICE_TRACK_KIND && tags?.utid !== undefined,
      )
      .forEach((td) => {
        const utid = assertExists(td.tags?.utid);
        // const upid = td.tags?.upid;
        // const isDefaultTrackForScope = Boolean(td.tags?.isDefaultTrackForScope);
        const group = this.getThreadGroup(utid);
        group.addChild(new TrackNode(td.uri, td.title));
      });
  }

  private addAsyncThreadSliceTracks(
    tracks: ReadonlyArray<TrackDescriptor>,
  ): void {
    tracks
      .filter(
        ({tags}) =>
          tags?.kind === ASYNC_SLICE_TRACK_KIND &&
          tags?.utid !== undefined &&
          tags?.scope === 'thread',
      )
      .forEach((td) => {
        const utid = assertExists(td.tags?.utid);
        const group = this.getThreadGroup(utid);
        group.addChild(new TrackNode(td.uri, td.title));
      });
  }

  private async addProcessCounterTracks(
    tracks: ReadonlyArray<TrackDescriptor>,
  ): Promise<void> {
    const processCounterTracks = tracks.filter(
      ({tags}) =>
        tags?.kind === COUNTER_TRACK_KIND &&
        tags?.scope === 'process' &&
        tags?.upid !== undefined,
    );

    for (const td of processCounterTracks) {
      const upid = assertExists(td.tags?.upid);
      const group = this.getProcGroup(upid);
      // const trackNameTag = td.tags?.trackName;
      // const trackName =
      //   typeof trackNameTag === 'string' ? trackNameTag : undefined;
      group.addChild(new TrackNode(td.uri, td.title));
    }
  }

  private addProcessHeapProfileTracks(
    tracks: ReadonlyArray<TrackDescriptor>,
  ): void {
    tracks
      .filter(
        ({tags}) =>
          tags?.kind === HEAP_PROFILE_TRACK_KIND && tags?.upid !== undefined,
      )
      .forEach((td) => {
        const upid = assertExists(td.tags?.upid);
        const group = this.getProcGroup(upid);
        group.addChild(new TrackNode(td.uri, td.title));
      });
  }

  private addProcessPerfSamplesTracks(
    tracks: ReadonlyArray<TrackDescriptor>,
  ): void {
    tracks
      .filter(
        ({tags}) =>
          tags?.kind === PERF_SAMPLES_PROFILE_TRACK_KIND &&
          tags.upid !== undefined &&
          tags.utid === undefined,
      )
      .forEach((td) => {
        const upid = assertExists(td.tags?.upid);
        const group = this.getProcGroup(upid);
        group.addChild(new TrackNode(td.uri, td.title));
      });
  }

  private addThreadPerfSamplesTracks(
    tracks: ReadonlyArray<TrackDescriptor>,
  ): void {
    tracks
      .filter(
        ({tags}) =>
          tags?.kind === PERF_SAMPLES_PROFILE_TRACK_KIND &&
          tags?.utid !== undefined,
      )
      .forEach((td) => {
        // const upid = td.tags?.upid;
        const utid = assertExists(td.tags?.utid);
        const group = this.getThreadGroup(utid);
        group.addChild(new TrackNode(td.uri, td.title));
      });
  }

  private getProcGroup(upid: number): GroupNode {
    const group = this.processGroups.get(upid);
    if (group) {
      return group;
    } else {
      throw new Error(`Unable to find proc group with upid ${upid}`);
    }
  }

  private getThreadGroup(utid: number): GroupNode {
    const group = this.threadGroups.get(utid);
    if (group) {
      return group;
    } else {
      throw new Error(`Unable to find thread group with utid ${utid}`);
    }
  }

  private async addKernelThreadGrouping(engine: Engine): Promise<void> {
    // Identify kernel threads if this is a linux system trace, and sufficient
    // process information is available. Kernel threads are identified by being
    // children of kthreadd (always pid 2).
    // The query will return the kthreadd process row first, which must exist
    // for any other kthreads to be returned by the query.
    // TODO(rsavitski): figure out how to handle the idle process (swapper),
    // which has pid 0 but appears as a distinct process (with its own comm) on
    // each cpu. It'd make sense to exclude its thread state track, but still
    // put process-scoped tracks in this group.
    const result = await engine.query(`
      select
        t.utid, p.upid, (case p.pid when 2 then 1 else 0 end) isKthreadd
      from
        thread t
        join process p using (upid)
        left join process parent on (p.parent_upid = parent.upid)
        join
          (select true from metadata m
             where (m.name = 'system_name' and m.str_value = 'Linux')
           union
           select 1 from (select true from sched limit 1))
      where
        p.pid = 2 or parent.pid = 2
      order by isKthreadd desc
    `);

    const it = result.iter({
      utid: NUM,
      upid: NUM,
    });

    // Not applying kernel thread grouping.
    if (!it.valid()) {
      return;
    }

    // Create the track group. Use kthreadd's PROCESS_SUMMARY_TRACK for the
    // main track. It doesn't summarise the kernel threads within the group,
    // but creating a dedicated track type is out of scope at the time of
    // writing.
    const group = new GroupNode('Kernel threads');
    group.headerTrackUri = '/kernel'; // Summary track
    globals.workspace.addChild(group);

    // Set the group for all kernel threads (including kthreadd itself).
    for (; it.valid(); it.next()) {
      const {utid} = it;

      const threadGroup = new GroupNode(`Kernel Thread ${utid}`);
      threadGroup.headless = true;
      group.addChild(threadGroup);

      this.threadGroups.set(utid, threadGroup);
    }
  }

  // Adds top level groups for processes and thread that don't belong to a
  // process.
  private async addProcessGroups(engine: Engine): Promise<void> {
    const result = await engine.query(`
      with processGroups as (
        select
          upid,
          process.pid as pid,
          process.name as processName,
          sum_running_dur as sumRunningDur,
          thread_slice_count + process_slice_count as sliceCount,
          perf_sample_count as perfSampleCount,
          allocation_count as heapProfileAllocationCount,
          graph_object_count as heapGraphObjectCount,
          (
            select group_concat(string_value)
            from args
            where
              process.arg_set_id is not null and
              arg_set_id = process.arg_set_id and
              flat_key = 'chrome.process_label'
          ) chromeProcessLabels,
          case process.name
            when 'Browser' then 3
            when 'Gpu' then 2
            when 'Renderer' then 1
            else 0
          end as chromeProcessRank
        from _process_available_info_summary
        join process using(upid)
      ),
      threadGroups as (
        select
          utid,
          tid,
          thread.name as threadName,
          sum_running_dur as sumRunningDur,
          slice_count as sliceCount,
          perf_sample_count as perfSampleCount
        from _thread_available_info_summary
        join thread using (utid)
        where upid is null
      )
      select *
      from (
        select
          'process' as kind,
          upid as uid,
          pid as id,
          processName as name
        from processGroups
        order by
          chromeProcessRank desc,
          heapProfileAllocationCount desc,
          heapGraphObjectCount desc,
          perfSampleCount desc,
          sumRunningDur desc,
          sliceCount desc,
          processName asc,
          upid asc
      )
      union all
      select *
      from (
        select
          'thread' as kind,
          utid as uid,
          tid as id,
          threadName as name
        from threadGroups
        order by
          perfSampleCount desc,
          sumRunningDur desc,
          sliceCount desc,
          threadName asc,
          utid asc
      )
  `);

    const it = result.iter({
      kind: STR,
      uid: NUM,
      id: NUM,
      name: STR_NULL,
    });
    for (; it.valid(); it.next()) {
      const {kind, uid, id, name} = it;

      if (kind === 'process') {
        // Ignore kernel process groups
        if (this.processGroups.has(uid)) {
          continue;
        }

        function getProcessDisplayName(
          processName: string | undefined,
          pid: number,
        ) {
          if (processName) {
            return `${stripPathFromExecutable(processName)} ${pid}`;
          } else {
            return `Process ${pid}`;
          }
        }

        const displayName = getProcessDisplayName(name ?? undefined, id);

        const group = new GroupNode(displayName);
        group.headerTrackUri = `/process_${uid}`; // Summary track URI
        globals.workspace.addChild(group);
        this.processGroups.set(uid, group);
      } else {
        // Ignore kernel process groups
        if (this.threadGroups.has(uid)) {
          continue;
        }

        function getThreadDisplayName(
          threadName: string | undefined,
          pid: number,
        ) {
          if (threadName) {
            return `${stripPathFromExecutable(threadName)} ${pid}`;
          } else {
            return `Thread ${pid}`;
          }
        }

        const displayName = getThreadDisplayName(name ?? undefined, id);

        const group = new GroupNode(displayName);
        group.headerTrackUri = `/thread_${uid}`; // Summary track URI
        globals.workspace.addChild(group);
        this.threadGroups.set(uid, group);
      }
    }
  }

  // Create all the nested & headless thread groups that live inside existing
  // process groups.
  private async addThreadGroups(engine: Engine): Promise<void> {
    const result = await engine.query(`
      with threadGroups as (
        select
          utid,
          upid,
          tid,
          thread.name as threadName,
          CASE
            WHEN thread.is_main_thread = 1 THEN 10
            WHEN thread.name = 'CrBrowserMain' THEN 10
            WHEN thread.name = 'CrRendererMain' THEN 10
            WHEN thread.name = 'CrGpuMain' THEN 10
            WHEN thread.name glob '*RenderThread*' THEN 9
            WHEN thread.name glob '*GPU completion*' THEN 8
            WHEN thread.name = 'Chrome_ChildIOThread' THEN 7
            WHEN thread.name = 'Chrome_IOThread' THEN 7
            WHEN thread.name = 'Compositor' THEN 6
            WHEN thread.name = 'VizCompositorThread' THEN 6
            ELSE 5
          END as priority
        from _thread_available_info_summary
        join thread using (utid)
        where upid is not null
      )
      select *
      from (
        select
          utid,
          upid,
          tid,
          threadName
        from threadGroups
        order by
          priority desc,
          tid asc
      )
  `);

    const it = result.iter({
      utid: NUM,
      tid: NUM,
      upid: NUM,
      threadName: STR_NULL,
    });
    for (; it.valid(); it.next()) {
      const {utid, tid, upid, threadName} = it;

      // Ignore kernel thread groups
      if (this.threadGroups.has(utid)) {
        continue;
      }

      const threadGroup = new GroupNode(threadName ?? `Thread ${tid}`);
      this.threadGroups.set(utid, threadGroup);
      threadGroup.headless = true;
      threadGroup.expand();

      this.processGroups.get(upid)?.addChild(threadGroup);
    }
  }

  private addPluginTracks(): void {
    const groups = new Map<string, GroupNode>();
    const tracks = globals.trackManager.getAutoShowTracks();

    for (const info of tracks) {
      const groupName = info.tags?.groupName;
      let container: ContainerNode = globals.workspace;

      if (groupName) {
        const existingGroup = groups.get(groupName);
        if (existingGroup) {
          container = existingGroup;
        } else {
          // Add the group
          const group = new GroupNode(groupName);
          container = group;
          globals.workspace.addChild(group);
          groups.set(groupName, group);
        }
      }

      const track = new TrackNode(info.uri, info.title);
      container.addChild(track);
    }
  }

  private addScrollJankPluginTracks(
    tracks: ReadonlyArray<TrackDescriptor>,
  ): void {
    const group = new GroupNode('Chrome Scroll Jank');
    group.expand();
    tracks
      .filter(({tags}) => tags?.kind === CHROME_TOPLEVEL_SCROLLS_KIND)
      .forEach((td) => {
        group.addChild(new TrackNode(td.uri, td.title));
      });
    tracks
      .filter(({tags}) => tags?.kind === SCROLL_JANK_V3_TRACK_KIND)
      .forEach((td) => {
        group.addChild(new TrackNode(td.uri, td.title));
      });
    tracks
      .filter(({tags}) => tags?.kind === CHROME_EVENT_LATENCY_TRACK_KIND)
      .forEach((td) => {
        group.addChild(new TrackNode(td.uri, td.title));
      });
    if (group.children.length) {
      globals.workspace.addChild(group);
    }
  }

  private addChromeScrollJankTrack(
    tracks: ReadonlyArray<TrackDescriptor>,
  ): void {
    tracks
      .filter(({tags}) => tags?.kind === CHROME_SCROLL_JANK_TRACK_KIND)
      .forEach((td) => {
        const utid = assertExists(td.tags?.utid);
        const group = this.getThreadGroup(utid);
        group.addChild(new TrackNode(td.uri, td.title));
      });
  }

  // Add an ordinary track from a track descriptor
  private addTrack(track: TrackDescriptor): void {
    globals.workspace.addChild(new TrackNode(track.uri, track.title));
  }

  // Add tracks that match some predicate
  private addTracks(
    source: ReadonlyArray<TrackDescriptor>,
    predicate: (td: TrackDescriptor) => boolean,
  ): ReadonlyArray<TrackDescriptor> {
    const filteredTracks = source.filter(predicate);
    filteredTracks.forEach((a) => this.addTrack(a));
    return filteredTracks;
  }

  public async decideTracks(): Promise<void> {
    const tracks = globals.trackManager.getAllTracks();

    // Add first the global tracks that don't require per-process track groups.
    this.addTracks(tracks, ({uri}) => uri === 'screenshots');
    this.addTracks(tracks, ({tags}) => tags?.kind === CPU_SLICE_TRACK_KIND);
    this.addTracks(tracks, ({tags}) => tags?.kind === CPU_FREQ_TRACK_KIND);
    this.addScrollJankPluginTracks(tracks);
    this.addTracks(
      tracks,
      ({tags}) =>
        tags?.kind === ASYNC_SLICE_TRACK_KIND && tags?.scope === 'global',
    );
    this.addTracks(
      tracks,
      ({tags}) =>
        tags?.kind === COUNTER_TRACK_KIND && tags?.scope === 'gpuFreq',
    );
    this.addTracks(
      tracks,
      ({tags}) =>
        tags?.kind === COUNTER_TRACK_KIND && tags?.scope === 'cpuFreqLimit',
    );
    this.addTracks(
      tracks,
      ({tags}) =>
        tags?.kind === COUNTER_TRACK_KIND && tags?.scope === 'cpuPerf',
    );
    this.addPluginTracks();
    this.addAnnotationTracks(tracks);

    this.groupGlobalIonTracks();
    this.groupGlobalIostatTracks(F2FS_IOSTAT_TAG, F2FS_IOSTAT_GROUP_NAME);
    this.groupGlobalIostatTracks(
      F2FS_IOSTAT_LAT_TAG,
      F2FS_IOSTAT_LAT_GROUP_NAME,
    );
    this.groupGlobalIostatTracks(DISK_IOSTAT_TAG, DISK_IOSTAT_GROUP_NAME);
    this.groupTracksByRegex(UFS_CMD_TAG_REGEX, UFS_CMD_TAG_GROUP);
    this.groupGlobalBuddyInfoTracks();
    this.groupTracksByRegex(KERNEL_WAKELOCK_REGEX, KERNEL_WAKELOCK_GROUP);
    this.groupTracksByRegex(NETWORK_TRACK_REGEX, NETWORK_TRACK_GROUP);
    this.groupTracksByRegex(ENTITY_RESIDENCY_REGEX, ENTITY_RESIDENCY_GROUP);
    this.groupTracksByRegex(UCLAMP_REGEX, UCLAMP_GROUP);
    this.groupFrequencyTracks(FREQUENCY_GROUP);
    this.groupTracksByRegex(POWER_RAILS_REGEX, POWER_RAILS_GROUP);
    this.groupTracksByRegex(TEMPERATURE_REGEX, TEMPERATURE_GROUP);
    this.groupTracksByRegex(IRQ_REGEX, IRQ_GROUP);
    this.groupTracksByRegex(CHROME_TRACK_REGEX, CHROME_TRACK_GROUP);
    this.groupMiscNonAllowlistedTracks(MISC_GROUP);

    // Add user slice tracks before listing the processes. These tracks will
    // be listed with their user/package name only, and they will be grouped
    // under on their original shared track names. E.g. "GPU Work Period"
    this.addUserAsyncSliceTracks(tracks);

    // Pre-group all kernel "threads" (actually processes) if this is a linux
    // system trace. Below, addProcessTrackGroups will skip them due to an
    // existing group uuid, and addThreadStateTracks will fill in the
    // per-thread tracks. Quirk: since all threads will appear to be
    // TrackKindPriority.MAIN_THREAD, any process-level tracks will end up
    // pushed to the bottom of the group in the UI.
    await this.addKernelThreadGrouping(
      this.engine.getProxy('TrackDecider::addKernelThreadGrouping'),
    );

    // Create the per-process track groups. Note that this won't necessarily
    // create a track per process. If a process has been completely idle and has
    // no sched events, no track group will be emitted.
    // Will populate this.addTrackGroupActions
    await this.addProcessGroups(
      this.engine.getProxy('TrackDecider::addProcessTrackGroups'),
    );

    this.addExpectedFramesTracks(tracks);
    this.addActualFramesTracks(tracks);
    this.addProcessPerfSamplesTracks(tracks);
    this.addProcessHeapProfileTracks(tracks);

    await this.addThreadGroups(
      this.engine.getProxy('TrackDecider::addThreadTrackGroups'),
    );

    this.addThreadPerfSamplesTracks(tracks);
    this.addThreadCpuSampleTracks(tracks);
    this.addThreadStateTracks(tracks);
    this.addThreadSliceTracks(tracks);
    this.addThreadCounterTracks(tracks);

    await this.addProcessCounterTracks(tracks);
    this.addProcessAsyncSliceTracks(tracks);
    this.addAsyncThreadSliceTracks(tracks);

    this.addChromeScrollJankTrack(tracks);

    // Remove any empty groups
    globals.workspace.children.forEach((n) => {
      if (n instanceof GroupNode && n.children.length === 0) {
        globals.workspace.removeChild(n);
      }
    });

    // Move groups underneath tracks
    Array.from(globals.workspace.children)
      .sort((a, b) => {
        // Define the desired order
        const order = [TrackNode, GroupNode];

        // Get the index in the order array
        const indexA = order.findIndex((type) => a instanceof type);
        const indexB = order.findIndex((type) => b instanceof type);

        // Sort based on the index in the order array
        return indexA - indexB;
      })
      .forEach((n) => globals.workspace.addChild(n));

    // If there is only one group, expand it
    const groups = globals.workspace.children;
    if (groups.length === 1 && groups[0] instanceof GroupNode) {
      groups[0].expand();
    }
  }
}

function stripPathFromExecutable(path: string) {
  if (path[0] === '/') {
    return path.split('/').slice(-1)[0];
  } else {
    return path;
  }
}
