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());