Merge "perfetto: remove output_to_genfiles parameter for protos" into main
diff --git a/docs/contributing/ui-plugins.md b/docs/contributing/ui-plugins.md
index 67bb445..09fa88e 100644
--- a/docs/contributing/ui-plugins.md
+++ b/docs/contributing/ui-plugins.md
@@ -468,7 +468,7 @@
 
 Persistent plugin state works using a `Store<T>` where `T` is some JSON
 serializable object.
-`Store` is implemented [here](https://cs.android.com/android/platform/superproject/main/+/main:external/perfetto/ui/src/frontend/store.ts).
+`Store` is implemented [here](https://cs.android.com/android/platform/superproject/main/+/main:external/perfetto/ui/src/base/store.ts).
 `Store` allows for reading and writing `T`.
 Reading:
 ```typescript
diff --git a/python/generators/sql_processing/utils.py b/python/generators/sql_processing/utils.py
index 1a76e1f..f7d733d 100644
--- a/python/generators/sql_processing/utils.py
+++ b/python/generators/sql_processing/utils.py
@@ -70,7 +70,7 @@
     fr" \( ({ARGS}) \) "
     # Type: table definition after RETURNS.
     fr"({COMMENTS})"
-    fr" RETURNS TABLE\( ({ARGS}) \) AS ")
+    fr" RETURNS TABLE \( ({ARGS}) \) AS ")
 
 CREATE_MACRO_PATTERN = update_pattern(
     fr"CREATE (OR REPLACE)? PERFETTO MACRO ({NAME}) "
diff --git a/src/trace_processor/perfetto_sql/intrinsics/table_functions/interval_intersect.cc b/src/trace_processor/perfetto_sql/intrinsics/table_functions/interval_intersect.cc
index b408d31..9ce7423 100644
--- a/src/trace_processor/perfetto_sql/intrinsics/table_functions/interval_intersect.cc
+++ b/src/trace_processor/perfetto_sql/intrinsics/table_functions/interval_intersect.cc
@@ -192,8 +192,8 @@
       }
 
       tables::IntervalIntersectTable::Row row;
-      row.ts = static_cast<uint32_t>(std::max(r_i.ts, l_i.ts));
-      row.dur = static_cast<uint32_t>(std::min(r_i.end(), l_i.end())) - row.ts;
+      row.ts = std::max(r_i.ts, l_i.ts);
+      row.dur = std::min(r_i.end(), l_i.end()) - row.ts;
       row.left_id = static_cast<uint32_t>(l_i.id);
       row.right_id = static_cast<uint32_t>(r_i.id);
       table->Insert(row);
@@ -214,8 +214,8 @@
       }
 
       tables::IntervalIntersectTable::Row row;
-      row.ts = static_cast<uint32_t>(std::max(r_i.ts, l_i.ts));
-      row.dur = static_cast<uint32_t>(std::min(r_i.end(), l_i.end())) - row.ts;
+      row.ts = std::max(r_i.ts, l_i.ts);
+      row.dur = std::min(r_i.end(), l_i.end()) - row.ts;
       row.left_id = static_cast<uint32_t>(l_i.id);
       row.right_id = static_cast<uint32_t>(r_i.id);
       table->Insert(row);
diff --git a/src/trace_processor/perfetto_sql/stdlib/intervals/intersect.sql b/src/trace_processor/perfetto_sql/stdlib/intervals/intersect.sql
index 2775e63..4d867d0 100644
--- a/src/trace_processor/perfetto_sql/stdlib/intervals/intersect.sql
+++ b/src/trace_processor/perfetto_sql/stdlib/intervals/intersect.sql
@@ -37,7 +37,7 @@
   ts Expr,
   dur Expr,
   intervals_table TableOrSubquery
-) RETURNS TableOrSubquery AS(
+) RETURNS TableOrSubquery AS (
   SELECT
     left_id AS id,
     ts,
diff --git a/test/trace_processor/diff_tests/stdlib/intervals/intersect_tests.py b/test/trace_processor/diff_tests/stdlib/intervals/intersect_tests.py
index 3fbdda0..b4bd982 100644
--- a/test/trace_processor/diff_tests/stdlib/intervals/intersect_tests.py
+++ b/test/trace_processor/diff_tests/stdlib/intervals/intersect_tests.py
@@ -21,7 +21,7 @@
 
 class IntervalsIntersect(TestSuite):
 
-  def test_simple_inteval_intersect(self):
+  def test_simple_interval_intersect(self):
     return DiffTestBlueprint(
         trace=TextProto(""),
         #      0 1 2 3 4 5 6 7
@@ -58,7 +58,7 @@
         6,1,0,2
         """))
 
-  def test_simple_inteval_intersect_rev(self):
+  def test_simple_interval_intersect_rev(self):
     return DiffTestBlueprint(
         trace=TextProto(""),
         #      0 1 2 3 4 5 6 7
@@ -272,3 +272,103 @@
         out=Csv("""
         "ts","dur","left_id","right_id"
         """))
+
+  def test_single_interval(self):
+    return DiffTestBlueprint(
+        trace=TextProto(""),
+        #      0 1 2 3 4 5 6 7
+        # A:   _ - - - - - - _
+        # B:   - - _ - - _ - -
+        # res: _ - _ - - _ - _
+        query="""
+        INCLUDE PERFETTO MODULE intervals.intersect;
+
+        CREATE PERFETTO TABLE A AS
+          WITH data(id, ts, dur) AS (
+            VALUES
+            (0, 1, 6)
+          )
+          SELECT * FROM data;
+
+        CREATE PERFETTO TABLE B AS
+          WITH data(id, ts, dur) AS (
+            VALUES
+            (0, 0, 2),
+            (1, 3, 2),
+            (2, 6, 2)
+          )
+          SELECT * FROM data;
+
+        SELECT *
+        FROM _interval_intersect_single!(1, 6, B)
+        ORDER BY ts;
+        """,
+        out=Csv("""
+        "id","ts","dur"
+        0,1,1
+        1,3,2
+        2,6,1
+        """))
+
+  def test_sanity_check(self):
+    return DiffTestBlueprint(
+        trace=DataPath('example_android_trace_30s.pb'),
+        query="""
+        INCLUDE PERFETTO MODULE intervals.intersect;
+
+        CREATE PERFETTO TABLE trace_interval AS
+        SELECT
+          0 AS id,
+          TRACE_START() AS ts,
+          TRACE_DUR() AS dur;
+
+        CREATE PERFETTO TABLE non_overlapping AS
+        SELECT
+          id, ts, dur
+        FROM thread_state
+        WHERE utid = 1 AND dur != -1;
+
+        WITH ii AS (
+          SELECT *
+          FROM _interval_intersect!(trace_interval, non_overlapping)
+        )
+        SELECT
+          (SELECT count(*) FROM ii) AS ii_count,
+          (SELECT count(*) FROM non_overlapping) AS thread_count,
+          (SELECT sum(dur) FROM ii) AS ii_sum,
+          (SELECT sum(dur) FROM non_overlapping) AS thread_sum;
+        """,
+        out=Csv("""
+        "ii_count","thread_count","ii_sum","thread_sum"
+        313,313,27540674879,27540674879
+        """))
+
+  def test_sanity_check_single_interval(self):
+    return DiffTestBlueprint(
+        trace=DataPath('example_android_trace_30s.pb'),
+        query="""
+        INCLUDE PERFETTO MODULE intervals.intersect;
+
+        CREATE PERFETTO TABLE non_overlapping AS
+        SELECT
+          id, ts, dur
+        FROM thread_state
+        WHERE utid = 1 AND dur != -1;
+
+        WITH ii AS (
+          SELECT *
+          FROM _interval_intersect_single!(
+            TRACE_START(),
+            TRACE_DUR(),
+            non_overlapping)
+        )
+        SELECT
+          (SELECT count(*) FROM ii) AS ii_count,
+          (SELECT count(*) FROM non_overlapping) AS thread_count,
+          (SELECT sum(dur) FROM ii) AS ii_sum,
+          (SELECT sum(dur) FROM non_overlapping) AS thread_sum;
+        """,
+        out=Csv("""
+        "ii_count","thread_count","ii_sum","thread_sum"
+        313,313,27540674879,27540674879
+        """))
diff --git a/test/trace_processor/diff_tests/stdlib/sched/tests.py b/test/trace_processor/diff_tests/stdlib/sched/tests.py
index 9324d51..6fd4414 100644
--- a/test/trace_processor/diff_tests/stdlib/sched/tests.py
+++ b/test/trace_processor/diff_tests/stdlib/sched/tests.py
@@ -223,7 +223,7 @@
         """,
         out=Csv("""
         "state","io_wait","blocked_function","dur"
-        "S","[NULL]","[NULL]",1404466083
+        "S","[NULL]","[NULL]",9994400675
         "Running","[NULL]","[NULL]",4655524
         "D","[NULL]","[NULL]",563645
         "R+","[NULL]","[NULL]",380156
@@ -240,7 +240,7 @@
         """,
         out=Csv("""
         "state","io_wait","cpu","blocked_function","dur"
-        "S","[NULL]","[NULL]","[NULL]",1404466083
+        "S","[NULL]","[NULL]","[NULL]",9994400675
         "Running","[NULL]",2,"[NULL]",4655524
         "D","[NULL]","[NULL]","[NULL]",563645
         "R+","[NULL]","[NULL]","[NULL]",380156
diff --git a/tools/check_sql_modules.py b/tools/check_sql_modules.py
index c09261b..ff21b4f 100755
--- a/tools/check_sql_modules.py
+++ b/tools/check_sql_modules.py
@@ -83,9 +83,6 @@
         if not pattern.match(rel_path):
           continue
 
-      if args.verbose:
-        print(f'Parsing {rel_path}:')
-
       with open(path, 'r') as f:
         sql = f.read()
 
@@ -98,10 +95,13 @@
       modules.append((path, sql, parsed))
 
       if args.verbose:
-        function_count = len(parsed.functions) + len(parsed.table_functions)
-        print(f'Parsed {function_count} functions'
-              f', {len(parsed.table_views)} tables/views'
-              f' ({len(parsed.errors)} errors).')
+        obj_count = len(parsed.functions) + len(parsed.table_functions) + len(
+            parsed.table_views) + len(parsed.macros)
+        print(
+            f"""Parsing '{rel_path}' ({obj_count} objects, {len(parsed.errors)} errors)
+- {len(parsed.functions)} functions + {len(parsed.table_functions)} table functions,
+- {len(parsed.table_views)} tables/views,
+- {len(parsed.macros)} macros.""")
 
   for path, sql, parsed in modules:
     lines = [l.strip() for l in sql.split('\n')]
diff --git a/ui/src/common/array_buffer_builder.ts b/ui/src/base/array_buffer_builder.ts
similarity index 100%
rename from ui/src/common/array_buffer_builder.ts
rename to ui/src/base/array_buffer_builder.ts
diff --git a/ui/src/common/registry.ts b/ui/src/base/registry.ts
similarity index 100%
rename from ui/src/common/registry.ts
rename to ui/src/base/registry.ts
diff --git a/ui/src/common/registry_unittest.ts b/ui/src/base/registry_unittest.ts
similarity index 100%
rename from ui/src/common/registry_unittest.ts
rename to ui/src/base/registry_unittest.ts
diff --git a/ui/src/frontend/store.ts b/ui/src/base/store.ts
similarity index 98%
rename from ui/src/frontend/store.ts
rename to ui/src/base/store.ts
index dfb9f0e..395da5e 100644
--- a/ui/src/frontend/store.ts
+++ b/ui/src/base/store.ts
@@ -14,8 +14,8 @@
 
 import produce, {Draft} from 'immer';
 
-import {Disposable} from '../base/disposable';
-import {getPath, Path, setPath} from '../base/object_utils';
+import {Disposable} from './disposable';
+import {getPath, Path, setPath} from './object_utils';
 
 export type Migrate<T> = (init: unknown) => T;
 export type Edit<T> = (draft: Draft<T>) => void;
diff --git a/ui/src/frontend/store_unittest.ts b/ui/src/base/store_unittest.ts
similarity index 99%
rename from ui/src/frontend/store_unittest.ts
rename to ui/src/base/store_unittest.ts
index 00bd3f2..4d15334 100644
--- a/ui/src/frontend/store_unittest.ts
+++ b/ui/src/base/store_unittest.ts
@@ -14,8 +14,8 @@
 
 import {Draft} from 'immer';
 
+import {using} from './disposable';
 import {createStore} from './store';
-import {using} from '../base/disposable';
 
 interface Bar {
   value: number;
diff --git a/ui/src/common/actions.ts b/ui/src/common/actions.ts
index 530f086..139fc7b 100644
--- a/ui/src/common/actions.ts
+++ b/ui/src/common/actions.ts
@@ -30,7 +30,7 @@
 } from '../frontend/pivot_table_types';
 import {PrimaryTrackSortKey} from '../public/index';
 
-import {randomColor} from './colorizer';
+import {randomColor} from '../core/colorizer';
 import {
   computeIntervals,
   DropDirection,
diff --git a/ui/src/common/commands.ts b/ui/src/common/commands.ts
index 7b44775..8ef8b9e 100644
--- a/ui/src/common/commands.ts
+++ b/ui/src/common/commands.ts
@@ -14,8 +14,8 @@
 
 import {Disposable} from '../base/disposable';
 import {FuzzyFinder, FuzzySegment} from '../base/fuzzy';
+import {Registry} from '../base/registry';
 import {Command} from '../public';
-import {Registry} from './registry';
 
 export interface CommandWithMatchInfo extends Command {
   segments: FuzzySegment[];
diff --git a/ui/src/common/plugins.ts b/ui/src/common/plugins.ts
index 56b88cd..80e9ca7 100644
--- a/ui/src/common/plugins.ts
+++ b/ui/src/common/plugins.ts
@@ -15,6 +15,7 @@
 import {v4 as uuidv4} from 'uuid';
 
 import {Disposable, Trash} from '../base/disposable';
+import {Registry} from '../base/registry';
 import {time} from '../base/time';
 import {globals} from '../frontend/globals';
 import {
@@ -39,7 +40,6 @@
 import {Engine} from '../trace_processor/engine';
 
 import {Actions} from './actions';
-import {Registry} from './registry';
 import {SCROLLING_TRACK_GROUP} from './state';
 import {addQueryResultsTab} from '../frontend/query_result_tab';
 import {Flag, featureFlags} from '../core/feature_flags';
diff --git a/ui/src/common/recordingV2/adb_connection_impl.ts b/ui/src/common/recordingV2/adb_connection_impl.ts
index 071f93f..3378057 100644
--- a/ui/src/common/recordingV2/adb_connection_impl.ts
+++ b/ui/src/common/recordingV2/adb_connection_impl.ts
@@ -15,7 +15,7 @@
 import {_TextDecoder} from 'custom_utils';
 
 import {defer} from '../../base/deferred';
-import {ArrayBufferBuilder} from '../array_buffer_builder';
+import {ArrayBufferBuilder} from '../../base/array_buffer_builder';
 
 import {AdbFileHandler} from './adb_file_handler';
 import {
diff --git a/ui/src/common/recordingV2/adb_file_handler.ts b/ui/src/common/recordingV2/adb_file_handler.ts
index c3a1149..0c538c3 100644
--- a/ui/src/common/recordingV2/adb_file_handler.ts
+++ b/ui/src/common/recordingV2/adb_file_handler.ts
@@ -16,7 +16,7 @@
 
 import {defer, Deferred} from '../../base/deferred';
 import {assertFalse} from '../../base/logging';
-import {ArrayBufferBuilder} from '../array_buffer_builder';
+import {ArrayBufferBuilder} from '../../base/array_buffer_builder';
 
 import {RecordingError} from './recording_error_handling';
 import {ByteStream} from './recording_interfaces_v2';
diff --git a/ui/src/common/recordingV2/target_factory_registry.ts b/ui/src/common/recordingV2/target_factory_registry.ts
index f68ef8e..54cec4a 100644
--- a/ui/src/common/recordingV2/target_factory_registry.ts
+++ b/ui/src/common/recordingV2/target_factory_registry.ts
@@ -12,7 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-import {Registry} from '../registry';
+import {Registry} from '../../base/registry';
 
 import {RecordingTargetV2, TargetFactory} from './recording_interfaces_v2';
 
diff --git a/ui/src/common/track_cache.ts b/ui/src/common/track_cache.ts
index 01ff733..3b2eb41 100644
--- a/ui/src/common/track_cache.ts
+++ b/ui/src/common/track_cache.ts
@@ -13,9 +13,10 @@
 // limitations under the License.
 
 import {Disposable, DisposableCallback} from '../base/disposable';
-import {PanelSize} from '../frontend/panel';
 import {exists} from '../base/utils';
-import {Store} from '../frontend/store';
+import {Registry} from '../base/registry';
+import {Store} from '../base/store';
+import {PanelSize} from '../frontend/panel';
 import {
   Migrate,
   Track,
@@ -23,7 +24,6 @@
   TrackDescriptor,
   TrackRef,
 } from '../public';
-import {Registry} from './registry';
 
 import {ObjectByKey, State, TrackState} from './state';
 
diff --git a/ui/src/common/track_helper.ts b/ui/src/common/track_helper.ts
index 7ba951c..4adeee6 100644
--- a/ui/src/common/track_helper.ts
+++ b/ui/src/common/track_helper.ts
@@ -14,10 +14,10 @@
 
 import {Disposable} from '../base/disposable';
 import {duration, Time, time, TimeSpan} from '../base/time';
+export {Store} from '../base/store';
 import {raf} from '../core/raf_scheduler';
 import {globals} from '../frontend/globals';
 
-export {Store} from '../frontend/store';
 export {EngineProxy} from '../trace_processor/engine';
 export {
   LONG,
diff --git a/ui/src/controller/trace_controller.ts b/ui/src/controller/trace_controller.ts
index 7f3b2a3..56507d9 100644
--- a/ui/src/controller/trace_controller.ts
+++ b/ui/src/controller/trace_controller.ts
@@ -106,7 +106,7 @@
   TraceFileStream,
   TraceHttpStream,
   TraceStream,
-} from './trace_stream';
+} from '../core/trace_stream';
 import {decideTracks} from './track_decider';
 
 type States = 'init' | 'loading_trace' | 'ready';
diff --git a/ui/src/common/color.ts b/ui/src/core/color.ts
similarity index 100%
rename from ui/src/common/color.ts
rename to ui/src/core/color.ts
diff --git a/ui/src/common/color_unittest.ts b/ui/src/core/color_unittest.ts
similarity index 100%
rename from ui/src/common/color_unittest.ts
rename to ui/src/core/color_unittest.ts
diff --git a/ui/src/common/colorizer.ts b/ui/src/core/colorizer.ts
similarity index 98%
rename from ui/src/common/colorizer.ts
rename to ui/src/core/colorizer.ts
index 215079a..3850e1e 100644
--- a/ui/src/common/colorizer.ts
+++ b/ui/src/core/colorizer.ts
@@ -14,8 +14,8 @@
 
 import {hsl} from 'color-convert';
 
-import {hash} from '../common/hash';
-import {featureFlags} from '../core/feature_flags';
+import {hash} from './hash';
+import {featureFlags} from './feature_flags';
 
 import {Color, HSLColor, HSLuvColor} from './color';
 
diff --git a/ui/src/common/colorizer_unittest.ts b/ui/src/core/colorizer_unittest.ts
similarity index 100%
rename from ui/src/common/colorizer_unittest.ts
rename to ui/src/core/colorizer_unittest.ts
diff --git a/ui/src/core/default_plugins.ts b/ui/src/core/default_plugins.ts
index ea6f263..8a03d47 100644
--- a/ui/src/core/default_plugins.ts
+++ b/ui/src/core/default_plugins.ts
@@ -55,5 +55,5 @@
   'perfetto.Screenshots',
   'perfetto.ThreadState',
   'perfetto.VisualisedArgs',
-  'linuxDeviceTracks',
+  'org.kernel.LinuxKernelDevices',
 ];
diff --git a/ui/src/common/hash.ts b/ui/src/core/hash.ts
similarity index 100%
rename from ui/src/common/hash.ts
rename to ui/src/core/hash.ts
diff --git a/ui/src/common/timestamp_format.ts b/ui/src/core/timestamp_format.ts
similarity index 100%
rename from ui/src/common/timestamp_format.ts
rename to ui/src/core/timestamp_format.ts
diff --git a/ui/src/controller/trace_stream.ts b/ui/src/core/trace_stream.ts
similarity index 100%
rename from ui/src/controller/trace_stream.ts
rename to ui/src/core/trace_stream.ts
diff --git a/ui/src/frontend/aggregation_panel.ts b/ui/src/frontend/aggregation_panel.ts
index ff8bfa7..cbd97d9 100644
--- a/ui/src/frontend/aggregation_panel.ts
+++ b/ui/src/frontend/aggregation_panel.ts
@@ -21,7 +21,7 @@
   ThreadStateExtra,
   isEmptyData,
 } from '../common/aggregation_data';
-import {colorForState} from '../common/colorizer';
+import {colorForState} from '../core/colorizer';
 import {translateState} from '../common/thread_state';
 
 import {globals} from './globals';
diff --git a/ui/src/frontend/app.ts b/ui/src/frontend/app.ts
index 6b7b896..0c63e9e 100644
--- a/ui/src/frontend/app.ts
+++ b/ui/src/frontend/app.ts
@@ -28,7 +28,7 @@
   setDurationPrecision,
   setTimestampFormat,
   TimestampFormat,
-} from '../common/timestamp_format';
+} from '../core/timestamp_format';
 import {raf} from '../core/raf_scheduler';
 import {Command} from '../public';
 import {EngineProxy} from '../trace_processor/engine';
diff --git a/ui/src/frontend/base_slice_track.ts b/ui/src/frontend/base_slice_track.ts
index afed340..e4203f0 100644
--- a/ui/src/frontend/base_slice_track.ts
+++ b/ui/src/frontend/base_slice_track.ts
@@ -23,8 +23,8 @@
   drawIncompleteSlice,
   drawTrackHoverTooltip,
 } from '../common/canvas_utils';
-import {colorCompare} from '../common/color';
-import {UNEXPECTED_PINK} from '../common/colorizer';
+import {colorCompare} from '../core/color';
+import {UNEXPECTED_PINK} from '../core/colorizer';
 import {Selection, SelectionKind} from '../common/state';
 import {featureFlags} from '../core/feature_flags';
 import {raf} from '../core/raf_scheduler';
diff --git a/ui/src/frontend/base_slice_track_unittest.ts b/ui/src/frontend/base_slice_track_unittest.ts
index afcca1d..196cc2e 100644
--- a/ui/src/frontend/base_slice_track_unittest.ts
+++ b/ui/src/frontend/base_slice_track_unittest.ts
@@ -13,7 +13,7 @@
 // limitations under the License.
 
 import {Time} from '../base/time';
-import {UNEXPECTED_PINK} from '../common/colorizer';
+import {UNEXPECTED_PINK} from '../core/colorizer';
 import {Slice} from '../public';
 
 import {filterVisibleSlicesForTesting as filterVisibleSlices} from './base_slice_track';
diff --git a/ui/src/frontend/bottom_tab.ts b/ui/src/frontend/bottom_tab.ts
index 7acb31b..4b82001 100644
--- a/ui/src/frontend/bottom_tab.ts
+++ b/ui/src/frontend/bottom_tab.ts
@@ -19,7 +19,7 @@
 import {exists} from '../base/utils';
 import {Actions} from '../common/actions';
 import {traceEvent} from '../common/metatracing';
-import {Registry} from '../common/registry';
+import {Registry} from '../base/registry';
 import {raf} from '../core/raf_scheduler';
 import {EngineProxy} from '../trace_processor/engine';
 
diff --git a/ui/src/frontend/ftrace_panel.ts b/ui/src/frontend/ftrace_panel.ts
index 7766267..c110868 100644
--- a/ui/src/frontend/ftrace_panel.ts
+++ b/ui/src/frontend/ftrace_panel.ts
@@ -16,7 +16,7 @@
 
 import {time, Time} from '../base/time';
 import {Actions} from '../common/actions';
-import {colorForFtrace} from '../common/colorizer';
+import {colorForFtrace} from '../core/colorizer';
 import {StringListPatch} from '../common/state';
 import {DetailsShell} from '../widgets/details_shell';
 import {
diff --git a/ui/src/frontend/globals.ts b/ui/src/frontend/globals.ts
index b4876d7..35cd660 100644
--- a/ui/src/frontend/globals.ts
+++ b/ui/src/frontend/globals.ts
@@ -14,6 +14,7 @@
 
 import {BigintMath} from '../base/bigint_math';
 import {assertExists} from '../base/logging';
+import {createStore, Store} from '../base/store';
 import {duration, Span, Time, time, TimeSpan} from '../base/time';
 import {Actions, DeferredAction} from '../common/actions';
 import {AggregateData} from '../common/aggregation_data';
@@ -39,7 +40,7 @@
   State,
 } from '../common/state';
 import {TabManager} from '../common/tab_registry';
-import {TimestampFormat, timestampFormat} from '../common/timestamp_format';
+import {TimestampFormat, timestampFormat} from '../core/timestamp_format';
 import {TrackManager} from '../common/track_cache';
 import {TABS_V2_FLAG} from '../core/feature_flags';
 import {setPerfHooks} from '../core/perf';
@@ -54,7 +55,6 @@
 import {horizontalScrollToTs} from './scroll_helper';
 import {ServiceWorkerController} from './service_worker_controller';
 import {SliceSqlId} from './sql_types';
-import {createStore, Store} from './store';
 import {PxSpan, TimeScale} from './time_scale';
 
 const INSTANT_FOCUS_DURATION = 1n;
diff --git a/ui/src/frontend/index.ts b/ui/src/frontend/index.ts
index 05c7f0a..468d9af 100644
--- a/ui/src/frontend/index.ts
+++ b/ui/src/frontend/index.ts
@@ -21,6 +21,7 @@
 
 import {defer} from '../base/deferred';
 import {addErrorHandler, reportError} from '../base/logging';
+import {Store} from '../base/store';
 import {Actions, DeferredAction, StateActions} from '../common/actions';
 import {flattenArgs, traceEvent} from '../common/metatracing';
 import {pluginManager} from '../common/plugins';
@@ -50,7 +51,6 @@
 import {RecordPageV2} from './record_page_v2';
 import {Route, Router} from './router';
 import {CheckHttpRpcConnection} from './rpc_http_dialog';
-import {Store} from './store';
 import {TraceInfoPage} from './trace_info_page';
 import {maybeOpenTraceFromRoute} from './trace_url_handler';
 import {ViewerPage} from './viewer_page';
diff --git a/ui/src/frontend/named_slice_track.ts b/ui/src/frontend/named_slice_track.ts
index e2a3717..23e0723 100644
--- a/ui/src/frontend/named_slice_track.ts
+++ b/ui/src/frontend/named_slice_track.ts
@@ -13,7 +13,7 @@
 // limitations under the License.
 
 import {Actions} from '../common/actions';
-import {getColorForSlice} from '../common/colorizer';
+import {getColorForSlice} from '../core/colorizer';
 import {STR_NULL} from '../trace_processor/query_result';
 
 import {
diff --git a/ui/src/frontend/notes_panel.ts b/ui/src/frontend/notes_panel.ts
index 29aff3e..dfc7800 100644
--- a/ui/src/frontend/notes_panel.ts
+++ b/ui/src/frontend/notes_panel.ts
@@ -18,7 +18,7 @@
 import {Icons} from '../base/semantic_icons';
 import {Time} from '../base/time';
 import {Actions} from '../common/actions';
-import {randomColor} from '../common/colorizer';
+import {randomColor} from '../core/colorizer';
 import {AreaNote, Note} from '../common/state';
 import {raf} from '../core/raf_scheduler';
 import {Button} from '../widgets/button';
diff --git a/ui/src/frontend/overview_timeline_panel.ts b/ui/src/frontend/overview_timeline_panel.ts
index d98c249..a47434a 100644
--- a/ui/src/frontend/overview_timeline_panel.ts
+++ b/ui/src/frontend/overview_timeline_panel.ts
@@ -15,8 +15,8 @@
 import m from 'mithril';
 
 import {duration, Span, Time, time} from '../base/time';
-import {colorForCpu} from '../common/colorizer';
-import {timestampFormat, TimestampFormat} from '../common/timestamp_format';
+import {colorForCpu} from '../core/colorizer';
+import {timestampFormat, TimestampFormat} from '../core/timestamp_format';
 
 import {
   OVERVIEW_TIMELINE_NON_VISIBLE_COLOR,
diff --git a/ui/src/frontend/slice_track.ts b/ui/src/frontend/slice_track.ts
index 87c300a..2f9eb40 100644
--- a/ui/src/frontend/slice_track.ts
+++ b/ui/src/frontend/slice_track.ts
@@ -15,7 +15,7 @@
 import {duration, Time, time} from '../base/time';
 import {Actions} from '../common/actions';
 import {cropText, drawIncompleteSlice} from '../common/canvas_utils';
-import {getColorForSlice} from '../common/colorizer';
+import {getColorForSlice} from '../core/colorizer';
 import {HighPrecisionTime} from '../common/high_precision_time';
 import {TrackData} from '../common/track_data';
 import {TimelineFetcher} from '../common/track_helper';
diff --git a/ui/src/frontend/time_axis_panel.ts b/ui/src/frontend/time_axis_panel.ts
index 01f8cc2..d20341f 100644
--- a/ui/src/frontend/time_axis_panel.ts
+++ b/ui/src/frontend/time_axis_panel.ts
@@ -15,7 +15,7 @@
 import m from 'mithril';
 
 import {Time, time, toISODateOnly} from '../base/time';
-import {TimestampFormat, timestampFormat} from '../common/timestamp_format';
+import {TimestampFormat, timestampFormat} from '../core/timestamp_format';
 
 import {TRACK_SHELL_WIDTH} from './css_constants';
 import {globals} from './globals';
diff --git a/ui/src/frontend/time_selection_panel.ts b/ui/src/frontend/time_selection_panel.ts
index c0034b0..0da9a23 100644
--- a/ui/src/frontend/time_selection_panel.ts
+++ b/ui/src/frontend/time_selection_panel.ts
@@ -15,7 +15,7 @@
 import m from 'mithril';
 
 import {duration, Span, time, Time, TimeSpan} from '../base/time';
-import {timestampFormat, TimestampFormat} from '../common/timestamp_format';
+import {timestampFormat, TimestampFormat} from '../core/timestamp_format';
 
 import {
   BACKGROUND_COLOR,
diff --git a/ui/src/frontend/widgets/duration.ts b/ui/src/frontend/widgets/duration.ts
index f07a095..c0357fb 100644
--- a/ui/src/frontend/widgets/duration.ts
+++ b/ui/src/frontend/widgets/duration.ts
@@ -23,7 +23,7 @@
   setDurationPrecision,
   TimestampFormat,
   timestampFormat,
-} from '../../common/timestamp_format';
+} from '../../core/timestamp_format';
 import {raf} from '../../core/raf_scheduler';
 import {Anchor} from '../../widgets/anchor';
 import {MenuDivider, MenuItem, PopupMenu2} from '../../widgets/menu';
diff --git a/ui/src/frontend/widgets/timestamp.ts b/ui/src/frontend/widgets/timestamp.ts
index 0f3f08b..9a89e3c 100644
--- a/ui/src/frontend/widgets/timestamp.ts
+++ b/ui/src/frontend/widgets/timestamp.ts
@@ -22,7 +22,7 @@
   setTimestampFormat,
   TimestampFormat,
   timestampFormat,
-} from '../../common/timestamp_format';
+} from '../../core/timestamp_format';
 import {raf} from '../../core/raf_scheduler';
 import {Anchor} from '../../widgets/anchor';
 import {MenuDivider, MenuItem, PopupMenu2} from '../../widgets/menu';
diff --git a/ui/src/plugins/linuxDeviceTracks/OWNERS b/ui/src/plugins/org.kernel.LinuxKernelDevices/OWNERS
similarity index 100%
rename from ui/src/plugins/linuxDeviceTracks/OWNERS
rename to ui/src/plugins/org.kernel.LinuxKernelDevices/OWNERS
diff --git a/ui/src/plugins/linuxDeviceTracks/index.ts b/ui/src/plugins/org.kernel.LinuxKernelDevices/index.ts
similarity index 89%
rename from ui/src/plugins/linuxDeviceTracks/index.ts
rename to ui/src/plugins/org.kernel.LinuxKernelDevices/index.ts
index 5c5b21c..e9bf9b0 100644
--- a/ui/src/plugins/linuxDeviceTracks/index.ts
+++ b/ui/src/plugins/org.kernel.LinuxKernelDevices/index.ts
@@ -25,7 +25,7 @@
 
 // This plugin renders visualizations of runtime power state transitions for
 // Linux kernel devices (devices managed by Linux drivers).
-class linuxDevices implements Plugin {
+class LinuxKernelDevices implements Plugin {
   onActivate(_: PluginContext): void {}
 
   async onTraceLoad(ctx: PluginContextTrace): Promise<void> {
@@ -57,11 +57,11 @@
 
     for (; it.valid(); it.next()) {
       const trackId = it.trackId;
-      const name = it.name ?? `${trackId}`;
+      const displayName = it.name ?? `${trackId}`;
 
       ctx.registerStaticTrack({
-        uri: `linuxDeviceTracks#${name}`,
-        displayName: name,
+        uri: `org.kernel.LinuxKernelDevices#${displayName}`,
+        displayName,
         trackIds: [trackId],
         kind: ASYNC_SLICE_TRACK_KIND,
         trackFactory: ({trackKey}) => {
@@ -81,6 +81,6 @@
 }
 
 export const plugin: PluginDescriptor = {
-  pluginId: 'linuxDeviceTracks',
-  plugin: linuxDevices,
+  pluginId: 'org.kernel.LinuxKernelDevices',
+  plugin: LinuxKernelDevices,
 };
diff --git a/ui/src/public/index.ts b/ui/src/public/index.ts
index 1e4b984..3ba4c6a 100644
--- a/ui/src/public/index.ts
+++ b/ui/src/public/index.ts
@@ -16,13 +16,12 @@
 
 import {Hotkey} from '../base/hotkeys';
 import {duration, time} from '../base/time';
-import {ColorScheme} from '../common/colorizer';
+import {Migrate, Store} from '../base/store';
+import {ColorScheme} from '../core/colorizer';
 import {Selection} from '../common/state';
 import {PanelSize} from '../frontend/panel';
-import {Migrate, Store} from '../frontend/store';
 import {EngineProxy} from '../trace_processor/engine';
 
-export {createStore, Migrate, Store} from '../frontend/store';
 export {EngineProxy} from '../trace_processor/engine';
 export {
   LONG,
@@ -33,6 +32,7 @@
   STR_NULL,
 } from '../trace_processor/query_result';
 export {BottomTabToSCSAdapter} from './utils';
+export {createStore, Migrate, Store} from '../base/store';
 
 // This is a temporary fix until this is available in the plugin API.
 export {
diff --git a/ui/src/tracks/chrome_scroll_jank/jank_colors.ts b/ui/src/tracks/chrome_scroll_jank/jank_colors.ts
index 22d508e..a18ea03 100644
--- a/ui/src/tracks/chrome_scroll_jank/jank_colors.ts
+++ b/ui/src/tracks/chrome_scroll_jank/jank_colors.ts
@@ -12,7 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-import {HSLColor} from '../../common/color';
-import {makeColorScheme} from '../../common/colorizer';
+import {HSLColor} from '../../core/color';
+import {makeColorScheme} from '../../core/colorizer';
 
 export const JANK_COLOR = makeColorScheme(new HSLColor([343, 100, 43]));
diff --git a/ui/src/tracks/chrome_scroll_jank/scroll_jank_v3_track.ts b/ui/src/tracks/chrome_scroll_jank/scroll_jank_v3_track.ts
index 7fa22ec..fb77174 100644
--- a/ui/src/tracks/chrome_scroll_jank/scroll_jank_v3_track.ts
+++ b/ui/src/tracks/chrome_scroll_jank/scroll_jank_v3_track.ts
@@ -30,7 +30,7 @@
 } from './index';
 import {JANK_COLOR} from './jank_colors';
 import {ScrollJankV3DetailsPanel} from './scroll_jank_v3_details_panel';
-import {getColorForSlice} from '../../common/colorizer';
+import {getColorForSlice} from '../../core/colorizer';
 
 const UNKNOWN_SLICE_NAME = 'Unknown';
 const JANK_SLICE_NAME = ' Jank';
diff --git a/ui/src/tracks/cpu_freq/index.ts b/ui/src/tracks/cpu_freq/index.ts
index 743d7bd..a2327fa 100644
--- a/ui/src/tracks/cpu_freq/index.ts
+++ b/ui/src/tracks/cpu_freq/index.ts
@@ -20,7 +20,7 @@
 import {duration, time, Time} from '../../base/time';
 import {calcCachedBucketSize} from '../../common/cache_utils';
 import {drawTrackHoverTooltip} from '../../common/canvas_utils';
-import {colorForCpu} from '../../common/colorizer';
+import {colorForCpu} from '../../core/colorizer';
 import {TrackData} from '../../common/track_data';
 import {TimelineFetcher} from '../../common/track_helper';
 import {checkerboardExcept} from '../../frontend/checkerboard';
diff --git a/ui/src/tracks/cpu_profile/index.ts b/ui/src/tracks/cpu_profile/index.ts
index e725370..fb7c7c5 100644
--- a/ui/src/tracks/cpu_profile/index.ts
+++ b/ui/src/tracks/cpu_profile/index.ts
@@ -15,7 +15,7 @@
 import {searchSegment} from '../../base/binary_search';
 import {duration, Time, time} from '../../base/time';
 import {Actions} from '../../common/actions';
-import {colorForSample} from '../../common/colorizer';
+import {colorForSample} from '../../core/colorizer';
 import {TrackData} from '../../common/track_data';
 import {TimelineFetcher} from '../../common/track_helper';
 import {CpuProfileDetailsPanel} from '../../frontend/cpu_profile_panel';
diff --git a/ui/src/tracks/cpu_slices/index.ts b/ui/src/tracks/cpu_slices/index.ts
index 6bbec00..647baed 100644
--- a/ui/src/tracks/cpu_slices/index.ts
+++ b/ui/src/tracks/cpu_slices/index.ts
@@ -26,8 +26,8 @@
   drawIncompleteSlice,
   drawTrackHoverTooltip,
 } from '../../common/canvas_utils';
-import {Color} from '../../common/color';
-import {colorForThread} from '../../common/colorizer';
+import {Color} from '../../core/color';
+import {colorForThread} from '../../core/colorizer';
 import {TrackData} from '../../common/track_data';
 import {TimelineFetcher} from '../../common/track_helper';
 import {checkerboardExcept} from '../../frontend/checkerboard';
diff --git a/ui/src/tracks/frames/actual_frames_track_v2.ts b/ui/src/tracks/frames/actual_frames_track_v2.ts
index 1f04718..6ce0e3d 100644
--- a/ui/src/tracks/frames/actual_frames_track_v2.ts
+++ b/ui/src/tracks/frames/actual_frames_track_v2.ts
@@ -12,8 +12,8 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-import {HSLColor} from '../../common/color';
-import {ColorScheme, makeColorScheme} from '../../common/colorizer';
+import {HSLColor} from '../../core/color';
+import {ColorScheme, makeColorScheme} from '../../core/colorizer';
 import {
   NAMED_ROW,
   NamedSliceTrack,
diff --git a/ui/src/tracks/frames/expected_frames_track_v2.ts b/ui/src/tracks/frames/expected_frames_track_v2.ts
index ea730b8..ce602a1 100644
--- a/ui/src/tracks/frames/expected_frames_track_v2.ts
+++ b/ui/src/tracks/frames/expected_frames_track_v2.ts
@@ -12,8 +12,8 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-import {HSLColor} from '../../common/color';
-import {makeColorScheme} from '../../common/colorizer';
+import {HSLColor} from '../../core/color';
+import {makeColorScheme} from '../../core/colorizer';
 import {NamedRow, NamedSliceTrack} from '../../frontend/named_slice_track';
 import {SLICE_LAYOUT_FIT_CONTENT_DEFAULTS} from '../../frontend/slice_layout';
 import {EngineProxy, Slice} from '../../public';
diff --git a/ui/src/tracks/ftrace/index.ts b/ui/src/tracks/ftrace/index.ts
index 530bd47..8be7074 100644
--- a/ui/src/tracks/ftrace/index.ts
+++ b/ui/src/tracks/ftrace/index.ts
@@ -15,7 +15,7 @@
 import m from 'mithril';
 
 import {duration, Time, time} from '../../base/time';
-import {colorForFtrace} from '../../common/colorizer';
+import {colorForFtrace} from '../../core/colorizer';
 import {LIMIT, TrackData} from '../../common/track_data';
 import {TimelineFetcher} from '../../common/track_helper';
 import {checkerboardExcept} from '../../frontend/checkerboard';
diff --git a/ui/src/tracks/process_summary/process_scheduling_track.ts b/ui/src/tracks/process_summary/process_scheduling_track.ts
index b059fb6..0edbf58 100644
--- a/ui/src/tracks/process_summary/process_scheduling_track.ts
+++ b/ui/src/tracks/process_summary/process_scheduling_track.ts
@@ -21,8 +21,8 @@
 import {Actions} from '../../common/actions';
 import {calcCachedBucketSize} from '../../common/cache_utils';
 import {drawTrackHoverTooltip} from '../../common/canvas_utils';
-import {Color} from '../../common/color';
-import {colorForThread} from '../../common/colorizer';
+import {Color} from '../../core/color';
+import {colorForThread} from '../../core/colorizer';
 import {TrackData} from '../../common/track_data';
 import {TimelineFetcher} from '../../common/track_helper';
 import {checkerboardExcept} from '../../frontend/checkerboard';
diff --git a/ui/src/tracks/process_summary/process_summary_track.ts b/ui/src/tracks/process_summary/process_summary_track.ts
index b5b4157..6a8e687 100644
--- a/ui/src/tracks/process_summary/process_summary_track.ts
+++ b/ui/src/tracks/process_summary/process_summary_track.ts
@@ -17,7 +17,7 @@
 import {BigintMath} from '../../base/bigint_math';
 import {assertFalse} from '../../base/logging';
 import {duration, Time, time} from '../../base/time';
-import {colorForTid} from '../../common/colorizer';
+import {colorForTid} from '../../core/colorizer';
 import {LIMIT, TrackData} from '../../common/track_data';
 import {EngineProxy, TimelineFetcher} from '../../common/track_helper';
 import {checkerboardExcept} from '../../frontend/checkerboard';
diff --git a/ui/src/tracks/thread_state/thread_state_v2.ts b/ui/src/tracks/thread_state/thread_state_v2.ts
index d48ae1e..631160d 100644
--- a/ui/src/tracks/thread_state/thread_state_v2.ts
+++ b/ui/src/tracks/thread_state/thread_state_v2.ts
@@ -13,7 +13,7 @@
 // limitations under the License.
 
 import {Actions} from '../../common/actions';
-import {colorForState} from '../../common/colorizer';
+import {colorForState} from '../../core/colorizer';
 import {Selection} from '../../common/state';
 import {translateState} from '../../common/thread_state';
 import {