blob: 0b927659d5e5243fda5cbf289f874ba7954319f3 [file] [log] [blame]
Hector Dearman3d26fdb2018-07-09 13:54:06 +01001// Copyright (C) 2018 The Android Open Source Project
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
Micha Schwab01b35682018-06-28 13:56:49 +010014
Michail Schwabc2ace4e2018-07-31 11:08:12 -040015import '../tracks/all_frontend';
Deepanjan Roy75b46a92018-07-24 09:11:29 -040016
Micha Schwab01b35682018-06-28 13:56:49 +010017import * as m from 'mithril';
Deepanjan Roya752b462018-07-04 01:24:31 +010018
Hector Dearman63a747c2018-08-07 11:36:50 +010019import {forwardRemoteCalls} from '../base/remote';
Deepanjan Roy112ff6a2018-09-10 08:31:43 -040020import {loadPermalink} from '../common/actions';
Primiano Tuccie36ca632018-08-21 14:32:23 +020021import {State} from '../common/state';
22import {TimeSpan} from '../common/time';
Primiano Tuccie36ca632018-08-21 14:32:23 +020023import {globals, QuantizedLoad, ThreadDesc} from './globals';
Hector Dearman81804d12018-07-10 11:38:15 +010024import {HomePage} from './home_page';
Hector Dearman4544f372018-09-19 12:32:36 +010025import {RecordPage} from './record_page';
Deepanjan Roy112ff6a2018-09-10 08:31:43 -040026import {Router} from './router';
Deepanjan Royfd79a7d2018-07-24 13:26:55 -040027import {ViewerPage} from './viewer_page';
Hector Dearman81804d12018-07-10 11:38:15 +010028
Hector Dearmanf13e3a82018-07-25 13:19:35 +010029/**
30 * The API the main thread exposes to the controller.
31 */
32class FrontendApi {
Deepanjan Roy112ff6a2018-09-10 08:31:43 -040033 constructor(private router: Router) {}
34
Hector Dearmanf13e3a82018-07-25 13:19:35 +010035 updateState(state: State) {
36 globals.state = state;
Primiano Tuccie36ca632018-08-21 14:32:23 +020037
38 // If the visible time in the global state has been updated more recently
39 // than the visible time handled by the frontend @ 60fps, update it. This
40 // typically happens when restoring the state from a permalink.
41 const vizTraceTime = globals.state.visibleTraceTime;
42 if (vizTraceTime.lastUpdate >
43 globals.frontendLocalState.visibleTimeLastUpdate) {
44 globals.frontendLocalState.updateVisibleTime(
45 new TimeSpan(vizTraceTime.startSec, vizTraceTime.endSec));
46 }
47
Hector Dearmana38bd902018-08-02 10:38:41 +010048 this.redraw();
Hector Dearmanf13e3a82018-07-25 13:19:35 +010049 }
Hector Dearmanf13e3a82018-07-25 13:19:35 +010050
Primiano Tuccie36ca632018-08-21 14:32:23 +020051 // TODO: we can't have a publish method for each batch of data that we don't
52 // want to keep in the global state. Figure out a more generic and type-safe
53 // mechanism to achieve this.
54
55 publishOverviewData(data: {[key: string]: QuantizedLoad}) {
56 for (const key of Object.keys(data)) {
57 if (!globals.overviewStore.has(key)) {
58 globals.overviewStore.set(key, []);
59 }
60 globals.overviewStore.get(key)!.push(data[key]);
61 }
Deepanjan Royf190cb22018-08-28 10:43:07 -040062 globals.rafScheduler.scheduleRedraw();
Primiano Tuccie36ca632018-08-21 14:32:23 +020063 }
64
65 publishTrackData(args: {id: string, data: {}}) {
66 globals.trackDataStore.set(args.id, args.data);
Deepanjan Royf190cb22018-08-28 10:43:07 -040067 globals.rafScheduler.scheduleRedraw();
Primiano Tuccie36ca632018-08-21 14:32:23 +020068 }
69
70 publishQueryResult(args: {id: string, data: {}}) {
71 globals.queryResults.set(args.id, args.data);
Hector Dearmana38bd902018-08-02 10:38:41 +010072 this.redraw();
Deepanjan Roy75b46a92018-07-24 09:11:29 -040073 }
Hector Dearmana38bd902018-08-02 10:38:41 +010074
Primiano Tuccie36ca632018-08-21 14:32:23 +020075 publishThreads(data: ThreadDesc[]) {
76 globals.threads.clear();
77 data.forEach(thread => {
78 globals.threads.set(thread.utid, thread);
79 });
Primiano Tucci8afc06d2018-08-06 19:11:42 +010080 this.redraw();
81 }
82
Hector Dearmana38bd902018-08-02 10:38:41 +010083 private redraw(): void {
Deepanjan Roy112ff6a2018-09-10 08:31:43 -040084 if (globals.state.route &&
85 globals.state.route !== this.router.getRouteFromHash()) {
86 this.router.setRouteOnHash(globals.state.route);
Hector Dearmana38bd902018-08-02 10:38:41 +010087 }
Deepanjan Roy112ff6a2018-09-10 08:31:43 -040088
89 globals.rafScheduler.scheduleFullRedraw();
Hector Dearmana38bd902018-08-02 10:38:41 +010090 }
Deepanjan Roy75b46a92018-07-24 09:11:29 -040091}
92
Primiano Tuccie36ca632018-08-21 14:32:23 +020093function main() {
94 const controller = new Worker('controller_bundle.js');
95 controller.onerror = e => {
96 console.error(e);
97 };
Hector Dearmanf13e3a82018-07-25 13:19:35 +010098 const channel = new MessageChannel();
Hector Dearman63a747c2018-08-07 11:36:50 +010099 controller.postMessage(channel.port1, [channel.port1]);
Deepanjan Roy112ff6a2018-09-10 08:31:43 -0400100 const dispatch = controller.postMessage.bind(controller);
101 const router = new Router(
102 '/',
103 {
104 '/': HomePage,
105 '/viewer': ViewerPage,
Hector Dearman4544f372018-09-19 12:32:36 +0100106 '/record': RecordPage,
Deepanjan Roy112ff6a2018-09-10 08:31:43 -0400107 },
108 dispatch);
109 forwardRemoteCalls(channel.port2, new FrontendApi(router));
110 globals.initialize(dispatch);
Primiano Tuccif30cd9c2018-08-13 01:53:26 +0200111
Deepanjan Roy112ff6a2018-09-10 08:31:43 -0400112 globals.rafScheduler.domRedraw = () =>
113 m.render(document.body, m(router.resolve(globals.state.route)));
Primiano Tuccif30cd9c2018-08-13 01:53:26 +0200114
Hector Dearman81804d12018-07-10 11:38:15 +0100115
Hector Dearman03f962c2018-08-09 17:00:32 +0100116 // Put these variables in the global scope for better debugging.
117 (window as {} as {m: {}}).m = m;
118 (window as {} as {globals: {}}).globals = globals;
119
Primiano Tuccie36ca632018-08-21 14:32:23 +0200120 // /?s=xxxx for permalinks.
Deepanjan Roy112ff6a2018-09-10 08:31:43 -0400121 const stateHash = router.param('s');
Hector Dearman03f962c2018-08-09 17:00:32 +0100122 if (stateHash) {
Primiano Tuccie36ca632018-08-21 14:32:23 +0200123 globals.dispatch(loadPermalink(stateHash));
Hector Dearman03f962c2018-08-09 17:00:32 +0100124 }
Primiano Tuccid5b2a552018-08-10 02:13:10 +0100125
126 // Prevent pinch zoom.
127 document.body.addEventListener('wheel', (e: MouseEvent) => {
128 if (e.ctrlKey) e.preventDefault();
129 });
Primiano Tuccie36ca632018-08-21 14:32:23 +0200130
Deepanjan Roy112ff6a2018-09-10 08:31:43 -0400131 router.navigateToCurrentHash();
Hector Dearman81804d12018-07-10 11:38:15 +0100132}
133
134main();