Merge "ui: cherry-pick aosp/3540100 to canary and stable" into main
diff --git a/src/trace_processor/metrics/sql/android/android_blocking_calls_cuj_per_frame_metric.sql b/src/trace_processor/metrics/sql/android/android_blocking_calls_cuj_per_frame_metric.sql
index dd4ce90..a2322ff 100644
--- a/src/trace_processor/metrics/sql/android/android_blocking_calls_cuj_per_frame_metric.sql
+++ b/src/trace_processor/metrics/sql/android/android_blocking_calls_cuj_per_frame_metric.sql
@@ -44,18 +44,6 @@
     JOIN android_jank_cuj cuj USING (cuj_id)
     JOIN android_jank_cuj_main_thread t USING (cuj_id);
 
-DROP TABLE IF EXISTS _android_frames_layers_with_end_ts;
-CREATE PERFETTO TABLE _android_frames_layers_with_end_ts AS
-    SELECT
-        ts,
-        dur,
-        frame_id,
-        layer_id,
-        upid,
-        ui_thread_utid,
-        (ts + dur) AS ts_end
-    FROM android_frames_layers;
-
 -- While calculating the metric, there are two possibilities for a blocking call:
 -- 1. Blocking call is completely within a frame boundary.
 -- 2. Blocking call crosses the frame boundary into the next frame.
@@ -77,7 +65,7 @@
     frame.frame_id,
     frame.layer_id
 FROM _android_critical_blocking_calls bc
-JOIN _android_frames_layers_with_end_ts frame
+JOIN android_frames_layers frame
 ON bc.utid = frame.ui_thread_utid
    -- The following condition to accommodate blocking call crossing frame boundary. The blocking
    -- call starts in a frame and ends in a frame. It can either be the same frame or a different
@@ -102,7 +90,7 @@
         cuj.ts_end - frame.ts,
         frame.ts_end - cuj.ts
     ) AS dur
-FROM _android_frames_layers_with_end_ts frame
+FROM android_frames_layers frame
 JOIN android_cujs cuj
 ON frame.upid = cuj.upid
    AND frame.layer_id = cuj.layer_id
diff --git a/src/trace_processor/perfetto_sql/stdlib/android/frames/timeline.sql b/src/trace_processor/perfetto_sql/stdlib/android/frames/timeline.sql
index c442ba6..dca9fb0 100644
--- a/src/trace_processor/perfetto_sql/stdlib/android/frames/timeline.sql
+++ b/src/trace_processor/perfetto_sql/stdlib/android/frames/timeline.sql
@@ -140,6 +140,9 @@
   -- `actual_frame_timeline_slice` or, if not present the time between the
   -- `ts` and the end of the final `DrawFrame`.
   dur DURATION,
+  -- End timestamp of the frame. End of the frame as defined by the sum of start timestamp and
+  -- duration of the frame.
+  ts_end TIMESTAMP,
   -- `slice.id` of "Choreographer#doFrame" slice.
   do_frame_id JOINID(slice.id),
   -- `slice.id` of "DrawFrame" slice. For now, we only support the first
@@ -229,6 +232,9 @@
   frame_id,
   ts,
   dur,
+  (
+    ts + dur
+  ) AS ts_end,
   do_frame_id,
   draw_frame_id,
   actual_frame_timeline_id,
diff --git a/src/trace_processor/perfetto_sql/stdlib/android/memory/heap_graph/class_tree.sql b/src/trace_processor/perfetto_sql/stdlib/android/memory/heap_graph/class_tree.sql
index 071fc52..7957423 100644
--- a/src/trace_processor/perfetto_sql/stdlib/android/memory/heap_graph/class_tree.sql
+++ b/src/trace_processor/perfetto_sql/stdlib/android/memory/heap_graph/class_tree.sql
@@ -112,3 +112,92 @@
   ON dst.id = r.owned_id
 JOIN heap_graph_class AS c
   ON dst.type_id = c.id;
