1// Copyright (C) 2021 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 {download} from '../base/clipboard'; 16import {ErrorDetails} from '../base/logging'; 17import {time} from '../base/time'; 18import {Actions} from '../common/actions'; 19import { 20 ConversionJobName, 21 ConversionJobStatus, 22} from '../common/conversion_jobs'; 23 24import {maybeShowErrorDialog} from './error_dialog'; 25import {globals} from './globals'; 26import {openBufferWithLegacyTraceViewer} from './legacy_trace_viewer'; 27 28type Args = 29 | UpdateStatusArgs 30 | UpdateJobStatusArgs 31 | DownloadFileArgs 32 | OpenTraceInLegacyArgs 33 | ErrorArgs; 34 35interface UpdateStatusArgs { 36 kind: 'updateStatus'; 37 status: string; 38} 39 40interface UpdateJobStatusArgs { 41 kind: 'updateJobStatus'; 42 name: ConversionJobName; 43 status: ConversionJobStatus; 44} 45 46interface DownloadFileArgs { 47 kind: 'downloadFile'; 48 buffer: Uint8Array; 49 name: string; 50} 51 52interface OpenTraceInLegacyArgs { 53 kind: 'openTraceInLegacy'; 54 buffer: Uint8Array; 55} 56 57interface ErrorArgs { 58 kind: 'error'; 59 error: ErrorDetails; 60} 61 62function handleOnMessage(msg: MessageEvent): void { 63 const args: Args = msg.data; 64 if (args.kind === 'updateStatus') { 65 globals.dispatch( 66 Actions.updateStatus({ 67 msg: args.status, 68 timestamp: Date.now() / 1000, 69 }), 70 ); 71 } else if (args.kind === 'updateJobStatus') { 72 globals.setConversionJobStatus(args.name, args.status); 73 } else if (args.kind === 'downloadFile') { 74 download(new File([new Blob([args.buffer])], args.name)); 75 } else if (args.kind === 'openTraceInLegacy') { 76 const str = new TextDecoder('utf-8').decode(args.buffer); 77 openBufferWithLegacyTraceViewer('trace.json', str, 0); 78 } else if (args.kind === 'error') { 79 maybeShowErrorDialog(args.error); 80 } else { 81 throw new Error(`Unhandled message ${JSON.stringify(args)}`); 82 } 83} 84 85function makeWorkerAndPost(msg: unknown) { 86 const worker = new Worker(globals.root + 'traceconv_bundle.js'); 87 worker.onmessage = handleOnMessage; 88 worker.postMessage(msg); 89} 90 91export function convertTraceToJsonAndDownload(trace: Blob) { 92 makeWorkerAndPost({ 93 kind: 'ConvertTraceAndDownload', 94 trace, 95 format: 'json', 96 }); 97} 98 99export function convertTraceToSystraceAndDownload(trace: Blob) { 100 makeWorkerAndPost({ 101 kind: 'ConvertTraceAndDownload', 102 trace, 103 format: 'systrace', 104 }); 105} 106 107export function convertToJson(trace: Blob, truncate?: 'start' | 'end') { 108 makeWorkerAndPost({ 109 kind: 'ConvertTraceAndOpenInLegacy', 110 trace, 111 truncate, 112 }); 113} 114 115export function convertTraceToPprofAndDownload( 116 trace: Blob, 117 pid: number, 118 ts: time, 119) { 120 makeWorkerAndPost({ 121 kind: 'ConvertTraceToPprof', 122 trace, 123 pid, 124 ts, 125 }); 126} 127