Merge "trace_processor: Flatten CPU freq storage and remove cycles"
diff --git a/ui/BUILD.gn b/ui/BUILD.gn
index 104b6e8..3acbece 100644
--- a/ui/BUILD.gn
+++ b/ui/BUILD.gn
@@ -260,6 +260,7 @@
     main_css,
     "src/assets/sidebar.scss",
     "src/assets/topbar.scss",
+    "src/assets/record.scss",
   ]
   outputs = [
     "$ui_dir/perfetto.css",
diff --git a/ui/src/assets/perfetto.scss b/ui/src/assets/perfetto.scss
index 95daabd..1b5c774 100644
--- a/ui/src/assets/perfetto.scss
+++ b/ui/src/assets/perfetto.scss
@@ -143,6 +143,8 @@
 
 @import 'sidebar';
 @import 'topbar';
+@import 'record';
+
 .home-page {
     text-align: center;
     padding-top: 20vh;
@@ -309,3 +311,13 @@
 header {
   height: 25px;
 }
+
+.text-column {
+  font-size: 115%;
+  // 2-3 alphabets per line is comfortable for reading.
+  // https://practicaltypography.com/line-length.html 
+  max-width: calc(26ch*2.34);
+  margin: 3rem auto;
+  user-select: text;
+  word-break: break-word;
+}
diff --git a/ui/src/assets/record.scss b/ui/src/assets/record.scss
new file mode 100644
index 0000000..e46456a
--- /dev/null
+++ b/ui/src/assets/record.scss
@@ -0,0 +1,50 @@
+// Copyright (C) 2018 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.
+
+.example-code {
+  display: block;
+  padding: 1rem;
+  background-color: black;
+  color: white;
+  margin: 1rem 0;
+  margin-top: calc(20px + 1rem);
+  border-radius: 3px;
+  position: relative;
+  border-top-right-radius: 4px;
+  overflow: initial;
+  user-select: text;
+
+  ::before {
+    height: 20px;
+    content: "";
+    display: block;
+    width: 100%;
+    background-color: rgb(87%, 87%, 87%);
+    left: 0;
+    position: absolute;
+    right: 0;
+    top: -18px;
+    border-top-left-radius: 4px;
+    border-top-right-radius: 4px;
+  }
+
+  button {
+    margin-left: auto;
+    display: block;
+    font-style: italic;
+    font-size: 75%;
+  }
+}
+
+
diff --git a/ui/src/frontend/index.ts b/ui/src/frontend/index.ts
index d331899..acd2c9f 100644
--- a/ui/src/frontend/index.ts
+++ b/ui/src/frontend/index.ts
@@ -29,6 +29,7 @@
 
 import {globals, QuantizedLoad, ThreadDesc} from './globals';
 import {HomePage} from './home_page';
+import {RecordPage} from './record_page';
 import {Router} from './router';
 import {ViewerPage} from './viewer_page';
 
@@ -125,6 +126,7 @@
       {
         '/': HomePage,
         '/viewer': ViewerPage,
+        '/record': RecordPage,
       },
       dispatch);
   forwardRemoteCalls(channel.port2, new FrontendApi(router));
diff --git a/ui/src/frontend/record_page.ts b/ui/src/frontend/record_page.ts
new file mode 100644
index 0000000..694c8f5
--- /dev/null
+++ b/ui/src/frontend/record_page.ts
@@ -0,0 +1,55 @@
+// Copyright (C) 2018 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 * as m from 'mithril';
+
+import {createPage} from './pages';
+
+const RECORD_COMMAND_LINE =
+    'echo CgYIgKAGIAESIwohCgxsaW51eC5mdHJhY2UQAKIGDhIFc2NoZWQSBWlucHV0GJBOMh0KFnBlcmZldHRvLnRyYWNlZF9wcm9iZXMQgCAYBEAASAA= | base64 --decode | adb shell "perfetto -c - -o /data/misc/perfetto-traces/trace" && adb pull /data/misc/perfetto-traces/trace /tmp/trace';
+
+async function copyToClipboard(text: string): Promise<void> {
+  try {
+    // TODO(hjd): Fix typescript type for navigator.
+    // tslint:disable-next-line no-any
+    await(navigator as any).clipboard.writeText(text);
+  } catch (err) {
+    console.error(`Failed to copy "${text}" to clipboard: ${err}`);
+  }
+}
+
+const CodeSample: m.Component<{text: string}, {}> = {
+  view({attrs}) {
+    return m(
+        '.example-code',
+        m('code', attrs.text),
+        m('button',
+          {
+            onclick: () => copyToClipboard(attrs.text),
+          },
+          'Copy to clipboard'), );
+  },
+};
+
+export const RecordPage = createPage({
+  view() {
+    return m(
+        '.text-column',
+        'To collect a 10 second Perfetto trace from an Android phone run this',
+        ' command:',
+        m(CodeSample, {text: RECORD_COMMAND_LINE}),
+        'Then click "Open trace file" in the menu to the left and select',
+        ' "/tmp/trace".');
+  }
+});
diff --git a/ui/src/frontend/router.ts b/ui/src/frontend/router.ts
index 425bb33..98bf553 100644
--- a/ui/src/frontend/router.ts
+++ b/ui/src/frontend/router.ts
@@ -55,7 +55,8 @@
     history.pushState(undefined, undefined, ROUTE_PREFIX + route);
 
     if (!(route in this.routes)) {
-      // Redirect to default route.
+      console.info(
+          `Route ${route} not known redirecting to ${this.defaultRoute}.`);
       this.dispatch(navigate(this.defaultRoute));
     }
   }
diff --git a/ui/src/frontend/sidebar.ts b/ui/src/frontend/sidebar.ts
index da204ab..76e6435 100644
--- a/ui/src/frontend/sidebar.ts
+++ b/ui/src/frontend/sidebar.ts
@@ -75,7 +75,7 @@
     items: [
       {t: 'Open trace file', a: popupFileSelectionDialog, i: 'folder_open'},
       {t: 'Open example trace', a: handleOpenTraceUrl, i: 'description'},
-      {t: 'Record new trace', a: navigateHome, i: 'fiber_smart_record'},
+      {t: 'Record new trace', a: navigateRecord, i: 'fiber_smart_record'},
       {t: 'Share current trace', a: dispatchCreatePermalink, i: 'share'},
     ],
   },
@@ -146,10 +146,16 @@
   globals.dispatch(openTraceFromFile(e.target.files[0]));
 }
 
-function navigateHome(_: Event) {
+function navigateHome(e: Event) {
+  e.preventDefault();
   globals.dispatch(navigate('/'));
 }
 
+function navigateRecord(e: Event) {
+  e.preventDefault();
+  globals.dispatch(navigate('/record'));
+}
+
 function dispatchCreatePermalink(e: Event) {
   e.preventDefault();
   globals.dispatch(createPermalink());