+
+CREATE PERFETTO MACRO _heap_graph_retained_object_count_agg(
+    path_hash_value Expr
+)
+RETURNS TableOrSubquery AS
+(
+  SELECT
+    c.name AS class_name,
+    o.heap_type,
+    o.root_type,
+    o.reachable,
+    sum(o.self_size) AS total_size,
+    sum(o.native_size) AS total_native_size,
+    count() AS count
+  FROM graph_reachable_bfs
+    !(
+      (
+        SELECT
+          IFNULL(parent_id, id) AS source_node_id,
+          IFNULL(id, parent_id) AS dest_node_id
+        FROM _heap_graph_object_min_depth_tree
+      ),
+      (
+        SELECT o.id AS node_id
+        FROM _heap_graph_path_hashes h
+        JOIN heap_graph_object o
+          ON h.id = o.id
+        JOIN heap_graph_class c
+          ON o.type_id = c.id
+        WHERE path_hash IN ($path_hash_value)
+      )) AS b
+  JOIN heap_graph_object AS o
+    ON b.node_id = o.id
+  JOIN heap_graph_class AS c
+    ON o.type_id = c.id
+  GROUP BY
+    class_name,
+    heap_type,
+    root_type,
+    reachable
+  ORDER BY
+    count DESC
+);
+
+CREATE PERFETTO MACRO _heap_graph_retaining_object_count_agg(
+    path_hash_value Expr
+)
+RETURNS TableOrSubquery AS
+(
+  SELECT
+    c.name AS class_name,
+    o.heap_type,
+    o.root_type,
+    o.reachable,
+    sum(o.self_size) AS total_size,
+    sum(o.native_size) AS total_native_size,
+    count() AS count
+  FROM graph_reachable_bfs
+    !(
+      (
+        SELECT
+          IFNULL(id, parent_id) AS source_node_id,
+          IFNULL(parent_id, id) AS dest_node_id
+        FROM _heap_graph_object_min_depth_tree
+      ),
+      (
+        SELECT o.id AS node_id
+        FROM _heap_graph_path_hashes h
+        JOIN heap_graph_object o
+          ON h.id = o.id
+        JOIN heap_graph_class c
+          ON o.type_id = c.id
+        WHERE path_hash IN ($path_hash_value)
+      )) AS b
+  JOIN _heap_graph_path_hashes AS h
+    ON h.id = o.id
+  JOIN heap_graph_object AS o
+    ON b.node_id = o.id
+  JOIN heap_graph_class AS c
+    ON o.type_id = c.id
+  GROUP BY
+    path_hash,
+    class_name,
+    heap_type,
+    root_type,
+    reachable
+  ORDER BY
+    count DESC
+);
diff --git a/src/tracing/core/in_process_shared_memory.h b/src/tracing/core/in_process_shared_memory.h
index 9ac692f..2a8382f 100644
--- a/src/tracing/core/in_process_shared_memory.h
+++ b/src/tracing/core/in_process_shared_memory.h
@@ -29,6 +29,7 @@
 class InProcessSharedMemory : public SharedMemory {
  public:
   static constexpr size_t kDefaultSize = 128 * 1024;
+  static constexpr size_t kShmemEmulationSize = 1024 * 1024;
 
   // Default ctor used for intra-process shmem between a producer and the
   // service.
diff --git a/src/tracing/ipc/producer/producer_ipc_client_impl.cc b/src/tracing/ipc/producer/producer_ipc_client_impl.cc
index db1297c..158da16 100644
--- a/src/tracing/ipc/producer/producer_ipc_client_impl.cc
+++ b/src/tracing/ipc/producer/producer_ipc_client_impl.cc
@@ -359,10 +359,8 @@
       PERFETTO_CHECK(!ipc_shared_memory);
       // Need to create an emulated shmem buffer when the transport deosn't
       // support it.
-      // TODO(chinglinyu): Let the tracing service decide on the shmem size and
-      // propagate the size in InitializeConnectionResponse.
       ipc_shared_memory = InProcessSharedMemory::Create(
-          /*size=*/InProcessSharedMemory::kDefaultSize);
+          /*size=*/InProcessSharedMemory::kShmemEmulationSize);
     }
     if (ipc_shared_memory) {
       auto shmem_mode = use_shmem_emulation_
diff --git a/test/trace_processor/diff_tests/stdlib/android/frames_tests.py b/test/trace_processor/diff_tests/stdlib/android/frames_tests.py
index a3dbd4e..9e68e20 100644
--- a/test/trace_processor/diff_tests/stdlib/android/frames_tests.py
+++ b/test/trace_processor/diff_tests/stdlib/android/frames_tests.py
@@ -128,27 +128,27 @@
           SELECT * FROM android_frames_layers;
           """,
           out=Csv("""
-          "frame_id","ts","dur","do_frame_id","draw_frame_id","actual_frame_timeline_id","expected_frame_timeline_id","render_thread_utid","ui_thread_utid","layer_id","layer_name","upid","process_name"
-          10,0,16000000,2,8,1,0,4,2,0,"TX - NotificationShade#0",2,"com.android.systemui"
-          20,8000000,28000000,15,16,12,11,4,2,0,"TX - NotificationShade#0",2,"com.android.systemui"
-          30,30000000,25000000,22,23,21,20,4,2,0,"TX - NotificationShade#0",2,"com.android.systemui"
-          40,40000000,40000000,35,41,37,36,4,2,0,"TX - NotificationShade#0",2,"com.android.systemui"
-          60,70000000,10000000,46,50,48,47,4,2,0,"TX - NotificationShade#0",2,"com.android.systemui"
-          60,70000000,20000000,46,50,49,47,4,2,0,"TX - NotificationShade#0",2,"com.android.systemui"
-          90,100000000,23000000,55,57,54,53,4,2,0,"TX - NotificationShade#0",2,"com.android.systemui"
-          90,100000000,23000000,55,60,54,53,4,2,0,"TX - NotificationShade#0",2,"com.android.systemui"
-          100,200000000,22000000,63,66,65,64,4,2,0,"TX - NotificationShade#0",2,"com.android.systemui"
-          100,200000000,22000000,63,69,65,64,4,2,0,"TX - NotificationShade#0",2,"com.android.systemui"
-          110,300000000,61000000,73,74,71,70,4,2,0,"TX - NotificationShade#0",2,"com.android.systemui"
-          110,300000000,80000000,73,74,72,70,4,2,1,"TX - JankyLayer#1",2,"com.android.systemui"
-          120,400000000,61000000,79,80,78,77,4,2,0,"TX - NotificationShade#0",2,"com.android.systemui"
-          130,500000000,2000000,87,89,85,84,4,2,0,"TX - NotificationShade#0",2,"com.android.systemui"
-          130,550000000,6000000,87,89,88,84,4,2,0,"TX - NotificationShade#0",2,"com.android.systemui"
-          140,608600000,17000000,93,95,94,91,4,2,0,"TX - NotificationShade#0",2,"com.android.systemui"
-          145,650000000,20000000,99,100,98,97,4,2,0,"TX - NotificationShade#0",2,"com.android.systemui"
-          150,700500000,14500000,102,105,104,103,4,2,0,"TX - NotificationShade#0",2,"com.android.systemui"
-          160,800000000,2000000,108,109,"[NULL]",107,4,2,"[NULL]","[NULL]",2,"com.android.systemui"
-          1000,1100000000,500000000,140,146,138,137,4,2,0,"TX - NotificationShade#0",2,"com.android.systemui"
+          "frame_id","ts","dur","ts_end","do_frame_id","draw_frame_id","actual_frame_timeline_id","expected_frame_timeline_id","render_thread_utid","ui_thread_utid","layer_id","layer_name","upid","process_name"
+          10,0,16000000,16000000,2,8,1,0,4,2,0,"TX - NotificationShade#0",2,"com.android.systemui"
+          20,8000000,28000000,36000000,15,16,12,11,4,2,0,"TX - NotificationShade#0",2,"com.android.systemui"
+          30,30000000,25000000,55000000,22,23,21,20,4,2,0,"TX - NotificationShade#0",2,"com.android.systemui"
+          40,40000000,40000000,80000000,35,41,37,36,4,2,0,"TX - NotificationShade#0",2,"com.android.systemui"
+          60,70000000,10000000,80000000,46,50,48,47,4,2,0,"TX - NotificationShade#0",2,"com.android.systemui"
+          60,70000000,20000000,90000000,46,50,49,47,4,2,0,"TX - NotificationShade#0",2,"com.android.systemui"
+          90,100000000,23000000,123000000,55,57,54,53,4,2,0,"TX - NotificationShade#0",2,"com.android.systemui"
+          90,100000000,23000000,123000000,55,60,54,53,4,2,0,"TX - NotificationShade#0",2,"com.android.systemui"
+          100,200000000,22000000,222000000,63,66,65,64,4,2,0,"TX - NotificationShade#0",2,"com.android.systemui"
+          100,200000000,22000000,222000000,63,69,65,64,4,2,0,"TX - NotificationShade#0",2,"com.android.systemui"
+          110,300000000,61000000,361000000,73,74,71,70,4,2,0,"TX - NotificationShade#0",2,"com.android.systemui"
+          110,300000000,80000000,380000000,73,74,72,70,4,2,1,"TX - JankyLayer#1",2,"com.android.systemui"
+          120,400000000,61000000,461000000,79,80,78,77,4,2,0,"TX - NotificationShade#0",2,"com.android.systemui"
+          130,500000000,2000000,502000000,87,89,85,84,4,2,0,"TX - NotificationShade#0",2,"com.android.systemui"
+          130,550000000,6000000,556000000,87,89,88,84,4,2,0,"TX - NotificationShade#0",2,"com.android.systemui"
+          140,608600000,17000000,625600000,93,95,94,91,4,2,0,"TX - NotificationShade#0",2,"com.android.systemui"
+          145,650000000,20000000,670000000,99,100,98,97,4,2,0,"TX - NotificationShade#0",2,"com.android.systemui"
+          150,700500000,14500000,715000000,102,105,104,103,4,2,0,"TX - NotificationShade#0",2,"com.android.systemui"
+          160,800000000,2000000,802000000,108,109,"[NULL]",107,4,2,"[NULL]","[NULL]",2,"com.android.systemui"
+          1000,1100000000,500000000,1600000000,140,146,138,137,4,2,0,"TX - NotificationShade#0",2,"com.android.systemui"
           """))
 
   def test_android_first_frame_after(self):
diff --git a/ui/src/plugins/dev.perfetto.HeapProfile/heap_profile_details_panel.ts b/ui/src/plugins/dev.perfetto.HeapProfile/heap_profile_details_panel.ts
index ca5ea10..858a254 100644
--- a/ui/src/plugins/dev.perfetto.HeapProfile/heap_profile_details_panel.ts
+++ b/ui/src/plugins/dev.perfetto.HeapProfile/heap_profile_details_panel.ts
@@ -16,6 +16,7 @@
 
 import {assertExists, assertFalse} from '../../base/logging';
 import {extensions} from '../../components/extensions';
+import {runQuery} from '../../components/query_table/queries';
 import {time} from '../../base/time';
 import {
   QueryFlamegraph,
@@ -233,12 +234,12 @@
     case ProfileType.JAVA_HEAP_SAMPLES:
       return flamegraphMetricsForHeapProfile(ts, upid, [
         {
-          name: 'Unreleased Allocation Size',
+          name: 'Total Allocation Size',
           unit: 'B',
           columnName: 'self_size',
         },
         {
-          name: 'Unreleased Allocation Count',
+          name: 'Total Allocation Count',
           unit: '',
           columnName: 'self_count',
         },
@@ -246,12 +247,12 @@
     case ProfileType.MIXED_HEAP_PROFILE:
       return flamegraphMetricsForHeapProfile(ts, upid, [
         {
-          name: 'Unreleased Allocation Size (malloc + java)',
+          name: 'Allocation Size (malloc + java)',
           unit: 'B',
           columnName: 'self_size',
         },
         {
-          name: 'Unreleased Allocation Count (malloc + java)',
+          name: 'Allocation Count (malloc + java)',
           unit: '',
           columnName: 'self_count',
         },
@@ -519,6 +520,36 @@
   };
 }
 
+function getHeapGraphRetainingObjectCountsView(): SqlTableDescription {
+  return {
+    name: `_heap_graph_retaining_object_counts`,
+    columns: [
+      new StandardColumn('class_name'),
+      new StandardColumn('count'),
+      new StandardColumn('total_size'),
+      new StandardColumn('total_native_size'),
+      new StandardColumn('heap_type'),
+      new StandardColumn('root_type'),
+      new StandardColumn('reachable'),
+    ],
+  };
+}
+
+function getHeapGraphRetainedObjectCountsView(): SqlTableDescription {
+  return {
+    name: `_heap_graph_retained_object_counts`,
+    columns: [
+      new StandardColumn('class_name'),
+      new StandardColumn('count'),
+      new StandardColumn('total_size'),
+      new StandardColumn('total_native_size'),
+      new StandardColumn('heap_type'),
+      new StandardColumn('root_type'),
+      new StandardColumn('reachable'),
+    ],
+  };
+}
+
 function getHeapGraphOptionalActions(
   trace: Trace,
 ): ReadonlyArray<FlamegraphOptionalAction> {
@@ -574,5 +605,41 @@
         }
       },
     },
+    {
+      name: 'Retained objects',
+      execute: async (kv: ReadonlyMap<string, string>) => {
+        const value = kv.get('path_hash_stable');
+        if (value !== undefined) {
+          const statement = `
+              CREATE OR REPLACE PERFETTO VIEW _heap_graph_retained_object_counts AS
+              SELECT * FROM _heap_graph_retained_object_count_agg!(${value});
+          `;
+
+          // Create view to be returned
+          await runQuery(statement, trace.engine);
+          extensions.addLegacySqlTableTab(trace, {
+            table: getHeapGraphRetainedObjectCountsView(),
+          });
+        }
+      },
+    },
+    {
+      name: 'Retaining objects',
+      execute: async (kv: ReadonlyMap<string, string>) => {
+        const value = kv.get('path_hash_stable');
+        if (value !== undefined) {
+          const statement = `
+              CREATE OR REPLACE PERFETTO VIEW _heap_graph_retaining_object_counts AS
+              SELECT * FROM _heap_graph_retaining_object_count_agg!(${value});
+          `;
+
+          // Create view to be returned
+          await runQuery(statement, trace.engine);
+          extensions.addLegacySqlTableTab(trace, {
+            table: getHeapGraphRetainingObjectCountsView(),
+          });
+        }
+      },
+    },
   ];
 }