1// 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.
14
15import {assertExists} from '../base/logging';
16import {Actions} from '../common/actions';
17import {Engine} from '../common/engine';
18import {Registry} from '../common/registry';
19import {TrackState} from '../common/state';
20
21import {Controller} from './controller';
22import {ControllerFactory} from './controller';
23import {globals} from './globals';
24
25// TrackController is a base class overridden by track implementations (e.g.,
26// sched slices, nestable slices, counters).
27export abstract class TrackController<Config = {}, Data = {}> extends
28    Controller<'main'> {
29  readonly trackId: string;
30  readonly engine: Engine;
31
32  constructor(args: TrackControllerArgs) {
33    super('main');
34    this.trackId = args.trackId;
35    this.engine = args.engine;
36  }
37
38  // Must be overridden by the track implementation. Is invoked when the track
39  // frontend runs out of cached data. The derived track controller is expected
40  // to publish new track data in response to this call.
41  abstract onBoundsChange(start: number, end: number, resolution: number): void;
42
43  get trackState(): TrackState {
44    return assertExists(globals.state.tracks[this.trackId]);
45  }
46
47  get config(): Config {
48    return this.trackState.config as Config;
49  }
50
51  publish(data: Data): void {
52    globals.publish('TrackData', {id: this.trackId, data});
53  }
54
55  /**
56   * Returns a valid SQL table name with the given prefix that should be unique
57   * for each track.
58   */
59  tableName(prefix: string) {
60    // Derive table name from, since that is unique for each track.
61    // Track ID can be UUID but '-' is not valid for sql table name.
62    const idSuffix = this.trackId.split('-').join('_');
63    return `${prefix}_${idSuffix}`;
64  }
65
66  shouldSummarize(resolution: number): boolean {
67    // |resolution| is in s/px (to nearest power of 10) assuming a display
68    // of ~1000px 0.0008 is 0.8s.
69    return resolution >= 0.0008;
70  }
71
72  run() {
73    const dataReq = this.trackState.dataReq;
74    if (dataReq === undefined) return;
75    globals.dispatch(Actions.clearTrackDataReq({trackId: this.trackId}));
76    this.onBoundsChange(dataReq.start, dataReq.end, dataReq.resolution);
77  }
78}
79
80export interface TrackControllerArgs {
81  trackId: string;
82  engine: Engine;
83}
84
85export interface TrackControllerFactory extends
86    ControllerFactory<TrackControllerArgs> {
87  kind: string;
88}
89
90export const trackControllerRegistry = new Registry<TrackControllerFactory>();
91