Merge "Do not depend on elf.h for symbolization."
diff --git a/docs/README.md b/docs/README.md
index 00a5e9a..f41504c 100644
--- a/docs/README.md
+++ b/docs/README.md
@@ -1,7 +1,7 @@
 # Perfetto - System profiling, app tracing and trace analysis
 
 Perfetto is a production-grade open-source stack for performance
-instrumentation and trace analysis. It offers services and libraries and for
+instrumentation and trace analysis. It offers services and libraries for
 recording system-level and app-level traces, native + java heap profiling, a
 library for analyzing traces using SQL and a web-based UI to visualize and
 explore multi-GB traces.
@@ -12,23 +12,23 @@
 
 At its core, Perfetto introduces a novel userspace-to-userspace
 [tracing protocol](/docs/design-docs/api-and-abi.md#tracing-protocol-abi) based
-on direct protobuf serization onto a shared memory buffer. The tracing protocol
-is used both internally for the built-in data sources and exposed to C++ apps
-through the [Tracing SDK](/docs/instrumentation/tracing-sdk.md) and the
+on direct protobuf serialization onto a shared memory buffer. The tracing
+protocol is used both internally for the built-in data sources and exposed to
+C++ apps through the [Tracing SDK](/docs/instrumentation/tracing-sdk.md) and the
 [Track Event Library](/docs/instrumentation/track-events.md).
 
 This new tracing protocol allows dynamic configuration of all aspects of tracing
 through an extensible protobuf-based capability advertisement and data source
 configuration mechanism (see
 [Trace configuration docs](/docs/concepts/config.md)).
-Different data sources can be multiplexed onto different sub-sets of
+Different data sources can be multiplexed onto different subsets of
 user-defined buffers, allowing also streaming of
 [arbitrarily long traces](/docs/concepts/config.md#long-traces) into the
 filesystem.
 
 ### System-wide tracing on Android and Linux
 
-On Linux and Anroid, Perfetto bundles a number of data sources that are able to
+On Linux and Android, Perfetto bundles a number of data sources that are able to
 gather detailed performance data from different system interfaces. For the full
 sets and details see the _Data Sources_ section of the documentation. Same
 examples:
@@ -46,7 +46,7 @@
 
 * [Native heap profiling](/docs/data-sources/native-heap-profiler.md): a
   low-overhead heap profiler for hooking malloc/free/new/delete and associating
-  memory to callstacks, based on out-of-process unwinding, configurable
+  memory to call-stacks, based on out-of-process unwinding, configurable
   sampling, attachable to already running processes.
 
 * [Java heap profiling](/docs/data-sources/java-heap-profiler.md): an
@@ -70,7 +70,7 @@
 between the flexibility of defining your own strongly-typed events and creating
 custom data sources or using the easier-to-use
 [Track Event Library](/docs/instrumentation/track-events.md) which allows to
-easily create time-boudned slices, counters and time markers using annotations
+easily create time-bounded slices, counters and time markers using annotations
 of the form `TRACE_EVENT("category", "event_name", "x", "str", "y", 42)`.
 
 The SDK is designed for tracing of multi-process systems and multi-threaded
@@ -109,8 +109,8 @@
 dedicated project for importing, parsing and querying new and legacy trace
 formats, [Trace Processor](/docs/analysis/trace-processor.md).
 
-Trace Processor is a portable C++11 library that provides a column-oriented
-table storage, designed ad-hoc for for efficiently holding hours of trace data
+Trace Processor is a portable C++11 library that provides column-oriented
+table storage, designed ad-hoc for efficiently holding hours of trace data
 into memory and exposes a SQL query interface based on the popular SQLite query
 engine.
 The trace data model becomes a set of
@@ -136,7 +136,7 @@
 
 Perfetto provides also a brand new trace visualizer for opening and querying
 hours-long traces, available at [ui.perfetto.dev](https://ui.perfetto.dev).
-The new visualizer takes advantage of modern web platform technolgies.
+The new visualizer takes advantage of modern web platform technologies.
 Its multi-threading design based WebWorkers keeps the UI always responsive;
 the analytical power of Trace Processor and SQLite is fully available in-browser
 through WebAssembly.
diff --git a/src/profiling/symbolizer/local_symbolizer.cc b/src/profiling/symbolizer/local_symbolizer.cc
index 144a55f..814b5a1 100644
--- a/src/profiling/symbolizer/local_symbolizer.cc
+++ b/src/profiling/symbolizer/local_symbolizer.cc
@@ -304,6 +304,7 @@
 
   size_t size = static_cast<size_t>(statbuf.st_size);
 
+  static_assert(EI_CLASS > EI_MAG3, "mem[EI_MAG?] accesses are in range.");
   if (size <= EI_CLASS)
     return false;
 
diff --git a/test/cts/producer/AndroidManifest.xml b/test/cts/producer/AndroidManifest.xml
index 6139dca..7a5d35d 100755
--- a/test/cts/producer/AndroidManifest.xml
+++ b/test/cts/producer/AndroidManifest.xml
@@ -20,7 +20,7 @@
     <uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
 
     <application>
-        <activity android:name=".ProducerActivity" >
+        <activity android:name=".ProducerActivity" android:exported="true">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
                 <category android:name="android.intent.category.LAUNCHER" />
diff --git a/test/cts/test_apps/AndroidManifest_debuggable.xml b/test/cts/test_apps/AndroidManifest_debuggable.xml
index c85ab05..871544e 100755
--- a/test/cts/test_apps/AndroidManifest_debuggable.xml
+++ b/test/cts/test_apps/AndroidManifest_debuggable.xml
@@ -21,11 +21,12 @@
     <application android:debuggable="true">
         <activity
           android:name="android.perfetto.cts.app.MainActivity"
-          android:exported="false">
+          android:exported="true">
         </activity>
         <activity-alias
           android:name="android.perfetto.cts.app.debuggable.MainActivity"
-          android:targetActivity="android.perfetto.cts.app.MainActivity">
+          android:targetActivity="android.perfetto.cts.app.MainActivity"
+           android:exported="true">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
                 <category android:name="android.intent.category.LAUNCHER" />
@@ -33,11 +34,12 @@
         </activity-alias>
         <activity
           android:name="android.perfetto.cts.app.BusyWaitActivity"
-          android:exported="false">
+          android:exported="true">
         </activity>
         <activity-alias
           android:name="android.perfetto.cts.app.debuggable.BusyWaitActivity"
-          android:targetActivity="android.perfetto.cts.app.BusyWaitActivity">
+          android:targetActivity="android.perfetto.cts.app.BusyWaitActivity"
+          android:exported="true">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
                 <category android:name="android.intent.category.LAUNCHER" />
@@ -45,4 +47,3 @@
         </activity-alias>
     </application>
 </manifest>
-
diff --git a/test/cts/test_apps/AndroidManifest_profileable.xml b/test/cts/test_apps/AndroidManifest_profileable.xml
index 129e922..6322806 100755
--- a/test/cts/test_apps/AndroidManifest_profileable.xml
+++ b/test/cts/test_apps/AndroidManifest_profileable.xml
@@ -22,11 +22,12 @@
         <profileable android:shell="true"/>
         <activity
           android:name="android.perfetto.cts.app.MainActivity"
-          android:exported="false">
+          android:exported="true">
         </activity>
         <activity-alias
           android:name="android.perfetto.cts.app.profileable.MainActivity"
-          android:targetActivity="android.perfetto.cts.app.MainActivity">
+          android:targetActivity="android.perfetto.cts.app.MainActivity"
+          android:exported="true">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
                 <category android:name="android.intent.category.LAUNCHER" />
@@ -34,11 +35,12 @@
         </activity-alias>
         <activity
           android:name="android.perfetto.cts.app.BusyWaitActivity"
-          android:exported="false">
+          android:exported="true">
         </activity>
         <activity-alias
           android:name="android.perfetto.cts.app.profileable.BusyWaitActivity"
-          android:targetActivity="android.perfetto.cts.app.BusyWaitActivity">
+          android:targetActivity="android.perfetto.cts.app.BusyWaitActivity"
+          android:exported="true">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
                 <category android:name="android.intent.category.LAUNCHER" />
diff --git a/test/cts/test_apps/AndroidManifest_release.xml b/test/cts/test_apps/AndroidManifest_release.xml
index 5b64a94..83d9c47 100755
--- a/test/cts/test_apps/AndroidManifest_release.xml
+++ b/test/cts/test_apps/AndroidManifest_release.xml
@@ -21,11 +21,12 @@
     <application>
         <activity
           android:name="android.perfetto.cts.app.MainActivity"
-          android:exported="false">
+          android:exported="true">
         </activity>
         <activity-alias
           android:name="android.perfetto.cts.app.release.MainActivity"
-          android:targetActivity="android.perfetto.cts.app.MainActivity">
+          android:targetActivity="android.perfetto.cts.app.MainActivity"
+          android:exported="true">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
                 <category android:name="android.intent.category.LAUNCHER" />
@@ -33,11 +34,12 @@
         </activity-alias>
         <activity
           android:name="android.perfetto.cts.app.BusyWaitActivity"
-          android:exported="false">
+          android:exported="true">
         </activity>
         <activity-alias
           android:name="android.perfetto.cts.app.release.BusyWaitActivity"
-          android:targetActivity="android.perfetto.cts.app.BusyWaitActivity">
+          android:targetActivity="android.perfetto.cts.app.BusyWaitActivity"
+          android:exported="true">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
                 <category android:name="android.intent.category.LAUNCHER" />
@@ -45,4 +47,3 @@
         </activity-alias>
     </application>
 </manifest>
-
diff --git a/tools/heap_profile b/tools/heap_profile
index 127035d..62f99e4 100755
--- a/tools/heap_profile
+++ b/tools/heap_profile
@@ -160,6 +160,8 @@
       "Default 7 days.",
       type=int,
       default=604800000)
+  # This flag is a no-op now. We never start heapprofd explicitly using system
+  # properties.
   parser.add_argument(
       "--no-start", help="Do not start heapprofd.", action='store_true')
   parser.add_argument(
@@ -363,16 +365,6 @@
         ['adb', 'shell', 'su root setenforce %s' % enforcing])
     subprocess.check_call(['adb', 'shell', 'su root setenforce 0'])
 
-  if not args.no_start:
-    heapprofd_prop = subprocess.check_output(
-        ['adb', 'shell', 'getprop persist.heapprofd.enable'])
-    if heapprofd_prop.strip() != '1':
-      subprocess.check_call(
-          ['adb', 'shell', 'setprop persist.heapprofd.enable 1'])
-      atexit.register(subprocess.check_call,
-                      ['adb', 'shell', 'setprop persist.heapprofd.enable 0'])
-
-
   if args.simpleperf:
     subprocess.check_call([
         'adb', 'shell', 'mkdir -p /data/local/tmp/heapprofd_profile && '
diff --git a/ui/src/controller/trace_controller.ts b/ui/src/controller/trace_controller.ts
index 14f2b8a..deeae01 100644
--- a/ui/src/controller/trace_controller.ts
+++ b/ui/src/controller/trace_controller.ts
@@ -159,7 +159,7 @@
 
         const selectionArgs: SelectionControllerArgs = {engine};
         childControllers.push(
-          Child('selection', SelectionController, selectionArgs));
+            Child('selection', SelectionController, selectionArgs));
 
         const cpuProfileArgs: CpuProfileControllerArgs = {engine};
         childControllers.push(
@@ -540,6 +540,7 @@
     const threadCounters = await engine.query(`
       select thread_counter_track.name, utid, thread_counter_track.id,
       start_ts, end_ts from thread_counter_track join thread using(utid)
+      where thread_counter_track.name not in ('time_in_state')
     `);
     for (let i = 0; i < threadCounters.numRecords; i++) {
       const name = threadCounters.columns[0].stringValues![i];
diff --git a/ui/src/frontend/legacy_trace_viewer.ts b/ui/src/frontend/legacy_trace_viewer.ts
index 4f90fb7..a200ea9 100644
--- a/ui/src/frontend/legacy_trace_viewer.ts
+++ b/ui/src/frontend/legacy_trace_viewer.ts
@@ -17,6 +17,27 @@
 import {assertTrue} from '../base/logging';
 import {showModal} from './modal';
 
+const CTRACE_HEADER = 'TRACE:\n';
+
+async function isCtrace(file: File): Promise<boolean> {
+  const fileName = file.name.toLowerCase();
+
+  if (fileName.endsWith('.ctrace')) {
+    return true;
+  }
+
+  // .ctrace files sometimes end with .txt. We can detect these via
+  // the presence of TRACE: near the top of the file.
+  if (fileName.endsWith('.txt')) {
+    const header = await readText(file.slice(0, 128));
+    if (header.includes(CTRACE_HEADER)) {
+      return true;
+    }
+  }
+
+  return false;
+}
+
 function readText(blob: Blob): Promise<string> {
   return new Promise((resolve, reject) => {
     const reader = new FileReader();
@@ -35,8 +56,11 @@
 export async function isLegacyTrace(file: File): Promise<boolean> {
   const fileName = file.name.toLowerCase();
   if (fileName.endsWith('.json') || fileName.endsWith('.json.gz') ||
-      fileName.endsWith('.zip') || fileName.endsWith('.ctrace') ||
-      fileName.endsWith('.html')) {
+      fileName.endsWith('.zip') || fileName.endsWith('.html')) {
+    return true;
+  }
+
+  if (await isCtrace(file)) {
     return true;
   }
 
@@ -61,7 +85,7 @@
   return false;
 }
 
-export function openFileWithLegacyTraceViewer(file: File) {
+export async function openFileWithLegacyTraceViewer(file: File) {
   const reader = new FileReader();
   reader.onload = () => {
     if (reader.result instanceof ArrayBuffer) {
@@ -76,7 +100,7 @@
     console.error(err);
   };
   if (file.name.endsWith('.gz') || file.name.endsWith('.zip') ||
-      file.name.endsWith('.ctrace')) {
+      await isCtrace(file)) {
     reader.readAsArrayBuffer(file);
   } else {
     reader.readAsText(file);
@@ -93,9 +117,10 @@
 
     // Handle .ctrace files.
     const enc = new TextDecoder('utf-8');
-    const header = enc.decode(data.slice(0, 7));
-    if (header === 'TRACE:\n') {
-      data = inflate(new Uint8Array(data.slice(7, size)), {to: 'string'});
+    const header = enc.decode(data.slice(0, 128));
+    if (header.includes(CTRACE_HEADER)) {
+      const offset = header.indexOf(CTRACE_HEADER) + CTRACE_HEADER.length;
+      data = inflate(new Uint8Array(data.slice(offset)), {to: 'string'});
     }
   }
 
diff --git a/ui/src/frontend/sidebar.ts b/ui/src/frontend/sidebar.ts
index a71d371..3a48a6f 100644
--- a/ui/src/frontend/sidebar.ts
+++ b/ui/src/frontend/sidebar.ts
@@ -646,7 +646,10 @@
         if (isDownloadAndShareDisabled() &&
             item.hasOwnProperty('checkDownloadDisabled')) {
           attrs = {
-            onclick: () => alert('Can not download or share external trace.'),
+            onclick: e => {
+              e.preventDefault();
+              alert('Can not download or share external trace.');
+            },
             href: '#',
             target: null,
             disabled: true,