Merge "Revert "Add support for disallowing concurrent sessions""
diff --git a/Android.bp b/Android.bp
index 6043633..117f572 100644
--- a/Android.bp
+++ b/Android.bp
@@ -12044,14 +12044,6 @@
     data: [
         ":perfetto-trace-processor-python-data",
     ],
-    version: {
-        py2: {
-            enabled: false,
-        },
-        py3: {
-            enabled: true,
-        },
-    },
     libs: [
         "libprotobuf-python",
     ],
diff --git a/Android.bp.extras b/Android.bp.extras
index 2de83f1..f1251b4 100644
--- a/Android.bp.extras
+++ b/Android.bp.extras
@@ -107,14 +107,6 @@
     data: [
         ":perfetto-trace-processor-python-data",
     ],
-    version: {
-        py2: {
-            enabled: false,
-        },
-        py3: {
-            enabled: true,
-        },
-    },
     libs: [
         "libprotobuf-python",
     ],
diff --git a/docs/analysis/pivot-tables.md b/docs/analysis/pivot-tables.md
new file mode 100644
index 0000000..4add1ba
--- /dev/null
+++ b/docs/analysis/pivot-tables.md
@@ -0,0 +1,38 @@
+# Pivot Tables
+
+Pivot Tables are a way to summarize and aggregate information about selected
+slices in a configurable way. It is available in canary and autopush channels by
+default, and can be enabled in stable by toggling a corresponding flag
+(Support > Flags > Pivot tables V2).
+
+To create a pivot table, you need to select a timeline area that contains
+slices. The table will then show an aggregation of the selected slices.
+
+## Conceptual model
+
+Pivot tables have two types of columns: pivots and aggregations. Conceptually,
+the UI requests all the data from columns of both types and then computes
+aggregate values for aggregation columns for every distinct tuple of pivot
+column values.
+
+Pivots are hierarchical, and the aggregate values are also computed for all the
+prefixes of pivot column values. For example, if you select process name,
+category, and event name (in that order) as pivots and have duration sum as the
+only aggregation columns, the following aggregate values will be computed:
+
+*   Total duration for each process
+*   Total duration for each process and category
+*   Total duration for each process, category, and event name
+
+The table rows are appropriately nested in the UI, from more general to more
+specific. Portions of the table can be collapsed and expanded.
+
+## Working with pivot table
+
+Pivot tables can be configured using dropdown menus in the table header cells.
+These can be used to:
+
+*   Add and remove pivots
+*   Add and remove aggregations
+*   Change aggregation functions
+*   Sort by aggregation columns
diff --git a/docs/design-docs/pivot-tables.md b/docs/design-docs/pivot-tables.md
deleted file mode 100644
index ddc340c..0000000
--- a/docs/design-docs/pivot-tables.md
+++ /dev/null
@@ -1,206 +0,0 @@
-# Pivot Tables
-
-_**Project Plan**: [Perfetto: Pivot tables for slices](https://docs.google.com/document/d/1RuEGQKLgOA8YWjZJHD6CTA3ghRRg6o5Phg3_rFCJEDE/)_  
-_**How to Use**: [Pivot Table Usage](/docs/visualization/perfetto-ui#pivot-tables)_  
-_**For Googlers**: [Perfetto: Pivot Table Use Cases](https://docs.google.com/document/d/1_iR-JjD7m19Q9GQtMk1_5NLSYXFicB_gg4S9D-6Q8lU/)_  
-
-## Objective
-Pivot tables give a simplified aggregated view of more complex data. They are
-made up of a number of pivots and aggregations that are grouped around these
-pivots. You can add more columns/aggregations and drag and drop the columns to
-explore the underlying data.
-
-## Motivation
-Pivot tables are useful in debugging hangs, stalls, and digging into traces
-which usually have too much data to clearly see the problems.
-The pivot table allows users to create custom tables to view specific
-information about traces in a summarized and less complex way.
-
-## Main Components
-
-![Pivot table design](/docs/images/pivot-tables/pivot-table-design.png)
-
-### Details Panel (Frontend)
-The [DetailsPanel](https://cs.android.com/android/_/android/platform/external/perfetto/+/0ae7c36fd528824ee9fdea6cfd4494e9f05183b5:ui/src/frontend/details_panel.ts)
-searches for active PivotTables to display on screen. It also syncs the
-PivotTableHelper with data from the State. (PivotTableHelper only syncs when the
-PivotTableEditor modal is not open).
-
-
-### Pivot Table (Frontend)
-The [PivotTable](https://cs.android.com/android/_/android/platform/external/perfetto/+/0ae7c36fd528824ee9fdea6cfd4494e9f05183b5:ui/src/frontend/pivot_table.ts) builds
-the pivot table tab and the table. It also handles user requests (like opening
-the pivot table editor, drag and drop columns, expand, etc) by calling the
-PivotTableHelper and updating the table.
-
-
-### PivotTableEditor (Frontend)
-The [PivotTableEditor](https://cs.android.com/android/_/android/platform/external/perfetto/+/0ae7c36fd528824ee9fdea6cfd4494e9f05183b5:ui/src/frontend/pivot_table_editor.ts)
-consists of ColumnPicker and ColumnDisplay classes.
-ColumnPicker allows the user to select column type, name and aggregation. Edits
-made through the ColumnPicker are saved temporarily in the PivotTableHelper
-without updating the state.
-ColumnDisplay displays the selected column from the ColumnPicker, it also allows
-users to manipulate the columns after selection (like delete, reorder, change
-the default sorting, etc...).
-In this stage the user is able to query the selected columns and update the
-table or discard the changes made and the PivotTableHelper will resync with the
-data in state.
-
-
-### PivotTableHelper (Frontend)
-The [PivotTableHelper](https://cs.android.com/android/_/android/platform/external/perfetto/+/0ae7c36fd528824ee9fdea6cfd4494e9f05183b5:ui/src/frontend/pivot_table_helper.ts)
-is created by every PivotTableController for every PivotTableId. It stores a
-copy of the selectedPivots and selectedAggregations from state. It also holds
-the logic for manipulating the data locally, which are used by the PivotTable
-and PivotTableEditor.
-It also replaces the data in the State with the changes upon request.
-The PivotTableHelper also checks for special “stack” columns, called stackPivots
-(`name (stack)` for [slice table](/docs/analysis/sql-tables.autogen#slice) is
-currently the only special column), as it sets the column attributes which are
-then used to identify them by other components.
-
-
-### State (Common)
-[PivotTableState](https://cs.android.com/android/_/android/platform/external/perfetto/+/0ae7c36fd528824ee9fdea6cfd4494e9f05183b5:ui/src/common/state.ts;l=303) holds the
-information that needs to be transferred to and from the frontend and the
-controller for each pivot table instance (PivotTableId). It also includes the
-global PivotTableConfigs (like the availableColumns and availableAggregations).
-
-
-### PivotTableController (Controller)
-A new [PivotTableController](https://cs.android.com/android/_/android/platform/external/perfetto/+/0ae7c36fd528824ee9fdea6cfd4494e9f05183b5:ui/src/controller/pivot_table_controller.ts)
-is created for every PivotTableId.
-The PivotTableController handles the setup of the pivot table once added, it
-queries for the columns for all tables and sets the PivotTableConfig. It also
-creates and initializes a PivotTableHelper for every PivotTableId and publishes
-it to the frontend.
-Additionally, the PivotTableController handles the collection and the
-computation of all data needed by the PivotTableQueryGenerator.
-It constantly checks if a request has been set in the PivotTableState and acts
-on it if so.
-It decides what columns to query, what whereFilters and tables to include and
-how to reformat the query result into a PivotTableQueryResponse based on the
-request type.
-
-There are four types of requests implemented in the controller:
-
-**_QUERY:_**
-Queries the first pivot of the selectedPivots and all the aggregations,
-including any global or table-wide whereFilters (Like the start and end
-timestamp and selected track_ids that are set by the pivot table generated
-through area selection).
-It also adds a whereFilter (Filter in the where clause of the query) if the
-pivot is a stackPivot to restrict the result to the top level slices only, since
-descendants can be generated by expanding the cell and issuing the DESCENDANTS
-request, and returns the result as a PivotTableQueryResponse.
-
-![Pivot table query](/docs/images/pivot-tables/pivot-table-query.png)
-
-Returned PivotTableQueryResponse:
-
-```typescript
-pivotTableQueryResponse = {
-  columns: ['slice type', 'slice category', 'slice name'];
-  rows: [
-    {
-      row: 'internal_slice',
-      expandableColumns: ['slice type'],
-      expandedRows = [],
-    }, {
-      row: 'thread_slice',
-      expandableColumns: ['slice type'],
-      expandedRows = [],
-    };
-  ]
-}
-```
-
-**_EXPAND:_**
-The [PivotTableBody](https://cs.android.com/android/_/android/platform/external/perfetto/+/a9118d769009349da7f264abb392f4207e66602b:ui/src/frontend/pivot_table.ts;l=235;drc=0bc8ff07f372a58ca4d0399d88567a66ef5b591b) generates the nested structure by
-recursively displaying the rows and checking if the row contains any expanded
-rows with the isExpanded flag set to true. As it goes through the nested rows,
-it passes the row index that it's about to expand, along with the column it's
-expanding for till it reaches a [PivotTableRow](https://cs.android.com/android/_/android/platform/external/perfetto/+/0ae7c36fd528824ee9fdea6cfd4494e9f05183b5:ui/src/frontend/pivot_table.ts;l=192).
-The PivotTableRow creates a cell for each column. If the cell is at a column
-that can be expanded, it is created as an [ExpandableCell](https://cs.android.com/android/_/android/platform/external/perfetto/+/0ae7c36fd528824ee9fdea6cfd4494e9f05183b5:ui/src/frontend/pivot_table.ts;l=121).
-When an 'EXPAND' request is issued on an ExpandableCell, it sets the
-requestedAction in the PivotTableState and provides it with the SubQueryAttrs.
-
-Given a columnIdx, value, and an array of rowIndicies (SubQueryAttrs) from
-the requestedAction in the PivotTableState, it finds the exact row that called
-this request from the main PivotTableQueryResponse, and finds the next pivot
-to query. It then generates the query similarly to the ‘QUERY’ request, but
-includes the whereFilter of the previous column (column name = column value).
-The rows of the query result are then nested into the caller row’s expandedRows,
-to build a tree view structure while expanding.
-
-![Pivot table expanded cell](/docs/images/pivot-tables/pivot-table-expanded-cell.png)
-
-Passed value:
-
-```typescript
-subQueryAttrs = {
-  rowIndices: [0, 3],
-  columnIdx: 1,
-  value: 'blink,benchmark',
-  expandedRowColumns: ['slice category'],
-}
-```
-
-Returned expanded rows:
-
-```typescript
-rows = [
-  {
-    row: 'LocalFrameView::RunAccessibilityLifecyclePhase',
-    expandableColumns: [],
-    expandedRows: []
-  },
-  {
-    row: 'LocalFrameView::RunCompositingInputsLifecyclePhase',
-    expandableColumns: [],
-    expandedRows: []
-  },
-  {
-    row: 'LocalFrameView::RunStyleAndLayoutLifecyclePhases',
-    expandableColumns: [],
-    expandedRows: []
-  },
-  ...
-]
-```
-
-The returned rows are saved inside the caller row expandedRows map.
-
-```typescript
-rows = {
-  row: 'blink,benchmark',
-  expandableColumns: ['slice category'],
-  expandedRows: [
-    'slice name' => {
-        isExpanded: true,
-        rows
-      }
-  ]
-}
-```
-
-**_UNEXPAND:_**
-Sets the caller row’s isExpanded flag to false, to hide it from the display but
-also keeping its expandedRows saved so as to not have to query them again if
-requested.
-
-**_DESCENDANTS:_**
-Should only be called for stackPivots, generates a query containing the
-stackPivot and the next pivot, if it exists, and all the aggregations. It also
-requests the PivotTableQueryGenerator to order by depth first, which is then
-used to refactor the resulting rows into the PivotTableQueryResponse tree view
-structure.
-The returned format is similar to the EXPAND request.
-
-### PivotTableQueryGenerator (Common)
-[PivotTableQueryGenerator](https://cs.android.com/android/_/android/platform/external/perfetto/+/0ae7c36fd528824ee9fdea6cfd4494e9f05183b5:ui/src/common/pivot_table_query_generator.ts)
-generates an sql query based on the given data, along with any hidden columns
-that may need to be added. It also creates an alias for each pivot and
-aggregation that is used to identify the resulting cells in the rows.
diff --git a/docs/toc.md b/docs/toc.md
index e0d6755..be1de00 100644
--- a/docs/toc.md
+++ b/docs/toc.md
@@ -42,6 +42,7 @@
   * [Common queries](analysis/common-queries.md)
   * [SQL tables](analysis/sql-tables.autogen)
   * [Stats table](analysis/sql-stats.autogen)
+  * [Pivot tables](analysis/pivot-tables.md)
 
 * [Trace visualization](#)
   * [Perfetto UI](visualization/perfetto-ui.md)
@@ -79,7 +80,6 @@
     * [Heapprofd sampling](design-docs/heapprofd-sampling.md)
     * [Life of a tracing session](design-docs/life-of-a-tracing-session.md)
     * [Perfetto CI](design-docs/continuous-integration.md)
-    * [Pivot tables](design-docs/pivot-tables.md)
     * [ProtoZero](design-docs/protozero.md)
     * [Security model](design-docs/security-model.md)
     * [Statsd Checkpoint Atoms](design-docs/checkpoint-atoms.md)
diff --git a/protos/third_party/chromium/chrome_track_event.proto b/protos/third_party/chromium/chrome_track_event.proto
index 23c6969..3d21d2a 100644
--- a/protos/third_party/chromium/chrome_track_event.proto
+++ b/protos/third_party/chromium/chrome_track_event.proto
@@ -1,4 +1,4 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
+// Copyright 2020 The Chromium Authors
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -203,6 +203,7 @@
 
   optional bool has_valid_header = 8;
   optional bool has_valid_schema = 9;
+  optional string error_message = 10;
 }
 
 message ChromeWebAppBadNavigate {
@@ -812,9 +813,65 @@
   optional int64 dur_ms = 2;
 }
 
+message SequenceManagerTask {
+  enum Priority {
+    UNKNOWN = 0;
+    CONTROL_PRIORITY = 1;
+    HIGHEST_PRIORITY = 2;
+    VERY_HIGH_PRIORITY = 3;
+    HIGH_PRIORITY = 4;
+    NORMAL_PRIORITY = 5;
+    LOW_PRIORITY = 6;
+    BEST_EFFORT_PRIORITY = 7;
+  }
+
+  optional Priority priority = 1;
+}
+
+message AndroidToolbar {
+  enum BlockCaptureReason {
+    BLOCKED_UNKNOWN = 0;
+    BLOCKED_TOOLBAR_OR_RESULT_NULL = 1;
+    BLOCKED_VIEW_NOT_DIRTY = 2;
+    BLOCKED_SNAPSHOT_SAME = 3;
+    BLOCKED_URL_BAR_HAS_FOCUS = 4;
+    BLOCKED_URL_BAR_FOCUS_IN_PROGRESS = 5;
+    BLOCKED_OPTIONAL_BUTTON_ANIMATION_IN_PROGRESS = 6;
+    BLOCKED_STATUS_ICON_ANIMATION_IN_PROGRESS = 7;
+    BLOCKED_SCROLL_ABLATION = 8;
+    BLOCKED_BROWSER_CONTROLS_LOCKED = 9;
+    // TODO(https://crbug.com/1324678): SCROLL_IN_PROGRESS.
+    // TODO(https://crbug.com/1324678): NATIVE_PAGE.
+  }
+  enum AllowCaptureReason {
+    ALLOWED_UNKNOWN = 0;
+    ALLOWED_FORCE_CAPTURE = 1;
+    ALLOWED_SNAPSHOT_DIFFERENCE = 2;
+  }
+  enum SnapshotDifference {
+    DIFF_NONE = 0;
+    DIFF_NULL = 1;
+    DIFF_TINT = 2;
+    DIFF_TAB_COUNT = 3;
+    DIFF_OPTIONAL_BUTTON_DATA = 4;
+    DIFF_VISUAL_STATE = 5;
+    DIFF_SECURITY_ICON = 6;
+    DIFF_SHOWING_UPDATE_BADGE = 7;
+    DIFF_PAINT_PREVIEW = 8;
+    DIFF_PROGRESS = 9;
+    DIFF_LOCATION_BAR_WIDTH = 10;
+    DIFF_URL_TEXT = 11;
+    DIFF_HOME_BUTTON_COLOR = 12;
+  }
+
+  optional BlockCaptureReason block_capture_reason = 1;
+  optional AllowCaptureReason allow_capture_reason = 2;
+  optional SnapshotDifference snapshot_difference = 3;
+}
+
 message ChromeTrackEvent {
   // Extension range for Chrome: 1000-1999
-  // Next ID: 1040
+  // Next ID: 1042
   extend TrackEvent {
     optional ChromeAppState chrome_app_state = 1000;
 
@@ -900,5 +957,9 @@
     optional AndroidIPC android_ipc = 1038;
 
     optional ChromeSqlDiagnostics sql_diagnostics = 1039;
+
+    optional SequenceManagerTask sequence_manager_task = 1040;
+
+    optional AndroidToolbar android_toolbar = 1041;
   }
 }
diff --git a/protos/third_party/chromium/sources.gni b/protos/third_party/chromium/sources.gni
index cef4a8e..115ec4b 100644
--- a/protos/third_party/chromium/sources.gni
+++ b/protos/third_party/chromium/sources.gni
@@ -1,4 +1,4 @@
-# Copyright (c) 2020 The Chromium Authors. All rights reserved.
+# Copyright 2020 The Chromium Authors
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
diff --git a/ui/src/frontend/pivot_table_redux.ts b/ui/src/frontend/pivot_table_redux.ts
index bfe5cdb..662246b 100644
--- a/ui/src/frontend/pivot_table_redux.ts
+++ b/ui/src/frontend/pivot_table_redux.ts
@@ -74,7 +74,7 @@
 function drillFilterColumnName(column: TableColumn): string {
   switch (column.kind) {
     case 'argument':
-      return extractArgumentExpression(column.argument);
+      return extractArgumentExpression(column.argument, 'slice');
     case 'regular':
       return `${column.table}.${column.column}`;
   }
diff --git a/ui/src/frontend/pivot_table_redux_query_generator.ts b/ui/src/frontend/pivot_table_redux_query_generator.ts
index de23e0d..b6a23f2 100644
--- a/ui/src/frontend/pivot_table_redux_query_generator.ts
+++ b/ui/src/frontend/pivot_table_redux_query_generator.ts
@@ -133,8 +133,9 @@
       expression(aggregation.column)})`;
 }
 
-export function extractArgumentExpression(argument: string) {
-  return `extract_arg(arg_set_id, ${sqliteString(argument)})`;
+export function extractArgumentExpression(argument: string, table?: string) {
+  const prefix = table === undefined ? '' : `${table}.`;
+  return `extract_arg(${prefix}arg_set_id, ${sqliteString(argument)})`;
 }
 
 function generateInnerQuery(