var frontend = (function () {
'use strict';

var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};

function createCommonjsModule(fn, basedir, module) {
	return module = {
	  path: basedir,
	  exports: {},
	  require: function (path, base) {
      return commonjsRequire(path, (base === undefined || base === null) ? module.path : base);
    }
	}, fn(module, module.exports), module.exports;
}

function commonjsRequire () {
	throw new Error('Dynamic requires are not currently supported by @rollup/plugin-commonjs');
}

var checkerboard_1 = createCommonjsModule(function (module, exports) {
// 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.
Object.defineProperty(exports, "__esModule", { value: true });
exports.checkerboardExcept = exports.checkerboard = void 0;
const LOADING_TEXT = 'Loading...';
let LOADING_TEXT_WIDTH = 0;
/**
 * Checker board the range [leftPx, rightPx].
 */
function checkerboard(ctx, heightPx, leftPx, rightPx) {
    const widthPx = rightPx - leftPx;
    ctx.font = '12px Roboto Condensed';
    ctx.fillStyle = '#eee';
    ctx.fillRect(leftPx, 0, widthPx, heightPx);
    ctx.fillStyle = '#666';
    const oldBaseline = ctx.textBaseline;
    ctx.textBaseline = 'middle';
    if (LOADING_TEXT_WIDTH === 0) {
        LOADING_TEXT_WIDTH = ctx.measureText(LOADING_TEXT).width;
    }
    ctx.fillText(LOADING_TEXT, leftPx + widthPx / 2 - LOADING_TEXT_WIDTH, heightPx / 2, widthPx);
    ctx.textBaseline = oldBaseline;
}
exports.checkerboard = checkerboard;
/**
 * Checker board everything between [startPx, endPx] except [leftPx, rightPx].
 */
function checkerboardExcept(ctx, heightPx, startPx, endPx, leftPx, rightPx) {
    // [leftPx, rightPx] doesn't overlap [startPx, endPx] at all:
    if (rightPx <= startPx || leftPx >= endPx) {
        checkerboard(ctx, heightPx, startPx, endPx);
        return;
    }
    // Checkerboard [startPx, leftPx]:
    if (leftPx > startPx) {
        checkerboard(ctx, heightPx, startPx, leftPx);
    }
    // Checkerboard [rightPx, endPx]:
    if (rightPx < endPx) {
        checkerboard(ctx, heightPx, rightPx, endPx);
    }
}
exports.checkerboardExcept = checkerboardExcept;

});

var perfetto_version = createCommonjsModule(function (module, exports) {
Object.defineProperty(exports, "__esModule", { value: true });
exports.SCM_REVISION = exports.VERSION = void 0;
exports.VERSION = "v15.0";
exports.SCM_REVISION = "e99d8868651540d5187224f00ee6407c837cf8a9";

});

var logging = createCommonjsModule(function (module, exports) {
// 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.
Object.defineProperty(exports, "__esModule", { value: true });
exports.reportError = exports.setErrorHandler = exports.assertFalse = exports.assertTrue = exports.assertExists = void 0;

let errorHandler = (_) => { };
function assertExists(value) {
    if (value === null || value === undefined) {
        throw new Error('Value doesn\'t exist');
    }
    return value;
}
exports.assertExists = assertExists;
function assertTrue(value, optMsg) {
    if (value !== true) {
        throw new Error(optMsg ? optMsg : 'Failed assertion');
    }
}
exports.assertTrue = assertTrue;
function assertFalse(value, optMsg) {
    assertTrue(!value, optMsg);
}
exports.assertFalse = assertFalse;
function setErrorHandler(handler) {
    errorHandler = handler;
}
exports.setErrorHandler = setErrorHandler;
function reportError(err) {
    let errLog = '';
    let errorObj = undefined;
    if (err instanceof ErrorEvent) {
        errLog = err.message;
        errorObj = err.error;
    }
    else if (err instanceof PromiseRejectionEvent) {
        errLog = `${err.reason}`;
        errorObj = err.reason;
    }
    else {
        errLog = `${err}`;
    }
    if (errorObj !== undefined && errorObj !== null) {
        const errStack = errorObj.stack;
        errLog += '\n';
        errLog += errStack !== undefined ? errStack : JSON.stringify(errorObj);
    }
    errLog += '\n\n';
    errLog += `${perfetto_version.VERSION} ${perfetto_version.SCM_REVISION}\n`;
    errLog += `UA: ${navigator.userAgent}\n`;
    console.error(errLog, err);
    errorHandler(errLog);
}
exports.reportError = reportError;

});

var conversion_jobs = createCommonjsModule(function (module, exports) {
// Copyright (C) 2021 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.
Object.defineProperty(exports, "__esModule", { value: true });
exports.ConversionJobStatus = void 0;
(function (ConversionJobStatus) {
    ConversionJobStatus["InProgress"] = "InProgress";
    ConversionJobStatus["NotRunning"] = "NotRunning";
})(exports.ConversionJobStatus || (exports.ConversionJobStatus = {}));

});

var state = createCommonjsModule(function (module, exports) {
// 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.
Object.defineProperty(exports, "__esModule", { value: true });
exports.getContainingTrackId = exports.createEmptyState = exports.getBuiltinChromeCategoryList = exports.getDefaultRecordingTargets = exports.createEmptyRecordConfig = exports.hasActiveProbes = exports.isAdbTarget = exports.isLinuxTarget = exports.isCrOSTarget = exports.isChromeTarget = exports.isAndroidTarget = exports.isAndroidP = exports.defaultTraceTime = exports.TrackKindPriority = exports.SCROLLING_TRACK_GROUP = exports.STATE_VERSION = exports.MAX_TIME = void 0;
exports.MAX_TIME = 180;
// 3: TrackKindPriority and related sorting changes.
exports.STATE_VERSION = 3;
exports.SCROLLING_TRACK_GROUP = 'ScrollingTracks';
(function (TrackKindPriority) {
    TrackKindPriority[TrackKindPriority["MAIN_THREAD"] = 0] = "MAIN_THREAD";
    TrackKindPriority[TrackKindPriority["RENDER_THREAD"] = 1] = "RENDER_THREAD";
    TrackKindPriority[TrackKindPriority["GPU_COMPLETION"] = 2] = "GPU_COMPLETION";
    TrackKindPriority[TrackKindPriority["ORDINARY"] = 3] = "ORDINARY";
})(exports.TrackKindPriority || (exports.TrackKindPriority = {}));
exports.defaultTraceTime = {
    startSec: 0,
    endSec: 10,
};
function isAndroidP(target) {
    return target.os === 'P';
}
exports.isAndroidP = isAndroidP;
function isAndroidTarget(target) {
    return ['Q', 'P', 'O'].includes(target.os);
}
exports.isAndroidTarget = isAndroidTarget;
function isChromeTarget(target) {
    return ['C', 'CrOS'].includes(target.os);
}
exports.isChromeTarget = isChromeTarget;
function isCrOSTarget(target) {
    return target.os === 'CrOS';
}
exports.isCrOSTarget = isCrOSTarget;
function isLinuxTarget(target) {
    return target.os === 'L';
}
exports.isLinuxTarget = isLinuxTarget;
function isAdbTarget(target) {
    if (target.serial)
        return true;
    return false;
}
exports.isAdbTarget = isAdbTarget;
function hasActiveProbes(config) {
    const fieldsWithEmptyResult = new Set(['hpBlockClient']);
    for (const key in config) {
        if (typeof (config[key]) === 'boolean' && config[key] === true &&
            !fieldsWithEmptyResult.has(key)) {
            return true;
        }
    }
    return false;
}
exports.hasActiveProbes = hasActiveProbes;
function createEmptyRecordConfig() {
    return {
        mode: 'STOP_WHEN_FULL',
        durationMs: 10000.0,
        maxFileSizeMb: 100,
        fileWritePeriodMs: 2500,
        bufferSizeMb: 64.0,
        cpuSched: false,
        cpuFreq: false,
        cpuSyscall: false,
        screenRecord: false,
        gpuFreq: false,
        gpuMemTotal: false,
        ftrace: false,
        atrace: false,
        ftraceEvents: [],
        ftraceExtraEvents: '',
        atraceCats: [],
        atraceApps: '',
        ftraceBufferSizeKb: 2 * 1024,
        ftraceDrainPeriodMs: 250,
        androidLogs: false,
        androidLogBuffers: [],
        androidFrameTimeline: false,
        cpuCoarse: false,
        cpuCoarsePollMs: 1000,
        batteryDrain: false,
        batteryDrainPollMs: 1000,
        boardSensors: false,
        memHiFreq: false,
        meminfo: false,
        meminfoPeriodMs: 1000,
        meminfoCounters: [],
        vmstat: false,
        vmstatPeriodMs: 1000,
        vmstatCounters: [],
        heapProfiling: false,
        hpSamplingIntervalBytes: 4096,
        hpProcesses: '',
        hpContinuousDumpsPhase: 0,
        hpContinuousDumpsInterval: 0,
        hpSharedMemoryBuffer: 8 * 1048576,
        hpBlockClient: true,
        hpAllHeaps: false,
        javaHeapDump: false,
        jpProcesses: '',
        jpContinuousDumpsPhase: 0,
        jpContinuousDumpsInterval: 0,
        memLmk: false,
        procStats: false,
        procStatsPeriodMs: 1000,
        chromeCategoriesSelected: [],
    };
}
exports.createEmptyRecordConfig = createEmptyRecordConfig;
function getDefaultRecordingTargets() {
    return [
        { os: 'Q', name: 'Android Q+' },
        { os: 'P', name: 'Android P' },
        { os: 'O', name: 'Android O-' },
        { os: 'C', name: 'Chrome' },
        { os: 'CrOS', name: 'Chrome OS (system trace)' },
        { os: 'L', name: 'Linux desktop' }
    ];
}
exports.getDefaultRecordingTargets = getDefaultRecordingTargets;
function getBuiltinChromeCategoryList() {
    // List of static Chrome categories, last updated at Chromium 81.0.4021.0 from
    // Chromium's //base/trace_event/builtin_categories.h.
    return [
        'accessibility',
        'AccountFetcherService',
        'android_webview',
        'aogh',
        'audio',
        'base',
        'benchmark',
        'blink',
        'blink.animations',
        'blink.bindings',
        'blink.console',
        'blink_gc',
        'blink.net',
        'blink_style',
        'blink.user_timing',
        'blink.worker',
        'Blob',
        'browser',
        'browsing_data',
        'CacheStorage',
        'Calculators',
        'CameraStream',
        'camera',
        'cast_app',
        'cast_perf_test',
        'cast.mdns',
        'cast.mdns.socket',
        'cast.stream',
        'cc',
        'cc.debug',
        'cdp.perf',
        'chromeos',
        'cma',
        'compositor',
        'content',
        'content_capture',
        'device',
        'devtools',
        'devtools.contrast',
        'devtools.timeline',
        'disk_cache',
        'download',
        'download_service',
        'drm',
        'drmcursor',
        'dwrite',
        'DXVA_Decoding',
        'EarlyJava',
        'evdev',
        'event',
        'exo',
        'explore_sites',
        'FileSystem',
        'file_system_provider',
        'fonts',
        'GAMEPAD',
        'gpu',
        'gpu.angle',
        'gpu.capture',
        'headless',
        'hwoverlays',
        'identity',
        'ime',
        'IndexedDB',
        'input',
        'io',
        'ipc',
        'Java',
        'jni',
        'jpeg',
        'latency',
        'latencyInfo',
        'leveldb',
        'loading',
        'log',
        'login',
        'media',
        'media_router',
        'memory',
        'midi',
        'mojom',
        'mus',
        'native',
        'navigation',
        'net',
        'netlog',
        'offline_pages',
        'omnibox',
        'oobe',
        'ozone',
        'partition_alloc',
        'passwords',
        'p2p',
        'page-serialization',
        'paint_preview',
        'pepper',
        'PlatformMalloc',
        'power',
        'ppapi',
        'ppapi_proxy',
        'print',
        'rail',
        'renderer',
        'renderer_host',
        'renderer.scheduler',
        'RLZ',
        'safe_browsing',
        'screenlock_monitor',
        'sequence_manager',
        'service_manager',
        'ServiceWorker',
        'sharing',
        'shell',
        'shortcut_viewer',
        'shutdown',
        'SiteEngagement',
        'skia',
        'sql',
        'stadia_media',
        'stadia_rtc',
        'startup',
        'sync',
        'sync_lock_contention',
        'test_gpu',
        'thread_pool',
        'toplevel',
        'toplevel.flow',
        'ui',
        'v8',
        'v8.execute',
        'v8.wasm',
        'ValueStoreFrontend::Backend',
        'views',
        'views.frame',
        'viz',
        'vk',
        'wayland',
        'webaudio',
        'weblayer',
        'WebCore',
        'webrtc',
        'xr',
        'disabled-by-default-animation-worklet',
        'disabled-by-default-audio',
        'disabled-by-default-audio-worklet',
        'disabled-by-default-blink.debug',
        'disabled-by-default-blink.debug.display_lock',
        'disabled-by-default-blink.debug.layout',
        'disabled-by-default-blink.debug.layout.trees',
        'disabled-by-default-blink.feature_usage',
        'disabled-by-default-blink_gc',
        'disabled-by-default-blink.image_decoding',
        'disabled-by-default-blink.invalidation',
        'disabled-by-default-cc',
        'disabled-by-default-cc.debug',
        'disabled-by-default-cc.debug.cdp-perf',
        'disabled-by-default-cc.debug.display_items',
        'disabled-by-default-cc.debug.picture',
        'disabled-by-default-cc.debug.scheduler',
        'disabled-by-default-cc.debug.scheduler.frames',
        'disabled-by-default-cc.debug.scheduler.now',
        'disabled-by-default-content.verbose',
        'disabled-by-default-cpu_profiler',
        'disabled-by-default-cpu_profiler.debug',
        'disabled-by-default-devtools.screenshot',
        'disabled-by-default-devtools.timeline',
        'disabled-by-default-devtools.timeline.frame',
        'disabled-by-default-devtools.timeline.inputs',
        'disabled-by-default-devtools.timeline.invalidationTracking',
        'disabled-by-default-devtools.timeline.layers',
        'disabled-by-default-devtools.timeline.picture',
        'disabled-by-default-file',
        'disabled-by-default-fonts',
        'disabled-by-default-gpu_cmd_queue',
        'disabled-by-default-gpu.dawn',
        'disabled-by-default-gpu.debug',
        'disabled-by-default-gpu.decoder',
        'disabled-by-default-gpu.device',
        'disabled-by-default-gpu.service',
        'disabled-by-default-gpu.vulkan.vma',
        'disabled-by-default-histogram_samples',
        'disabled-by-default-ipc.flow',
        'disabled-by-default-java-heap-profiler',
        'disabled-by-default-layer-element',
        'disabled-by-default-layout_shift.debug',
        'disabled-by-default-lifecycles',
        'disabled-by-default-loading',
        'disabled-by-default-mediastream',
        'disabled-by-default-memory-infra',
        'disabled-by-default-memory-infra.v8.code_stats',
        'disabled-by-default-mojom',
        'disabled-by-default-net',
        'disabled-by-default-network',
        'disabled-by-default-paint-worklet',
        'disabled-by-default-power',
        'disabled-by-default-renderer.scheduler',
        'disabled-by-default-renderer.scheduler.debug',
        'disabled-by-default-sandbox',
        'disabled-by-default-sequence_manager',
        'disabled-by-default-sequence_manager.debug',
        'disabled-by-default-sequence_manager.verbose_snapshots',
        'disabled-by-default-skia',
        'disabled-by-default-skia.gpu',
        'disabled-by-default-skia.gpu.cache',
        'disabled-by-default-skia.shaders',
        'disabled-by-default-SyncFileSystem',
        'disabled-by-default-system_stats',
        'disabled-by-default-thread_pool_diagnostics',
        'disabled-by-default-toplevel.flow',
        'disabled-by-default-toplevel.ipc',
        'disabled-by-default-user_action_samples',
        'disabled-by-default-v8.compile',
        'disabled-by-default-v8.cpu_profiler',
        'disabled-by-default-v8.cpu_profiler.hires',
        'disabled-by-default-v8.gc',
        'disabled-by-default-v8.gc_stats',
        'disabled-by-default-v8.ic_stats',
        'disabled-by-default-v8.runtime',
        'disabled-by-default-v8.runtime_stats',
        'disabled-by-default-v8.runtime_stats_sampling',
        'disabled-by-default-v8.stack_trace',
        'disabled-by-default-v8.turbofan',
        'disabled-by-default-v8.wasm',
        'disabled-by-default-v8.wasm.detailed',
        'disabled-by-default-v8.wasm.turbofan',
        'disabled-by-default-video_and_image_capture',
        'disabled-by-default-viz.debug.overlay_planes',
        'disabled-by-default-viz.gpu_composite_time',
        'disabled-by-default-viz.hit_testing_flow',
        'disabled-by-default-viz.overdraw',
        'disabled-by-default-viz.quads',
        'disabled-by-default-viz.surface_id_flow',
        'disabled-by-default-viz.surface_lifetime',
        'disabled-by-default-viz.triangles',
        'disabled-by-default-webaudio.audionode',
        'disabled-by-default-webrtc',
        'disabled-by-default-worker.scheduler',
        'disabled-by-default-xr.debug',
    ];
}
exports.getBuiltinChromeCategoryList = getBuiltinChromeCategoryList;
function createEmptyState() {
    return {
        version: exports.STATE_VERSION,
        route: null,
        nextId: 0,
        nextNoteId: 1,
        nextAreaId: 0,
        newEngineMode: 'USE_HTTP_RPC_IF_AVAILABLE',
        engines: {},
        traceTime: Object.assign({}, exports.defaultTraceTime),
        tracks: {},
        aggregatePreferences: {},
        trackGroups: {},
        visibleTracks: [],
        pinnedTracks: [],
        scrollingTracks: [],
        areas: {},
        queries: {},
        metrics: {},
        permalink: {},
        notes: {},
        recordConfig: createEmptyRecordConfig(),
        displayConfigAsPbtxt: false,
        frontendLocalState: {
            omniboxState: {
                lastUpdate: 0,
                omnibox: '',
                mode: 'SEARCH',
            },
            visibleState: Object.assign(Object.assign({}, exports.defaultTraceTime), { lastUpdate: 0, resolution: 0 }),
        },
        logsPagination: {
            offset: 0,
            count: 0,
        },
        status: { msg: '', timestamp: 0 },
        currentSelection: null,
        currentHeapProfileFlamegraph: null,
        traceConversionInProgress: false,
        video: null,
        videoEnabled: false,
        videoOffset: 0,
        videoNoteIds: [],
        scrubbingEnabled: false,
        flagPauseEnabled: false,
        recordingInProgress: false,
        recordingCancelled: false,
        extensionInstalled: false,
        recordingTarget: getDefaultRecordingTargets()[0],
        availableAdbDevices: [],
        updateChromeCategories: false,
        chromeCategories: undefined,
    };
}
exports.createEmptyState = createEmptyState;
function getContainingTrackId(state, trackId) {
    const track = state.tracks[trackId];
    if (!track) {
        return null;
    }
    const parentId = track.trackGroup;
    if (!parentId) {
        return null;
    }
    return parentId;
}
exports.getContainingTrackId = getContainingTrackId;

});

var time = createCommonjsModule(function (module, exports) {
// 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.
Object.defineProperty(exports, "__esModule", { value: true });
exports.TimeSpan = exports.timeToCode = exports.formatTimestamp = exports.toNs = exports.toNsCeil = exports.toNsFloor = exports.fromNs = exports.timeToString = void 0;

const EPSILON = 0.0000000001;
// TODO(hjd): Combine with timeToCode.
function timeToString(sec) {
    const units = ['s', 'ms', 'us', 'ns'];
    const sign = Math.sign(sec);
    let n = Math.abs(sec);
    let u = 0;
    while (n < 1 && n !== 0 && u < units.length - 1) {
        n *= 1000;
        u++;
    }
    return `${sign < 0 ? '-' : ''}${Math.round(n * 10) / 10} ${units[u]}`;
}
exports.timeToString = timeToString;
function fromNs(ns) {
    return ns / 1e9;
}
exports.fromNs = fromNs;
function toNsFloor(seconds) {
    return Math.floor(seconds * 1e9);
}
exports.toNsFloor = toNsFloor;
function toNsCeil(seconds) {
    return Math.ceil(seconds * 1e9);
}
exports.toNsCeil = toNsCeil;
function toNs(seconds) {
    return Math.round(seconds * 1e9);
}
exports.toNs = toNs;
// 1000000023ns -> "1.000 000 023"
function formatTimestamp(sec) {
    const parts = sec.toFixed(9).split('.');
    parts[1] = parts[1].replace(/\B(?=(\d{3})+(?!\d))/g, ' ');
    return parts.join('.');
}
exports.formatTimestamp = formatTimestamp;
// TODO(hjd): Rename to formatTimestampWithUnits
// 1000000023ns -> "1s 23ns"
function timeToCode(sec) {
    let result = '';
    let ns = Math.round(sec * 1e9);
    if (ns < 1)
        return '0s';
    const unitAndValue = [
        ['m', 60000000000],
        ['s', 1000000000],
        ['ms', 1000000],
        ['us', 1000],
        ['ns', 1]
    ];
    unitAndValue.forEach(pair => {
        const unit = pair[0];
        const val = pair[1];
        if (ns >= val) {
            const i = Math.floor(ns / val);
            ns -= i * val;
            result += i.toLocaleString() + unit + ' ';
        }
    });
    return result.slice(0, -1);
}
exports.timeToCode = timeToCode;
class TimeSpan {
    constructor(start, end) {
        logging.assertTrue(start <= end);
        this.start = start;
        this.end = end;
    }
    clone() {
        return new TimeSpan(this.start, this.end);
    }
    equals(other) {
        return Math.abs(this.start - other.start) < EPSILON &&
            Math.abs(this.end - other.end) < EPSILON;
    }
    get duration() {
        return this.end - this.start;
    }
    isInBounds(sec) {
        return this.start <= sec && sec <= this.end;
    }
    add(sec) {
        return new TimeSpan(this.start + sec, this.end + sec);
    }
    contains(other) {
        return this.start <= other.start && other.end <= this.end;
    }
}
exports.TimeSpan = TimeSpan;

});

var analytics = createCommonjsModule(function (module, exports) {
// Copyright (C) 2020 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.
Object.defineProperty(exports, "__esModule", { value: true });
exports.NullAnalytics = exports.initAnalytics = void 0;


const ANALYTICS_ID = 'UA-137828855-1';
const PAGE_TITLE = 'no-page-title';
function initAnalytics() {
    // Only initialize logging on prod or staging
    if (window.location.origin.startsWith('http://localhost:') ||
        window.location.origin.endsWith('.perfetto.dev') ||
        window.location.origin.endsWith('staging-dot-perfetto-ui.appspot.com')) {
        return new AnalyticsImpl();
    }
    return new NullAnalytics();
}
exports.initAnalytics = initAnalytics;
const gtagGlobals = window;
class NullAnalytics {
    initialize() { }
    updatePath(_) { }
    logEvent(_x, _y) { }
    logError(_x) { }
}
exports.NullAnalytics = NullAnalytics;
class AnalyticsImpl {
    constructor() {
        this.initialized_ = false;
        // The code below is taken from the official Google Analytics docs [1] and
        // adapted to TypeScript. We have it here rather than as an inline script
        // in index.html (as suggested by GA's docs) because inline scripts don't
        // play nicely with the CSP policy, at least in Firefox (Firefox doesn't
        // support all CSP 3 features we use).
        // [1] https://developers.google.com/analytics/devguides/collection/gtagjs .
        gtagGlobals.dataLayer = gtagGlobals.dataLayer || [];
        // tslint:disable-next-line no-any
        function gtagFunction(..._) {
            // This needs to be a function and not a lambda. |arguments| behaves
            // slightly differently in a lambda and breaks GA.
            gtagGlobals.dataLayer.push(arguments);
        }
        gtagGlobals.gtag = gtagFunction;
        gtagGlobals.gtag('js', new Date());
    }
    // This is callled only after the script that sets isInternalUser loads.
    // It is fine to call updatePath() and log*() functions before initialize().
    // The gtag() function internally enqueues all requests into |dataLayer|.
    initialize() {
        if (this.initialized_)
            return;
        this.initialized_ = true;
        const script = document.createElement('script');
        script.src = 'https://www.googletagmanager.com/gtag/js?id=' + ANALYTICS_ID;
        script.defer = true;
        document.head.appendChild(script);
        const route = globals$1.globals.state.route || '/';
        console.log(`GA initialized. route=${route}`, `isInternalUser=${globals$1.globals.isInternalUser}`);
        // GA's reccomendation for SPAs is to disable automatic page views and
        // manually send page_view events. See:
        // https://developers.google.com/analytics/devguides/collection/gtagjs/pages#manual_pageviews
        gtagGlobals.gtag('config', ANALYTICS_ID, {
            allow_google_signals: false,
            anonymize_ip: true,
            page_path: route,
            referrer: document.referrer.split('?')[0],
            send_page_view: false,
            page_title: PAGE_TITLE,
            dimension1: globals$1.globals.isInternalUser ? '1' : '0',
            dimension2: perfetto_version.VERSION,
            dimension3: globals$1.globals.channel,
        });
        this.updatePath(route);
    }
    updatePath(path) {
        gtagGlobals.gtag('event', 'page_view', { page_path: path, page_title: PAGE_TITLE });
    }
    logEvent(category, event) {
        gtagGlobals.gtag('event', event, { event_category: category });
    }
    logError(description, fatal = true) {
        gtagGlobals.gtag('event', 'exception', { description, fatal });
    }
}

});

var colorName = {
	"aliceblue": [240, 248, 255],
	"antiquewhite": [250, 235, 215],
	"aqua": [0, 255, 255],
	"aquamarine": [127, 255, 212],
	"azure": [240, 255, 255],
	"beige": [245, 245, 220],
	"bisque": [255, 228, 196],
	"black": [0, 0, 0],
	"blanchedalmond": [255, 235, 205],
	"blue": [0, 0, 255],
	"blueviolet": [138, 43, 226],
	"brown": [165, 42, 42],
	"burlywood": [222, 184, 135],
	"cadetblue": [95, 158, 160],
	"chartreuse": [127, 255, 0],
	"chocolate": [210, 105, 30],
	"coral": [255, 127, 80],
	"cornflowerblue": [100, 149, 237],
	"cornsilk": [255, 248, 220],
	"crimson": [220, 20, 60],
	"cyan": [0, 255, 255],
	"darkblue": [0, 0, 139],
	"darkcyan": [0, 139, 139],
	"darkgoldenrod": [184, 134, 11],
	"darkgray": [169, 169, 169],
	"darkgreen": [0, 100, 0],
	"darkgrey": [169, 169, 169],
	"darkkhaki": [189, 183, 107],
	"darkmagenta": [139, 0, 139],
	"darkolivegreen": [85, 107, 47],
	"darkorange": [255, 140, 0],
	"darkorchid": [153, 50, 204],
	"darkred": [139, 0, 0],
	"darksalmon": [233, 150, 122],
	"darkseagreen": [143, 188, 143],
	"darkslateblue": [72, 61, 139],
	"darkslategray": [47, 79, 79],
	"darkslategrey": [47, 79, 79],
	"darkturquoise": [0, 206, 209],
	"darkviolet": [148, 0, 211],
	"deeppink": [255, 20, 147],
	"deepskyblue": [0, 191, 255],
	"dimgray": [105, 105, 105],
	"dimgrey": [105, 105, 105],
	"dodgerblue": [30, 144, 255],
	"firebrick": [178, 34, 34],
	"floralwhite": [255, 250, 240],
	"forestgreen": [34, 139, 34],
	"fuchsia": [255, 0, 255],
	"gainsboro": [220, 220, 220],
	"ghostwhite": [248, 248, 255],
	"gold": [255, 215, 0],
	"goldenrod": [218, 165, 32],
	"gray": [128, 128, 128],
	"green": [0, 128, 0],
	"greenyellow": [173, 255, 47],
	"grey": [128, 128, 128],
	"honeydew": [240, 255, 240],
	"hotpink": [255, 105, 180],
	"indianred": [205, 92, 92],
	"indigo": [75, 0, 130],
	"ivory": [255, 255, 240],
	"khaki": [240, 230, 140],
	"lavender": [230, 230, 250],
	"lavenderblush": [255, 240, 245],
	"lawngreen": [124, 252, 0],
	"lemonchiffon": [255, 250, 205],
	"lightblue": [173, 216, 230],
	"lightcoral": [240, 128, 128],
	"lightcyan": [224, 255, 255],
	"lightgoldenrodyellow": [250, 250, 210],
	"lightgray": [211, 211, 211],
	"lightgreen": [144, 238, 144],
	"lightgrey": [211, 211, 211],
	"lightpink": [255, 182, 193],
	"lightsalmon": [255, 160, 122],
	"lightseagreen": [32, 178, 170],
	"lightskyblue": [135, 206, 250],
	"lightslategray": [119, 136, 153],
	"lightslategrey": [119, 136, 153],
	"lightsteelblue": [176, 196, 222],
	"lightyellow": [255, 255, 224],
	"lime": [0, 255, 0],
	"limegreen": [50, 205, 50],
	"linen": [250, 240, 230],
	"magenta": [255, 0, 255],
	"maroon": [128, 0, 0],
	"mediumaquamarine": [102, 205, 170],
	"mediumblue": [0, 0, 205],
	"mediumorchid": [186, 85, 211],
	"mediumpurple": [147, 112, 219],
	"mediumseagreen": [60, 179, 113],
	"mediumslateblue": [123, 104, 238],
	"mediumspringgreen": [0, 250, 154],
	"mediumturquoise": [72, 209, 204],
	"mediumvioletred": [199, 21, 133],
	"midnightblue": [25, 25, 112],
	"mintcream": [245, 255, 250],
	"mistyrose": [255, 228, 225],
	"moccasin": [255, 228, 181],
	"navajowhite": [255, 222, 173],
	"navy": [0, 0, 128],
	"oldlace": [253, 245, 230],
	"olive": [128, 128, 0],
	"olivedrab": [107, 142, 35],
	"orange": [255, 165, 0],
	"orangered": [255, 69, 0],
	"orchid": [218, 112, 214],
	"palegoldenrod": [238, 232, 170],
	"palegreen": [152, 251, 152],
	"paleturquoise": [175, 238, 238],
	"palevioletred": [219, 112, 147],
	"papayawhip": [255, 239, 213],
	"peachpuff": [255, 218, 185],
	"peru": [205, 133, 63],
	"pink": [255, 192, 203],
	"plum": [221, 160, 221],
	"powderblue": [176, 224, 230],
	"purple": [128, 0, 128],
	"rebeccapurple": [102, 51, 153],
	"red": [255, 0, 0],
	"rosybrown": [188, 143, 143],
	"royalblue": [65, 105, 225],
	"saddlebrown": [139, 69, 19],
	"salmon": [250, 128, 114],
	"sandybrown": [244, 164, 96],
	"seagreen": [46, 139, 87],
	"seashell": [255, 245, 238],
	"sienna": [160, 82, 45],
	"silver": [192, 192, 192],
	"skyblue": [135, 206, 235],
	"slateblue": [106, 90, 205],
	"slategray": [112, 128, 144],
	"slategrey": [112, 128, 144],
	"snow": [255, 250, 250],
	"springgreen": [0, 255, 127],
	"steelblue": [70, 130, 180],
	"tan": [210, 180, 140],
	"teal": [0, 128, 128],
	"thistle": [216, 191, 216],
	"tomato": [255, 99, 71],
	"turquoise": [64, 224, 208],
	"violet": [238, 130, 238],
	"wheat": [245, 222, 179],
	"white": [255, 255, 255],
	"whitesmoke": [245, 245, 245],
	"yellow": [255, 255, 0],
	"yellowgreen": [154, 205, 50]
};

/* MIT license */
/* eslint-disable no-mixed-operators */


// NOTE: conversions should only return primitive values (i.e. arrays, or
//       values that give correct `typeof` results).
//       do not use box values types (i.e. Number(), String(), etc.)

const reverseKeywords = {};
for (const key of Object.keys(colorName)) {
	reverseKeywords[colorName[key]] = key;
}

const convert = {
	rgb: {channels: 3, labels: 'rgb'},
	hsl: {channels: 3, labels: 'hsl'},
	hsv: {channels: 3, labels: 'hsv'},
	hwb: {channels: 3, labels: 'hwb'},
	cmyk: {channels: 4, labels: 'cmyk'},
	xyz: {channels: 3, labels: 'xyz'},
	lab: {channels: 3, labels: 'lab'},
	lch: {channels: 3, labels: 'lch'},
	hex: {channels: 1, labels: ['hex']},
	keyword: {channels: 1, labels: ['keyword']},
	ansi16: {channels: 1, labels: ['ansi16']},
	ansi256: {channels: 1, labels: ['ansi256']},
	hcg: {channels: 3, labels: ['h', 'c', 'g']},
	apple: {channels: 3, labels: ['r16', 'g16', 'b16']},
	gray: {channels: 1, labels: ['gray']}
};

var conversions = convert;

// Hide .channels and .labels properties
for (const model of Object.keys(convert)) {
	if (!('channels' in convert[model])) {
		throw new Error('missing channels property: ' + model);
	}

	if (!('labels' in convert[model])) {
		throw new Error('missing channel labels property: ' + model);
	}

	if (convert[model].labels.length !== convert[model].channels) {
		throw new Error('channel and label counts mismatch: ' + model);
	}

	const {channels, labels} = convert[model];
	delete convert[model].channels;
	delete convert[model].labels;
	Object.defineProperty(convert[model], 'channels', {value: channels});
	Object.defineProperty(convert[model], 'labels', {value: labels});
}

convert.rgb.hsl = function (rgb) {
	const r = rgb[0] / 255;
	const g = rgb[1] / 255;
	const b = rgb[2] / 255;
	const min = Math.min(r, g, b);
	const max = Math.max(r, g, b);
	const delta = max - min;
	let h;
	let s;

	if (max === min) {
		h = 0;
	} else if (r === max) {
		h = (g - b) / delta;
	} else if (g === max) {
		h = 2 + (b - r) / delta;
	} else if (b === max) {
		h = 4 + (r - g) / delta;
	}

	h = Math.min(h * 60, 360);

	if (h < 0) {
		h += 360;
	}

	const l = (min + max) / 2;

	if (max === min) {
		s = 0;
	} else if (l <= 0.5) {
		s = delta / (max + min);
	} else {
		s = delta / (2 - max - min);
	}

	return [h, s * 100, l * 100];
};

convert.rgb.hsv = function (rgb) {
	let rdif;
	let gdif;
	let bdif;
	let h;
	let s;

	const r = rgb[0] / 255;
	const g = rgb[1] / 255;
	const b = rgb[2] / 255;
	const v = Math.max(r, g, b);
	const diff = v - Math.min(r, g, b);
	const diffc = function (c) {
		return (v - c) / 6 / diff + 1 / 2;
	};

	if (diff === 0) {
		h = 0;
		s = 0;
	} else {
		s = diff / v;
		rdif = diffc(r);
		gdif = diffc(g);
		bdif = diffc(b);

		if (r === v) {
			h = bdif - gdif;
		} else if (g === v) {
			h = (1 / 3) + rdif - bdif;
		} else if (b === v) {
			h = (2 / 3) + gdif - rdif;
		}

		if (h < 0) {
			h += 1;
		} else if (h > 1) {
			h -= 1;
		}
	}

	return [
		h * 360,
		s * 100,
		v * 100
	];
};

convert.rgb.hwb = function (rgb) {
	const r = rgb[0];
	const g = rgb[1];
	let b = rgb[2];
	const h = convert.rgb.hsl(rgb)[0];
	const w = 1 / 255 * Math.min(r, Math.min(g, b));

	b = 1 - 1 / 255 * Math.max(r, Math.max(g, b));

	return [h, w * 100, b * 100];
};

convert.rgb.cmyk = function (rgb) {
	const r = rgb[0] / 255;
	const g = rgb[1] / 255;
	const b = rgb[2] / 255;

	const k = Math.min(1 - r, 1 - g, 1 - b);
	const c = (1 - r - k) / (1 - k) || 0;
	const m = (1 - g - k) / (1 - k) || 0;
	const y = (1 - b - k) / (1 - k) || 0;

	return [c * 100, m * 100, y * 100, k * 100];
};

function comparativeDistance(x, y) {
	/*
		See https://en.m.wikipedia.org/wiki/Euclidean_distance#Squared_Euclidean_distance
	*/
	return (
		((x[0] - y[0]) ** 2) +
		((x[1] - y[1]) ** 2) +
		((x[2] - y[2]) ** 2)
	);
}

convert.rgb.keyword = function (rgb) {
	const reversed = reverseKeywords[rgb];
	if (reversed) {
		return reversed;
	}

	let currentClosestDistance = Infinity;
	let currentClosestKeyword;

	for (const keyword of Object.keys(colorName)) {
		const value = colorName[keyword];

		// Compute comparative distance
		const distance = comparativeDistance(rgb, value);

		// Check if its less, if so set as closest
		if (distance < currentClosestDistance) {
			currentClosestDistance = distance;
			currentClosestKeyword = keyword;
		}
	}

	return currentClosestKeyword;
};

convert.keyword.rgb = function (keyword) {
	return colorName[keyword];
};

convert.rgb.xyz = function (rgb) {
	let r = rgb[0] / 255;
	let g = rgb[1] / 255;
	let b = rgb[2] / 255;

	// Assume sRGB
	r = r > 0.04045 ? (((r + 0.055) / 1.055) ** 2.4) : (r / 12.92);
	g = g > 0.04045 ? (((g + 0.055) / 1.055) ** 2.4) : (g / 12.92);
	b = b > 0.04045 ? (((b + 0.055) / 1.055) ** 2.4) : (b / 12.92);

	const x = (r * 0.4124) + (g * 0.3576) + (b * 0.1805);
	const y = (r * 0.2126) + (g * 0.7152) + (b * 0.0722);
	const z = (r * 0.0193) + (g * 0.1192) + (b * 0.9505);

	return [x * 100, y * 100, z * 100];
};

convert.rgb.lab = function (rgb) {
	const xyz = convert.rgb.xyz(rgb);
	let x = xyz[0];
	let y = xyz[1];
	let z = xyz[2];

	x /= 95.047;
	y /= 100;
	z /= 108.883;

	x = x > 0.008856 ? (x ** (1 / 3)) : (7.787 * x) + (16 / 116);
	y = y > 0.008856 ? (y ** (1 / 3)) : (7.787 * y) + (16 / 116);
	z = z > 0.008856 ? (z ** (1 / 3)) : (7.787 * z) + (16 / 116);

	const l = (116 * y) - 16;
	const a = 500 * (x - y);
	const b = 200 * (y - z);

	return [l, a, b];
};

convert.hsl.rgb = function (hsl) {
	const h = hsl[0] / 360;
	const s = hsl[1] / 100;
	const l = hsl[2] / 100;
	let t2;
	let t3;
	let val;

	if (s === 0) {
		val = l * 255;
		return [val, val, val];
	}

	if (l < 0.5) {
		t2 = l * (1 + s);
	} else {
		t2 = l + s - l * s;
	}

	const t1 = 2 * l - t2;

	const rgb = [0, 0, 0];
	for (let i = 0; i < 3; i++) {
		t3 = h + 1 / 3 * -(i - 1);
		if (t3 < 0) {
			t3++;
		}

		if (t3 > 1) {
			t3--;
		}

		if (6 * t3 < 1) {
			val = t1 + (t2 - t1) * 6 * t3;
		} else if (2 * t3 < 1) {
			val = t2;
		} else if (3 * t3 < 2) {
			val = t1 + (t2 - t1) * (2 / 3 - t3) * 6;
		} else {
			val = t1;
		}

		rgb[i] = val * 255;
	}

	return rgb;
};

convert.hsl.hsv = function (hsl) {
	const h = hsl[0];
	let s = hsl[1] / 100;
	let l = hsl[2] / 100;
	let smin = s;
	const lmin = Math.max(l, 0.01);

	l *= 2;
	s *= (l <= 1) ? l : 2 - l;
	smin *= lmin <= 1 ? lmin : 2 - lmin;
	const v = (l + s) / 2;
	const sv = l === 0 ? (2 * smin) / (lmin + smin) : (2 * s) / (l + s);

	return [h, sv * 100, v * 100];
};

convert.hsv.rgb = function (hsv) {
	const h = hsv[0] / 60;
	const s = hsv[1] / 100;
	let v = hsv[2] / 100;
	const hi = Math.floor(h) % 6;

	const f = h - Math.floor(h);
	const p = 255 * v * (1 - s);
	const q = 255 * v * (1 - (s * f));
	const t = 255 * v * (1 - (s * (1 - f)));
	v *= 255;

	switch (hi) {
		case 0:
			return [v, t, p];
		case 1:
			return [q, v, p];
		case 2:
			return [p, v, t];
		case 3:
			return [p, q, v];
		case 4:
			return [t, p, v];
		case 5:
			return [v, p, q];
	}
};

convert.hsv.hsl = function (hsv) {
	const h = hsv[0];
	const s = hsv[1] / 100;
	const v = hsv[2] / 100;
	const vmin = Math.max(v, 0.01);
	let sl;
	let l;

	l = (2 - s) * v;
	const lmin = (2 - s) * vmin;
	sl = s * vmin;
	sl /= (lmin <= 1) ? lmin : 2 - lmin;
	sl = sl || 0;
	l /= 2;

	return [h, sl * 100, l * 100];
};

// http://dev.w3.org/csswg/css-color/#hwb-to-rgb
convert.hwb.rgb = function (hwb) {
	const h = hwb[0] / 360;
	let wh = hwb[1] / 100;
	let bl = hwb[2] / 100;
	const ratio = wh + bl;
	let f;

	// Wh + bl cant be > 1
	if (ratio > 1) {
		wh /= ratio;
		bl /= ratio;
	}

	const i = Math.floor(6 * h);
	const v = 1 - bl;
	f = 6 * h - i;

	if ((i & 0x01) !== 0) {
		f = 1 - f;
	}

	const n = wh + f * (v - wh); // Linear interpolation

	let r;
	let g;
	let b;
	/* eslint-disable max-statements-per-line,no-multi-spaces */
	switch (i) {
		default:
		case 6:
		case 0: r = v;  g = n;  b = wh; break;
		case 1: r = n;  g = v;  b = wh; break;
		case 2: r = wh; g = v;  b = n; break;
		case 3: r = wh; g = n;  b = v; break;
		case 4: r = n;  g = wh; b = v; break;
		case 5: r = v;  g = wh; b = n; break;
	}
	/* eslint-enable max-statements-per-line,no-multi-spaces */

	return [r * 255, g * 255, b * 255];
};

convert.cmyk.rgb = function (cmyk) {
	const c = cmyk[0] / 100;
	const m = cmyk[1] / 100;
	const y = cmyk[2] / 100;
	const k = cmyk[3] / 100;

	const r = 1 - Math.min(1, c * (1 - k) + k);
	const g = 1 - Math.min(1, m * (1 - k) + k);
	const b = 1 - Math.min(1, y * (1 - k) + k);

	return [r * 255, g * 255, b * 255];
};

convert.xyz.rgb = function (xyz) {
	const x = xyz[0] / 100;
	const y = xyz[1] / 100;
	const z = xyz[2] / 100;
	let r;
	let g;
	let b;

	r = (x * 3.2406) + (y * -1.5372) + (z * -0.4986);
	g = (x * -0.9689) + (y * 1.8758) + (z * 0.0415);
	b = (x * 0.0557) + (y * -0.2040) + (z * 1.0570);

	// Assume sRGB
	r = r > 0.0031308
		? ((1.055 * (r ** (1.0 / 2.4))) - 0.055)
		: r * 12.92;

	g = g > 0.0031308
		? ((1.055 * (g ** (1.0 / 2.4))) - 0.055)
		: g * 12.92;

	b = b > 0.0031308
		? ((1.055 * (b ** (1.0 / 2.4))) - 0.055)
		: b * 12.92;

	r = Math.min(Math.max(0, r), 1);
	g = Math.min(Math.max(0, g), 1);
	b = Math.min(Math.max(0, b), 1);

	return [r * 255, g * 255, b * 255];
};

convert.xyz.lab = function (xyz) {
	let x = xyz[0];
	let y = xyz[1];
	let z = xyz[2];

	x /= 95.047;
	y /= 100;
	z /= 108.883;

	x = x > 0.008856 ? (x ** (1 / 3)) : (7.787 * x) + (16 / 116);
	y = y > 0.008856 ? (y ** (1 / 3)) : (7.787 * y) + (16 / 116);
	z = z > 0.008856 ? (z ** (1 / 3)) : (7.787 * z) + (16 / 116);

	const l = (116 * y) - 16;
	const a = 500 * (x - y);
	const b = 200 * (y - z);

	return [l, a, b];
};

convert.lab.xyz = function (lab) {
	const l = lab[0];
	const a = lab[1];
	const b = lab[2];
	let x;
	let y;
	let z;

	y = (l + 16) / 116;
	x = a / 500 + y;
	z = y - b / 200;

	const y2 = y ** 3;
	const x2 = x ** 3;
	const z2 = z ** 3;
	y = y2 > 0.008856 ? y2 : (y - 16 / 116) / 7.787;
	x = x2 > 0.008856 ? x2 : (x - 16 / 116) / 7.787;
	z = z2 > 0.008856 ? z2 : (z - 16 / 116) / 7.787;

	x *= 95.047;
	y *= 100;
	z *= 108.883;

	return [x, y, z];
};

convert.lab.lch = function (lab) {
	const l = lab[0];
	const a = lab[1];
	const b = lab[2];
	let h;

	const hr = Math.atan2(b, a);
	h = hr * 360 / 2 / Math.PI;

	if (h < 0) {
		h += 360;
	}

	const c = Math.sqrt(a * a + b * b);

	return [l, c, h];
};

convert.lch.lab = function (lch) {
	const l = lch[0];
	const c = lch[1];
	const h = lch[2];

	const hr = h / 360 * 2 * Math.PI;
	const a = c * Math.cos(hr);
	const b = c * Math.sin(hr);

	return [l, a, b];
};

convert.rgb.ansi16 = function (args, saturation = null) {
	const [r, g, b] = args;
	let value = saturation === null ? convert.rgb.hsv(args)[2] : saturation; // Hsv -> ansi16 optimization

	value = Math.round(value / 50);

	if (value === 0) {
		return 30;
	}

	let ansi = 30
		+ ((Math.round(b / 255) << 2)
		| (Math.round(g / 255) << 1)
		| Math.round(r / 255));

	if (value === 2) {
		ansi += 60;
	}

	return ansi;
};

convert.hsv.ansi16 = function (args) {
	// Optimization here; we already know the value and don't need to get
	// it converted for us.
	return convert.rgb.ansi16(convert.hsv.rgb(args), args[2]);
};

convert.rgb.ansi256 = function (args) {
	const r = args[0];
	const g = args[1];
	const b = args[2];

	// We use the extended greyscale palette here, with the exception of
	// black and white. normal palette only has 4 greyscale shades.
	if (r === g && g === b) {
		if (r < 8) {
			return 16;
		}

		if (r > 248) {
			return 231;
		}

		return Math.round(((r - 8) / 247) * 24) + 232;
	}

	const ansi = 16
		+ (36 * Math.round(r / 255 * 5))
		+ (6 * Math.round(g / 255 * 5))
		+ Math.round(b / 255 * 5);

	return ansi;
};

convert.ansi16.rgb = function (args) {
	let color = args % 10;

	// Handle greyscale
	if (color === 0 || color === 7) {
		if (args > 50) {
			color += 3.5;
		}

		color = color / 10.5 * 255;

		return [color, color, color];
	}

	const mult = (~~(args > 50) + 1) * 0.5;
	const r = ((color & 1) * mult) * 255;
	const g = (((color >> 1) & 1) * mult) * 255;
	const b = (((color >> 2) & 1) * mult) * 255;

	return [r, g, b];
};

convert.ansi256.rgb = function (args) {
	// Handle greyscale
	if (args >= 232) {
		const c = (args - 232) * 10 + 8;
		return [c, c, c];
	}

	args -= 16;

	let rem;
	const r = Math.floor(args / 36) / 5 * 255;
	const g = Math.floor((rem = args % 36) / 6) / 5 * 255;
	const b = (rem % 6) / 5 * 255;

	return [r, g, b];
};

convert.rgb.hex = function (args) {
	const integer = ((Math.round(args[0]) & 0xFF) << 16)
		+ ((Math.round(args[1]) & 0xFF) << 8)
		+ (Math.round(args[2]) & 0xFF);

	const string = integer.toString(16).toUpperCase();
	return '000000'.substring(string.length) + string;
};

convert.hex.rgb = function (args) {
	const match = args.toString(16).match(/[a-f0-9]{6}|[a-f0-9]{3}/i);
	if (!match) {
		return [0, 0, 0];
	}

	let colorString = match[0];

	if (match[0].length === 3) {
		colorString = colorString.split('').map(char => {
			return char + char;
		}).join('');
	}

	const integer = parseInt(colorString, 16);
	const r = (integer >> 16) & 0xFF;
	const g = (integer >> 8) & 0xFF;
	const b = integer & 0xFF;

	return [r, g, b];
};

convert.rgb.hcg = function (rgb) {
	const r = rgb[0] / 255;
	const g = rgb[1] / 255;
	const b = rgb[2] / 255;
	const max = Math.max(Math.max(r, g), b);
	const min = Math.min(Math.min(r, g), b);
	const chroma = (max - min);
	let grayscale;
	let hue;

	if (chroma < 1) {
		grayscale = min / (1 - chroma);
	} else {
		grayscale = 0;
	}

	if (chroma <= 0) {
		hue = 0;
	} else
	if (max === r) {
		hue = ((g - b) / chroma) % 6;
	} else
	if (max === g) {
		hue = 2 + (b - r) / chroma;
	} else {
		hue = 4 + (r - g) / chroma;
	}

	hue /= 6;
	hue %= 1;

	return [hue * 360, chroma * 100, grayscale * 100];
};

convert.hsl.hcg = function (hsl) {
	const s = hsl[1] / 100;
	const l = hsl[2] / 100;

	const c = l < 0.5 ? (2.0 * s * l) : (2.0 * s * (1.0 - l));

	let f = 0;
	if (c < 1.0) {
		f = (l - 0.5 * c) / (1.0 - c);
	}

	return [hsl[0], c * 100, f * 100];
};

convert.hsv.hcg = function (hsv) {
	const s = hsv[1] / 100;
	const v = hsv[2] / 100;

	const c = s * v;
	let f = 0;

	if (c < 1.0) {
		f = (v - c) / (1 - c);
	}

	return [hsv[0], c * 100, f * 100];
};

convert.hcg.rgb = function (hcg) {
	const h = hcg[0] / 360;
	const c = hcg[1] / 100;
	const g = hcg[2] / 100;

	if (c === 0.0) {
		return [g * 255, g * 255, g * 255];
	}

	const pure = [0, 0, 0];
	const hi = (h % 1) * 6;
	const v = hi % 1;
	const w = 1 - v;
	let mg = 0;

	/* eslint-disable max-statements-per-line */
	switch (Math.floor(hi)) {
		case 0:
			pure[0] = 1; pure[1] = v; pure[2] = 0; break;
		case 1:
			pure[0] = w; pure[1] = 1; pure[2] = 0; break;
		case 2:
			pure[0] = 0; pure[1] = 1; pure[2] = v; break;
		case 3:
			pure[0] = 0; pure[1] = w; pure[2] = 1; break;
		case 4:
			pure[0] = v; pure[1] = 0; pure[2] = 1; break;
		default:
			pure[0] = 1; pure[1] = 0; pure[2] = w;
	}
	/* eslint-enable max-statements-per-line */

	mg = (1.0 - c) * g;

	return [
		(c * pure[0] + mg) * 255,
		(c * pure[1] + mg) * 255,
		(c * pure[2] + mg) * 255
	];
};

convert.hcg.hsv = function (hcg) {
	const c = hcg[1] / 100;
	const g = hcg[2] / 100;

	const v = c + g * (1.0 - c);
	let f = 0;

	if (v > 0.0) {
		f = c / v;
	}

	return [hcg[0], f * 100, v * 100];
};

convert.hcg.hsl = function (hcg) {
	const c = hcg[1] / 100;
	const g = hcg[2] / 100;

	const l = g * (1.0 - c) + 0.5 * c;
	let s = 0;

	if (l > 0.0 && l < 0.5) {
		s = c / (2 * l);
	} else
	if (l >= 0.5 && l < 1.0) {
		s = c / (2 * (1 - l));
	}

	return [hcg[0], s * 100, l * 100];
};

convert.hcg.hwb = function (hcg) {
	const c = hcg[1] / 100;
	const g = hcg[2] / 100;
	const v = c + g * (1.0 - c);
	return [hcg[0], (v - c) * 100, (1 - v) * 100];
};

convert.hwb.hcg = function (hwb) {
	const w = hwb[1] / 100;
	const b = hwb[2] / 100;
	const v = 1 - b;
	const c = v - w;
	let g = 0;

	if (c < 1) {
		g = (v - c) / (1 - c);
	}

	return [hwb[0], c * 100, g * 100];
};

convert.apple.rgb = function (apple) {
	return [(apple[0] / 65535) * 255, (apple[1] / 65535) * 255, (apple[2] / 65535) * 255];
};

convert.rgb.apple = function (rgb) {
	return [(rgb[0] / 255) * 65535, (rgb[1] / 255) * 65535, (rgb[2] / 255) * 65535];
};

convert.gray.rgb = function (args) {
	return [args[0] / 100 * 255, args[0] / 100 * 255, args[0] / 100 * 255];
};

convert.gray.hsl = function (args) {
	return [0, 0, args[0]];
};

convert.gray.hsv = convert.gray.hsl;

convert.gray.hwb = function (gray) {
	return [0, 100, gray[0]];
};

convert.gray.cmyk = function (gray) {
	return [0, 0, 0, gray[0]];
};

convert.gray.lab = function (gray) {
	return [gray[0], 0, 0];
};

convert.gray.hex = function (gray) {
	const val = Math.round(gray[0] / 100 * 255) & 0xFF;
	const integer = (val << 16) + (val << 8) + val;

	const string = integer.toString(16).toUpperCase();
	return '000000'.substring(string.length) + string;
};

convert.rgb.gray = function (rgb) {
	const val = (rgb[0] + rgb[1] + rgb[2]) / 3;
	return [val / 255 * 100];
};

/*
	This function routes a model to all other models.

	all functions that are routed have a property `.conversion` attached
	to the returned synthetic function. This property is an array
	of strings, each with the steps in between the 'from' and 'to'
	color models (inclusive).

	conversions that are not possible simply are not included.
*/

function buildGraph() {
	const graph = {};
	// https://jsperf.com/object-keys-vs-for-in-with-closure/3
	const models = Object.keys(conversions);

	for (let len = models.length, i = 0; i < len; i++) {
		graph[models[i]] = {
			// http://jsperf.com/1-vs-infinity
			// micro-opt, but this is simple.
			distance: -1,
			parent: null
		};
	}

	return graph;
}

// https://en.wikipedia.org/wiki/Breadth-first_search
function deriveBFS(fromModel) {
	const graph = buildGraph();
	const queue = [fromModel]; // Unshift -> queue -> pop

	graph[fromModel].distance = 0;

	while (queue.length) {
		const current = queue.pop();
		const adjacents = Object.keys(conversions[current]);

		for (let len = adjacents.length, i = 0; i < len; i++) {
			const adjacent = adjacents[i];
			const node = graph[adjacent];

			if (node.distance === -1) {
				node.distance = graph[current].distance + 1;
				node.parent = current;
				queue.unshift(adjacent);
			}
		}
	}

	return graph;
}

function link(from, to) {
	return function (args) {
		return to(from(args));
	};
}

function wrapConversion(toModel, graph) {
	const path = [graph[toModel].parent, toModel];
	let fn = conversions[graph[toModel].parent][toModel];

	let cur = graph[toModel].parent;
	while (graph[cur].parent) {
		path.unshift(graph[cur].parent);
		fn = link(conversions[graph[cur].parent][cur], fn);
		cur = graph[cur].parent;
	}

	fn.conversion = path;
	return fn;
}

var route = function (fromModel) {
	const graph = deriveBFS(fromModel);
	const conversion = {};

	const models = Object.keys(graph);
	for (let len = models.length, i = 0; i < len; i++) {
		const toModel = models[i];
		const node = graph[toModel];

		if (node.parent === null) {
			// No possible conversion, or this node is the source model.
			continue;
		}

		conversion[toModel] = wrapConversion(toModel, graph);
	}

	return conversion;
};

const convert$1 = {};

const models = Object.keys(conversions);

function wrapRaw(fn) {
	const wrappedFn = function (...args) {
		const arg0 = args[0];
		if (arg0 === undefined || arg0 === null) {
			return arg0;
		}

		if (arg0.length > 1) {
			args = arg0;
		}

		return fn(args);
	};

	// Preserve .conversion property if there is one
	if ('conversion' in fn) {
		wrappedFn.conversion = fn.conversion;
	}

	return wrappedFn;
}

function wrapRounded(fn) {
	const wrappedFn = function (...args) {
		const arg0 = args[0];

		if (arg0 === undefined || arg0 === null) {
			return arg0;
		}

		if (arg0.length > 1) {
			args = arg0;
		}

		const result = fn(args);

		// We're assuming the result is an array here.
		// see notice in conversions.js; don't use box types
		// in conversion functions.
		if (typeof result === 'object') {
			for (let len = result.length, i = 0; i < len; i++) {
				result[i] = Math.round(result[i]);
			}
		}

		return result;
	};

	// Preserve .conversion property if there is one
	if ('conversion' in fn) {
		wrappedFn.conversion = fn.conversion;
	}

	return wrappedFn;
}

models.forEach(fromModel => {
	convert$1[fromModel] = {};

	Object.defineProperty(convert$1[fromModel], 'channels', {value: conversions[fromModel].channels});
	Object.defineProperty(convert$1[fromModel], 'labels', {value: conversions[fromModel].labels});

	const routes = route(fromModel);
	const routeModels = Object.keys(routes);

	routeModels.forEach(toModel => {
		const fn = routes[toModel];

		convert$1[fromModel][toModel] = wrapRounded(fn);
		convert$1[fromModel][toModel].raw = wrapRaw(fn);
	});
});

var colorConvert = convert$1;

var colorizer = createCommonjsModule(function (module, exports) {
// Copyright (C) 2019 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.
Object.defineProperty(exports, "__esModule", { value: true });
exports.hslForSlice = exports.randomColor = exports.colorForThread = exports.colorForTid = exports.textColorForState = exports.colorForState = exports.hueForCpu = void 0;

const MD_PALETTE = [
    { c: 'red', h: 4, s: 90, l: 58 },
    { c: 'pink', h: 340, s: 82, l: 52 },
    { c: 'purple', h: 291, s: 64, l: 42 },
    { c: 'deep purple', h: 262, s: 52, l: 47 },
    { c: 'indigo', h: 231, s: 48, l: 48 },
    { c: 'blue', h: 207, s: 90, l: 54 },
    { c: 'light blue', h: 199, s: 98, l: 48 },
    { c: 'cyan', h: 187, s: 100, l: 42 },
    { c: 'teal', h: 174, s: 100, l: 29 },
    { c: 'green', h: 122, s: 39, l: 49 },
    { c: 'light green', h: 88, s: 50, l: 53 },
    { c: 'lime', h: 66, s: 70, l: 54 },
    { c: 'amber', h: 45, s: 100, l: 51 },
    { c: 'orange', h: 36, s: 100, l: 50 },
    { c: 'deep orange', h: 14, s: 100, l: 57 },
    { c: 'brown', h: 16, s: 25, l: 38 },
    { c: 'blue gray', h: 200, s: 18, l: 46 },
    { c: 'yellow', h: 54, s: 100, l: 62 },
];
const GREY_COLOR = {
    c: 'grey',
    h: 0,
    s: 0,
    l: 62
};
function hash(s, max) {
    let hash = 0x811c9dc5 & 0xfffffff;
    for (let i = 0; i < s.length; i++) {
        hash ^= s.charCodeAt(i);
        hash = (hash * 16777619) & 0xffffffff;
    }
    return Math.abs(hash) % max;
}
function hueForCpu(cpu) {
    return (128 + (32 * cpu)) % 256;
}
exports.hueForCpu = hueForCpu;
const DESAT_RED = {
    c: 'desat red',
    h: 3,
    s: 30,
    l: 49
};
const DARK_GREEN = {
    c: 'dark green',
    h: 120,
    s: 44,
    l: 34
};
const LIME_GREEN = {
    c: 'lime green',
    h: 75,
    s: 55,
    l: 47
};
const TRANSPARENT_WHITE = {
    c: 'white',
    h: 0,
    s: 1,
    l: 97,
    a: 0.55,
};
const ORANGE = {
    c: 'orange',
    h: 36,
    s: 100,
    l: 50
};
const INDIGO = {
    c: 'indigo',
    h: 231,
    s: 48,
    l: 48
};
function colorForState(state) {
    if (state === 'Running') {
        return DARK_GREEN;
    }
    else if (state.startsWith('Runnable')) {
        return LIME_GREEN;
    }
    else if (state.includes('Uninterruptible Sleep')) {
        if (state.includes('non-IO')) {
            return DESAT_RED;
        }
        return ORANGE;
    }
    else if (state.includes('Sleeping')) {
        return TRANSPARENT_WHITE;
    }
    return INDIGO;
}
exports.colorForState = colorForState;
function textColorForState(stateCode) {
    const background = colorForState(stateCode);
    return background.l > 80 ? '#404040' : '#fff';
}
exports.textColorForState = textColorForState;
function colorForTid(tid) {
    const colorIdx = hash(tid.toString(), MD_PALETTE.length);
    return Object.assign({}, MD_PALETTE[colorIdx]);
}
exports.colorForTid = colorForTid;
function colorForThread(thread) {
    if (thread === undefined) {
        return Object.assign({}, GREY_COLOR);
    }
    const tid = thread.pid ? thread.pid : thread.tid;
    return colorForTid(tid);
}
exports.colorForThread = colorForThread;
// 40 different random hues 9 degrees apart.
function randomColor() {
    const hue = Math.floor(Math.random() * 40) * 9;
    return '#' + colorConvert.hsl.hex([hue, 90, 30]);
}
exports.randomColor = randomColor;
// Chooses a color uniform at random based on hash(sliceName).  Returns [hue,
// saturation, lightness].
//
// Prefer converting this to an RGB color using hsluv, not the browser's
// built-in vanilla HSL handling.  This is because this function chooses
// hue/lightness uniform at random, but HSL is not perceptually uniform.  See
// https://www.boronine.com/2012/03/26/Color-Spaces-for-Human-Beings/.
//
// If isSelected, the color will be particularly dark, making it stand out.
function hslForSlice(sliceName, isSelected) {
    const hue = hash(sliceName, 360);
    // Saturation 100 would give the most differentiation between colors, but it's
    // garish.
    const saturation = 80;
    const lightness = isSelected ? 30 : hash(sliceName + 'x', 40) + 40;
    return [hue, saturation, lightness];
}
exports.hslForSlice = hslForSlice;

});

var tslib = createCommonjsModule(function (module) {
/*! *****************************************************************************
Copyright (c) Microsoft Corporation.

Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted.

THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
***************************************************************************** */

/* global global, define, System, Reflect, Promise */
var __extends;
var __assign;
var __rest;
var __decorate;
var __param;
var __metadata;
var __awaiter;
var __generator;
var __exportStar;
var __values;
var __read;
var __spread;
var __spreadArrays;
var __await;
var __asyncGenerator;
var __asyncDelegator;
var __asyncValues;
var __makeTemplateObject;
var __importStar;
var __importDefault;
var __classPrivateFieldGet;
var __classPrivateFieldSet;
var __createBinding;
(function (factory) {
    var root = typeof commonjsGlobal === "object" ? commonjsGlobal : typeof self === "object" ? self : typeof this === "object" ? this : {};
    {
        factory(createExporter(root, createExporter(module.exports)));
    }
    function createExporter(exports, previous) {
        if (exports !== root) {
            if (typeof Object.create === "function") {
                Object.defineProperty(exports, "__esModule", { value: true });
            }
            else {
                exports.__esModule = true;
            }
        }
        return function (id, v) { return exports[id] = previous ? previous(id, v) : v; };
    }
})
(function (exporter) {
    var extendStatics = Object.setPrototypeOf ||
        ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
        function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };

    __extends = function (d, b) {
        extendStatics(d, b);
        function __() { this.constructor = d; }
        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
    };

    __assign = Object.assign || function (t) {
        for (var s, i = 1, n = arguments.length; i < n; i++) {
            s = arguments[i];
            for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
        }
        return t;
    };

    __rest = function (s, e) {
        var t = {};
        for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
            t[p] = s[p];
        if (s != null && typeof Object.getOwnPropertySymbols === "function")
            for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
                if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
                    t[p[i]] = s[p[i]];
            }
        return t;
    };

    __decorate = function (decorators, target, key, desc) {
        var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
        if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
        else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
        return c > 3 && r && Object.defineProperty(target, key, r), r;
    };

    __param = function (paramIndex, decorator) {
        return function (target, key) { decorator(target, key, paramIndex); }
    };

    __metadata = function (metadataKey, metadataValue) {
        if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(metadataKey, metadataValue);
    };

    __awaiter = function (thisArg, _arguments, P, generator) {
        function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
        return new (P || (P = Promise))(function (resolve, reject) {
            function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
            function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
            function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
            step((generator = generator.apply(thisArg, _arguments || [])).next());
        });
    };

    __generator = function (thisArg, body) {
        var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
        return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
        function verb(n) { return function (v) { return step([n, v]); }; }
        function step(op) {
            if (f) throw new TypeError("Generator is already executing.");
            while (_) try {
                if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
                if (y = 0, t) op = [op[0] & 2, t.value];
                switch (op[0]) {
                    case 0: case 1: t = op; break;
                    case 4: _.label++; return { value: op[1], done: false };
                    case 5: _.label++; y = op[1]; op = [0]; continue;
                    case 7: op = _.ops.pop(); _.trys.pop(); continue;
                    default:
                        if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
                        if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
                        if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
                        if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
                        if (t[2]) _.ops.pop();
                        _.trys.pop(); continue;
                }
                op = body.call(thisArg, _);
            } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
            if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
        }
    };

    __createBinding = function(o, m, k, k2) {
        if (k2 === undefined) k2 = k;
        o[k2] = m[k];
    };

    __exportStar = function (m, exports) {
        for (var p in m) if (p !== "default" && !exports.hasOwnProperty(p)) exports[p] = m[p];
    };

    __values = function (o) {
        var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
        if (m) return m.call(o);
        if (o && typeof o.length === "number") return {
            next: function () {
                if (o && i >= o.length) o = void 0;
                return { value: o && o[i++], done: !o };
            }
        };
        throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
    };

    __read = function (o, n) {
        var m = typeof Symbol === "function" && o[Symbol.iterator];
        if (!m) return o;
        var i = m.call(o), r, ar = [], e;
        try {
            while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
        }
        catch (error) { e = { error: error }; }
        finally {
            try {
                if (r && !r.done && (m = i["return"])) m.call(i);
            }
            finally { if (e) throw e.error; }
        }
        return ar;
    };

    __spread = function () {
        for (var ar = [], i = 0; i < arguments.length; i++)
            ar = ar.concat(__read(arguments[i]));
        return ar;
    };

    __spreadArrays = function () {
        for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length;
        for (var r = Array(s), k = 0, i = 0; i < il; i++)
            for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++)
                r[k] = a[j];
        return r;
    };

    __await = function (v) {
        return this instanceof __await ? (this.v = v, this) : new __await(v);
    };

    __asyncGenerator = function (thisArg, _arguments, generator) {
        if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
        var g = generator.apply(thisArg, _arguments || []), i, q = [];
        return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i;
        function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; }
        function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } }
        function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r);  }
        function fulfill(value) { resume("next", value); }
        function reject(value) { resume("throw", value); }
        function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); }
    };

    __asyncDelegator = function (o) {
        var i, p;
        return i = {}, verb("next"), verb("throw", function (e) { throw e; }), verb("return"), i[Symbol.iterator] = function () { return this; }, i;
        function verb(n, f) { i[n] = o[n] ? function (v) { return (p = !p) ? { value: __await(o[n](v)), done: n === "return" } : f ? f(v) : v; } : f; }
    };

    __asyncValues = function (o) {
        if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
        var m = o[Symbol.asyncIterator], i;
        return m ? m.call(o) : (o = typeof __values === "function" ? __values(o) : o[Symbol.iterator](), i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i);
        function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; }
        function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); }
    };

    __makeTemplateObject = function (cooked, raw) {
        if (Object.defineProperty) { Object.defineProperty(cooked, "raw", { value: raw }); } else { cooked.raw = raw; }
        return cooked;
    };

    __importStar = function (mod) {
        if (mod && mod.__esModule) return mod;
        var result = {};
        if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
        result["default"] = mod;
        return result;
    };

    __importDefault = function (mod) {
        return (mod && mod.__esModule) ? mod : { "default": mod };
    };

    __classPrivateFieldGet = function (receiver, privateMap) {
        if (!privateMap.has(receiver)) {
            throw new TypeError("attempted to get private field on non-instance");
        }
        return privateMap.get(receiver);
    };

    __classPrivateFieldSet = function (receiver, privateMap, value) {
        if (!privateMap.has(receiver)) {
            throw new TypeError("attempted to set private field on non-instance");
        }
        privateMap.set(receiver, value);
        return value;
    };

    exporter("__extends", __extends);
    exporter("__assign", __assign);
    exporter("__rest", __rest);
    exporter("__decorate", __decorate);
    exporter("__param", __param);
    exporter("__metadata", __metadata);
    exporter("__awaiter", __awaiter);
    exporter("__generator", __generator);
    exporter("__exportStar", __exportStar);
    exporter("__createBinding", __createBinding);
    exporter("__values", __values);
    exporter("__read", __read);
    exporter("__spread", __spread);
    exporter("__spreadArrays", __spreadArrays);
    exporter("__await", __await);
    exporter("__asyncGenerator", __asyncGenerator);
    exporter("__asyncDelegator", __asyncDelegator);
    exporter("__asyncValues", __asyncValues);
    exporter("__makeTemplateObject", __makeTemplateObject);
    exporter("__importStar", __importStar);
    exporter("__importDefault", __importDefault);
    exporter("__classPrivateFieldGet", __classPrivateFieldGet);
    exporter("__classPrivateFieldSet", __classPrivateFieldSet);
});
});

var deferred = createCommonjsModule(function (module, exports) {
// 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.
Object.defineProperty(exports, "__esModule", { value: true });
exports.defer = void 0;
/**
 * Create a promise with exposed resolve and reject callbacks.
 */
function defer() {
    let resolve = null;
    let reject = null;
    const p = new Promise((res, rej) => [resolve, reject] = [res, rej]);
    return Object.assign(p, { resolve, reject });
}
exports.defer = defer;

});

var trace_to_text = createCommonjsModule(function (module, exports) {
var trace_to_text_wasm = (function() {
  var _scriptDir = typeof document !== 'undefined' && document.currentScript ? document.currentScript.src : undefined;
  if (typeof __filename !== 'undefined') _scriptDir = _scriptDir || __filename;
  return (
function(trace_to_text_wasm) {
  trace_to_text_wasm = trace_to_text_wasm || {};

var Module = typeof trace_to_text_wasm !== "undefined" ? trace_to_text_wasm : {};

var readyPromiseResolve, readyPromiseReject;

Module["ready"] = new Promise(function(resolve, reject) {
 readyPromiseResolve = resolve;
 readyPromiseReject = reject;
});

if (!Object.getOwnPropertyDescriptor(Module["ready"], "_main")) {
 Object.defineProperty(Module["ready"], "_main", {
  configurable: true,
  get: function() {
   abort("You are getting _main on the Promise object, instead of the instance. Use .then() to get called back with the instance, see the MODULARIZE docs in src/settings.js");
  }
 });
 Object.defineProperty(Module["ready"], "_main", {
  configurable: true,
  set: function() {
   abort("You are setting _main on the Promise object, instead of the instance. Use .then() to get called back with the instance, see the MODULARIZE docs in src/settings.js");
  }
 });
}

if (!Object.getOwnPropertyDescriptor(Module["ready"], "_emscripten_stack_get_end")) {
 Object.defineProperty(Module["ready"], "_emscripten_stack_get_end", {
  configurable: true,
  get: function() {
   abort("You are getting _emscripten_stack_get_end on the Promise object, instead of the instance. Use .then() to get called back with the instance, see the MODULARIZE docs in src/settings.js");
  }
 });
 Object.defineProperty(Module["ready"], "_emscripten_stack_get_end", {
  configurable: true,
  set: function() {
   abort("You are setting _emscripten_stack_get_end on the Promise object, instead of the instance. Use .then() to get called back with the instance, see the MODULARIZE docs in src/settings.js");
  }
 });
}

if (!Object.getOwnPropertyDescriptor(Module["ready"], "_emscripten_stack_get_free")) {
 Object.defineProperty(Module["ready"], "_emscripten_stack_get_free", {
  configurable: true,
  get: function() {
   abort("You are getting _emscripten_stack_get_free on the Promise object, instead of the instance. Use .then() to get called back with the instance, see the MODULARIZE docs in src/settings.js");
  }
 });
 Object.defineProperty(Module["ready"], "_emscripten_stack_get_free", {
  configurable: true,
  set: function() {
   abort("You are setting _emscripten_stack_get_free on the Promise object, instead of the instance. Use .then() to get called back with the instance, see the MODULARIZE docs in src/settings.js");
  }
 });
}

if (!Object.getOwnPropertyDescriptor(Module["ready"], "_emscripten_stack_init")) {
 Object.defineProperty(Module["ready"], "_emscripten_stack_init", {
  configurable: true,
  get: function() {
   abort("You are getting _emscripten_stack_init on the Promise object, instead of the instance. Use .then() to get called back with the instance, see the MODULARIZE docs in src/settings.js");
  }
 });
 Object.defineProperty(Module["ready"], "_emscripten_stack_init", {
  configurable: true,
  set: function() {
   abort("You are setting _emscripten_stack_init on the Promise object, instead of the instance. Use .then() to get called back with the instance, see the MODULARIZE docs in src/settings.js");
  }
 });
}

if (!Object.getOwnPropertyDescriptor(Module["ready"], "_stackSave")) {
 Object.defineProperty(Module["ready"], "_stackSave", {
  configurable: true,
  get: function() {
   abort("You are getting _stackSave on the Promise object, instead of the instance. Use .then() to get called back with the instance, see the MODULARIZE docs in src/settings.js");
  }
 });
 Object.defineProperty(Module["ready"], "_stackSave", {
  configurable: true,
  set: function() {
   abort("You are setting _stackSave on the Promise object, instead of the instance. Use .then() to get called back with the instance, see the MODULARIZE docs in src/settings.js");
  }
 });
}

if (!Object.getOwnPropertyDescriptor(Module["ready"], "_stackRestore")) {
 Object.defineProperty(Module["ready"], "_stackRestore", {
  configurable: true,
  get: function() {
   abort("You are getting _stackRestore on the Promise object, instead of the instance. Use .then() to get called back with the instance, see the MODULARIZE docs in src/settings.js");
  }
 });
 Object.defineProperty(Module["ready"], "_stackRestore", {
  configurable: true,
  set: function() {
   abort("You are setting _stackRestore on the Promise object, instead of the instance. Use .then() to get called back with the instance, see the MODULARIZE docs in src/settings.js");
  }
 });
}

if (!Object.getOwnPropertyDescriptor(Module["ready"], "_stackAlloc")) {
 Object.defineProperty(Module["ready"], "_stackAlloc", {
  configurable: true,
  get: function() {
   abort("You are getting _stackAlloc on the Promise object, instead of the instance. Use .then() to get called back with the instance, see the MODULARIZE docs in src/settings.js");
  }
 });
 Object.defineProperty(Module["ready"], "_stackAlloc", {
  configurable: true,
  set: function() {
   abort("You are setting _stackAlloc on the Promise object, instead of the instance. Use .then() to get called back with the instance, see the MODULARIZE docs in src/settings.js");
  }
 });
}

if (!Object.getOwnPropertyDescriptor(Module["ready"], "___wasm_call_ctors")) {
 Object.defineProperty(Module["ready"], "___wasm_call_ctors", {
  configurable: true,
  get: function() {
   abort("You are getting ___wasm_call_ctors on the Promise object, instead of the instance. Use .then() to get called back with the instance, see the MODULARIZE docs in src/settings.js");
  }
 });
 Object.defineProperty(Module["ready"], "___wasm_call_ctors", {
  configurable: true,
  set: function() {
   abort("You are setting ___wasm_call_ctors on the Promise object, instead of the instance. Use .then() to get called back with the instance, see the MODULARIZE docs in src/settings.js");
  }
 });
}

if (!Object.getOwnPropertyDescriptor(Module["ready"], "_fflush")) {
 Object.defineProperty(Module["ready"], "_fflush", {
  configurable: true,
  get: function() {
   abort("You are getting _fflush on the Promise object, instead of the instance. Use .then() to get called back with the instance, see the MODULARIZE docs in src/settings.js");
  }
 });
 Object.defineProperty(Module["ready"], "_fflush", {
  configurable: true,
  set: function() {
   abort("You are setting _fflush on the Promise object, instead of the instance. Use .then() to get called back with the instance, see the MODULARIZE docs in src/settings.js");
  }
 });
}

if (!Object.getOwnPropertyDescriptor(Module["ready"], "___errno_location")) {
 Object.defineProperty(Module["ready"], "___errno_location", {
  configurable: true,
  get: function() {
   abort("You are getting ___errno_location on the Promise object, instead of the instance. Use .then() to get called back with the instance, see the MODULARIZE docs in src/settings.js");
  }
 });
 Object.defineProperty(Module["ready"], "___errno_location", {
  configurable: true,
  set: function() {
   abort("You are setting ___errno_location on the Promise object, instead of the instance. Use .then() to get called back with the instance, see the MODULARIZE docs in src/settings.js");
  }
 });
}

if (!Object.getOwnPropertyDescriptor(Module["ready"], "_malloc")) {
 Object.defineProperty(Module["ready"], "_malloc", {
  configurable: true,
  get: function() {
   abort("You are getting _malloc on the Promise object, instead of the instance. Use .then() to get called back with the instance, see the MODULARIZE docs in src/settings.js");
  }
 });
 Object.defineProperty(Module["ready"], "_malloc", {
  configurable: true,
  set: function() {
   abort("You are setting _malloc on the Promise object, instead of the instance. Use .then() to get called back with the instance, see the MODULARIZE docs in src/settings.js");
  }
 });
}

if (!Object.getOwnPropertyDescriptor(Module["ready"], "_free")) {
 Object.defineProperty(Module["ready"], "_free", {
  configurable: true,
  get: function() {
   abort("You are getting _free on the Promise object, instead of the instance. Use .then() to get called back with the instance, see the MODULARIZE docs in src/settings.js");
  }
 });
 Object.defineProperty(Module["ready"], "_free", {
  configurable: true,
  set: function() {
   abort("You are setting _free on the Promise object, instead of the instance. Use .then() to get called back with the instance, see the MODULARIZE docs in src/settings.js");
  }
 });
}

if (!Object.getOwnPropertyDescriptor(Module["ready"], "_memalign")) {
 Object.defineProperty(Module["ready"], "_memalign", {
  configurable: true,
  get: function() {
   abort("You are getting _memalign on the Promise object, instead of the instance. Use .then() to get called back with the instance, see the MODULARIZE docs in src/settings.js");
  }
 });
 Object.defineProperty(Module["ready"], "_memalign", {
  configurable: true,
  set: function() {
   abort("You are setting _memalign on the Promise object, instead of the instance. Use .then() to get called back with the instance, see the MODULARIZE docs in src/settings.js");
  }
 });
}

if (!Object.getOwnPropertyDescriptor(Module["ready"], "_memset")) {
 Object.defineProperty(Module["ready"], "_memset", {
  configurable: true,
  get: function() {
   abort("You are getting _memset on the Promise object, instead of the instance. Use .then() to get called back with the instance, see the MODULARIZE docs in src/settings.js");
  }
 });
 Object.defineProperty(Module["ready"], "_memset", {
  configurable: true,
  set: function() {
   abort("You are setting _memset on the Promise object, instead of the instance. Use .then() to get called back with the instance, see the MODULARIZE docs in src/settings.js");
  }
 });
}

if (!Object.getOwnPropertyDescriptor(Module["ready"], "__get_tzname")) {
 Object.defineProperty(Module["ready"], "__get_tzname", {
  configurable: true,
  get: function() {
   abort("You are getting __get_tzname on the Promise object, instead of the instance. Use .then() to get called back with the instance, see the MODULARIZE docs in src/settings.js");
  }
 });
 Object.defineProperty(Module["ready"], "__get_tzname", {
  configurable: true,
  set: function() {
   abort("You are setting __get_tzname on the Promise object, instead of the instance. Use .then() to get called back with the instance, see the MODULARIZE docs in src/settings.js");
  }
 });
}

if (!Object.getOwnPropertyDescriptor(Module["ready"], "__get_daylight")) {
 Object.defineProperty(Module["ready"], "__get_daylight", {
  configurable: true,
  get: function() {
   abort("You are getting __get_daylight on the Promise object, instead of the instance. Use .then() to get called back with the instance, see the MODULARIZE docs in src/settings.js");
  }
 });
 Object.defineProperty(Module["ready"], "__get_daylight", {
  configurable: true,
  set: function() {
   abort("You are setting __get_daylight on the Promise object, instead of the instance. Use .then() to get called back with the instance, see the MODULARIZE docs in src/settings.js");
  }
 });
}

if (!Object.getOwnPropertyDescriptor(Module["ready"], "__get_timezone")) {
 Object.defineProperty(Module["ready"], "__get_timezone", {
  configurable: true,
  get: function() {
   abort("You are getting __get_timezone on the Promise object, instead of the instance. Use .then() to get called back with the instance, see the MODULARIZE docs in src/settings.js");
  }
 });
 Object.defineProperty(Module["ready"], "__get_timezone", {
  configurable: true,
  set: function() {
   abort("You are setting __get_timezone on the Promise object, instead of the instance. Use .then() to get called back with the instance, see the MODULARIZE docs in src/settings.js");
  }
 });
}

if (!Object.getOwnPropertyDescriptor(Module["ready"], "_emscripten_main_thread_process_queued_calls")) {
 Object.defineProperty(Module["ready"], "_emscripten_main_thread_process_queued_calls", {
  configurable: true,
  get: function() {
   abort("You are getting _emscripten_main_thread_process_queued_calls on the Promise object, instead of the instance. Use .then() to get called back with the instance, see the MODULARIZE docs in src/settings.js");
  }
 });
 Object.defineProperty(Module["ready"], "_emscripten_main_thread_process_queued_calls", {
  configurable: true,
  set: function() {
   abort("You are setting _emscripten_main_thread_process_queued_calls on the Promise object, instead of the instance. Use .then() to get called back with the instance, see the MODULARIZE docs in src/settings.js");
  }
 });
}

if (!Object.getOwnPropertyDescriptor(Module["ready"], "_usleep")) {
 Object.defineProperty(Module["ready"], "_usleep", {
  configurable: true,
  get: function() {
   abort("You are getting _usleep on the Promise object, instead of the instance. Use .then() to get called back with the instance, see the MODULARIZE docs in src/settings.js");
  }
 });
 Object.defineProperty(Module["ready"], "_usleep", {
  configurable: true,
  set: function() {
   abort("You are setting _usleep on the Promise object, instead of the instance. Use .then() to get called back with the instance, see the MODULARIZE docs in src/settings.js");
  }
 });
}

if (!Object.getOwnPropertyDescriptor(Module["ready"], "onRuntimeInitialized")) {
 Object.defineProperty(Module["ready"], "onRuntimeInitialized", {
  configurable: true,
  get: function() {
   abort("You are getting onRuntimeInitialized on the Promise object, instead of the instance. Use .then() to get called back with the instance, see the MODULARIZE docs in src/settings.js");
  }
 });
 Object.defineProperty(Module["ready"], "onRuntimeInitialized", {
  configurable: true,
  set: function() {
   abort("You are setting onRuntimeInitialized on the Promise object, instead of the instance. Use .then() to get called back with the instance, see the MODULARIZE docs in src/settings.js");
  }
 });
}

var moduleOverrides = {};

var key;

for (key in Module) {
 if (Module.hasOwnProperty(key)) {
  moduleOverrides[key] = Module[key];
 }
}

var arguments_ = [];

var thisProgram = "./this.program";

var quit_ = function(status, toThrow) {
 throw toThrow;
};

var ENVIRONMENT_IS_WEB = false;

var ENVIRONMENT_IS_WORKER = false;

var ENVIRONMENT_IS_NODE = false;

var ENVIRONMENT_IS_SHELL = false;

ENVIRONMENT_IS_WEB = typeof window === "object";

ENVIRONMENT_IS_WORKER = typeof importScripts === "function";

ENVIRONMENT_IS_NODE = typeof process === "object" && typeof process.versions === "object" && typeof process.versions.node === "string";

ENVIRONMENT_IS_SHELL = !ENVIRONMENT_IS_WEB && !ENVIRONMENT_IS_NODE && !ENVIRONMENT_IS_WORKER;

if (Module["ENVIRONMENT"]) {
 throw new Error("Module.ENVIRONMENT has been deprecated. To force the environment, use the ENVIRONMENT compile-time option (for example, -s ENVIRONMENT=web or -s ENVIRONMENT=node)");
}

var scriptDirectory = "";

function locateFile(path) {
 if (Module["locateFile"]) {
  return Module["locateFile"](path, scriptDirectory);
 }
 return scriptDirectory + path;
}

var read_, readBinary;

var nodeFS;

var nodePath;

if (ENVIRONMENT_IS_NODE) {
 if (ENVIRONMENT_IS_WORKER) {
  scriptDirectory = require("path").dirname(scriptDirectory) + "/";
 } else {
  scriptDirectory = __dirname + "/";
 }
 read_ = function shell_read(filename, binary) {
  if (!nodeFS) nodeFS = require("fs");
  if (!nodePath) nodePath = require("path");
  filename = nodePath["normalize"](filename);
  return nodeFS["readFileSync"](filename, binary ? null : "utf8");
 };
 readBinary = function readBinary(filename) {
  var ret = read_(filename, true);
  if (!ret.buffer) {
   ret = new Uint8Array(ret);
  }
  assert(ret.buffer);
  return ret;
 };
 if (process["argv"].length > 1) {
  thisProgram = process["argv"][1].replace(/\\/g, "/");
 }
 arguments_ = process["argv"].slice(2);
 process["on"]("uncaughtException", function(ex) {
  if (!(ex instanceof ExitStatus)) {
   throw ex;
  }
 });
 process["on"]("unhandledRejection", abort);
 quit_ = function(status) {
  process["exit"](status);
 };
 Module["inspect"] = function() {
  return "[Emscripten Module object]";
 };
} else if (ENVIRONMENT_IS_SHELL) {
 if (typeof read != "undefined") {
  read_ = function shell_read(f) {
   return read(f);
  };
 }
 readBinary = function readBinary(f) {
  var data;
  if (typeof readbuffer === "function") {
   return new Uint8Array(readbuffer(f));
  }
  data = read(f, "binary");
  assert(typeof data === "object");
  return data;
 };
 if (typeof scriptArgs != "undefined") {
  arguments_ = scriptArgs;
 } else if (typeof arguments != "undefined") {
  arguments_ = arguments;
 }
 if (typeof quit === "function") {
  quit_ = function(status) {
   quit(status);
  };
 }
 if (typeof print !== "undefined") {
  if (typeof console === "undefined") console = {};
  console.log = print;
  console.warn = console.error = typeof printErr !== "undefined" ? printErr : print;
 }
} else if (ENVIRONMENT_IS_WEB || ENVIRONMENT_IS_WORKER) {
 if (ENVIRONMENT_IS_WORKER) {
  scriptDirectory = self.location.href;
 } else if (typeof document !== "undefined" && document.currentScript) {
  scriptDirectory = document.currentScript.src;
 }
 if (_scriptDir) {
  scriptDirectory = _scriptDir;
 }
 if (scriptDirectory.indexOf("blob:") !== 0) {
  scriptDirectory = scriptDirectory.substr(0, scriptDirectory.lastIndexOf("/") + 1);
 } else {
  scriptDirectory = "";
 }
 {
  read_ = function(url) {
   var xhr = new XMLHttpRequest();
   xhr.open("GET", url, false);
   xhr.send(null);
   return xhr.responseText;
  };
  if (ENVIRONMENT_IS_WORKER) {
   readBinary = function(url) {
    var xhr = new XMLHttpRequest();
    xhr.open("GET", url, false);
    xhr.responseType = "arraybuffer";
    xhr.send(null);
    return new Uint8Array(xhr.response);
   };
  }
 }
} else {
 throw new Error("environment detection error");
}

var out = Module["print"] || console.log.bind(console);

var err = Module["printErr"] || console.warn.bind(console);

for (key in moduleOverrides) {
 if (moduleOverrides.hasOwnProperty(key)) {
  Module[key] = moduleOverrides[key];
 }
}

moduleOverrides = null;

if (Module["arguments"]) arguments_ = Module["arguments"];

if (!Object.getOwnPropertyDescriptor(Module, "arguments")) Object.defineProperty(Module, "arguments", {
 configurable: true,
 get: function() {
  abort("Module.arguments has been replaced with plain arguments_ (the initial value can be provided on Module, but after startup the value is only looked for on a local variable of that name)");
 }
});

if (Module["thisProgram"]) thisProgram = Module["thisProgram"];

if (!Object.getOwnPropertyDescriptor(Module, "thisProgram")) Object.defineProperty(Module, "thisProgram", {
 configurable: true,
 get: function() {
  abort("Module.thisProgram has been replaced with plain thisProgram (the initial value can be provided on Module, but after startup the value is only looked for on a local variable of that name)");
 }
});

if (Module["quit"]) quit_ = Module["quit"];

if (!Object.getOwnPropertyDescriptor(Module, "quit")) Object.defineProperty(Module, "quit", {
 configurable: true,
 get: function() {
  abort("Module.quit has been replaced with plain quit_ (the initial value can be provided on Module, but after startup the value is only looked for on a local variable of that name)");
 }
});

assert(typeof Module["memoryInitializerPrefixURL"] === "undefined", "Module.memoryInitializerPrefixURL option was removed, use Module.locateFile instead");

assert(typeof Module["pthreadMainPrefixURL"] === "undefined", "Module.pthreadMainPrefixURL option was removed, use Module.locateFile instead");

assert(typeof Module["cdInitializerPrefixURL"] === "undefined", "Module.cdInitializerPrefixURL option was removed, use Module.locateFile instead");

assert(typeof Module["filePackagePrefixURL"] === "undefined", "Module.filePackagePrefixURL option was removed, use Module.locateFile instead");

assert(typeof Module["read"] === "undefined", "Module.read option was removed (modify read_ in JS)");

assert(typeof Module["readAsync"] === "undefined", "Module.readAsync option was removed (modify readAsync in JS)");

assert(typeof Module["readBinary"] === "undefined", "Module.readBinary option was removed (modify readBinary in JS)");

assert(typeof Module["setWindowTitle"] === "undefined", "Module.setWindowTitle option was removed (modify setWindowTitle in JS)");

assert(typeof Module["TOTAL_MEMORY"] === "undefined", "Module.TOTAL_MEMORY has been renamed Module.INITIAL_MEMORY");

if (!Object.getOwnPropertyDescriptor(Module, "read")) Object.defineProperty(Module, "read", {
 configurable: true,
 get: function() {
  abort("Module.read has been replaced with plain read_ (the initial value can be provided on Module, but after startup the value is only looked for on a local variable of that name)");
 }
});

if (!Object.getOwnPropertyDescriptor(Module, "readAsync")) Object.defineProperty(Module, "readAsync", {
 configurable: true,
 get: function() {
  abort("Module.readAsync has been replaced with plain readAsync (the initial value can be provided on Module, but after startup the value is only looked for on a local variable of that name)");
 }
});

if (!Object.getOwnPropertyDescriptor(Module, "readBinary")) Object.defineProperty(Module, "readBinary", {
 configurable: true,
 get: function() {
  abort("Module.readBinary has been replaced with plain readBinary (the initial value can be provided on Module, but after startup the value is only looked for on a local variable of that name)");
 }
});

if (!Object.getOwnPropertyDescriptor(Module, "setWindowTitle")) Object.defineProperty(Module, "setWindowTitle", {
 configurable: true,
 get: function() {
  abort("Module.setWindowTitle has been replaced with plain setWindowTitle (the initial value can be provided on Module, but after startup the value is only looked for on a local variable of that name)");
 }
});

var STACK_ALIGN = 16;

function alignMemory(size, factor) {
 if (!factor) factor = STACK_ALIGN;
 return Math.ceil(size / factor) * factor;
}

function warnOnce(text) {
 if (!warnOnce.shown) warnOnce.shown = {};
 if (!warnOnce.shown[text]) {
  warnOnce.shown[text] = 1;
  err(text);
 }
}

function convertJsFunctionToWasm(func, sig) {
 if (typeof WebAssembly.Function === "function") {
  var typeNames = {
   "i": "i32",
   "j": "i64",
   "f": "f32",
   "d": "f64"
  };
  var type = {
   parameters: [],
   results: sig[0] == "v" ? [] : [ typeNames[sig[0]] ]
  };
  for (var i = 1; i < sig.length; ++i) {
   type.parameters.push(typeNames[sig[i]]);
  }
  return new WebAssembly.Function(type, func);
 }
 var typeSection = [ 1, 0, 1, 96 ];
 var sigRet = sig.slice(0, 1);
 var sigParam = sig.slice(1);
 var typeCodes = {
  "i": 127,
  "j": 126,
  "f": 125,
  "d": 124
 };
 typeSection.push(sigParam.length);
 for (var i = 0; i < sigParam.length; ++i) {
  typeSection.push(typeCodes[sigParam[i]]);
 }
 if (sigRet == "v") {
  typeSection.push(0);
 } else {
  typeSection = typeSection.concat([ 1, typeCodes[sigRet] ]);
 }
 typeSection[1] = typeSection.length - 2;
 var bytes = new Uint8Array([ 0, 97, 115, 109, 1, 0, 0, 0 ].concat(typeSection, [ 2, 7, 1, 1, 101, 1, 102, 0, 0, 7, 5, 1, 1, 102, 0, 0 ]));
 var module = new WebAssembly.Module(bytes);
 var instance = new WebAssembly.Instance(module, {
  "e": {
   "f": func
  }
 });
 var wrappedFunc = instance.exports["f"];
 return wrappedFunc;
}

var freeTableIndexes = [];

var functionsInTableMap;

function getEmptyTableSlot() {
 if (freeTableIndexes.length) {
  return freeTableIndexes.pop();
 }
 try {
  wasmTable.grow(1);
 } catch (err) {
  if (!(err instanceof RangeError)) {
   throw err;
  }
  throw "Unable to grow wasm table. Set ALLOW_TABLE_GROWTH.";
 }
 return wasmTable.length - 1;
}

function addFunctionWasm(func, sig) {
 if (!functionsInTableMap) {
  functionsInTableMap = new WeakMap();
  for (var i = 0; i < wasmTable.length; i++) {
   var item = wasmTable.get(i);
   if (item) {
    functionsInTableMap.set(item, i);
   }
  }
 }
 if (functionsInTableMap.has(func)) {
  return functionsInTableMap.get(func);
 }
 var ret = getEmptyTableSlot();
 try {
  wasmTable.set(ret, func);
 } catch (err) {
  if (!(err instanceof TypeError)) {
   throw err;
  }
  assert(typeof sig !== "undefined", "Missing signature argument to addFunction: " + func);
  var wrapped = convertJsFunctionToWasm(func, sig);
  wasmTable.set(ret, wrapped);
 }
 functionsInTableMap.set(func, ret);
 return ret;
}

function addFunction(func, sig) {
 assert(typeof func !== "undefined");
 return addFunctionWasm(func, sig);
}

var wasmBinary;

if (Module["wasmBinary"]) wasmBinary = Module["wasmBinary"];

if (!Object.getOwnPropertyDescriptor(Module, "wasmBinary")) Object.defineProperty(Module, "wasmBinary", {
 configurable: true,
 get: function() {
  abort("Module.wasmBinary has been replaced with plain wasmBinary (the initial value can be provided on Module, but after startup the value is only looked for on a local variable of that name)");
 }
});

var noExitRuntime;

if (Module["noExitRuntime"]) noExitRuntime = Module["noExitRuntime"];

if (!Object.getOwnPropertyDescriptor(Module, "noExitRuntime")) Object.defineProperty(Module, "noExitRuntime", {
 configurable: true,
 get: function() {
  abort("Module.noExitRuntime has been replaced with plain noExitRuntime (the initial value can be provided on Module, but after startup the value is only looked for on a local variable of that name)");
 }
});

if (typeof WebAssembly !== "object") {
 abort("no native wasm support detected");
}

var wasmMemory;

var ABORT = false;

function assert(condition, text) {
 if (!condition) {
  abort("Assertion failed: " + text);
 }
}

function getCFunc(ident) {
 var func = Module["_" + ident];
 assert(func, "Cannot call unknown function " + ident + ", make sure it is exported");
 return func;
}

function ccall(ident, returnType, argTypes, args, opts) {
 var toC = {
  "string": function(str) {
   var ret = 0;
   if (str !== null && str !== undefined && str !== 0) {
    var len = (str.length << 2) + 1;
    ret = stackAlloc(len);
    stringToUTF8(str, ret, len);
   }
   return ret;
  },
  "array": function(arr) {
   var ret = stackAlloc(arr.length);
   writeArrayToMemory(arr, ret);
   return ret;
  }
 };
 function convertReturnValue(ret) {
  if (returnType === "string") return UTF8ToString(ret);
  if (returnType === "boolean") return Boolean(ret);
  return ret;
 }
 var func = getCFunc(ident);
 var cArgs = [];
 var stack = 0;
 assert(returnType !== "array", 'Return type should not be "array".');
 if (args) {
  for (var i = 0; i < args.length; i++) {
   var converter = toC[argTypes[i]];
   if (converter) {
    if (stack === 0) stack = stackSave();
    cArgs[i] = converter(args[i]);
   } else {
    cArgs[i] = args[i];
   }
  }
 }
 var ret = func.apply(null, cArgs);
 ret = convertReturnValue(ret);
 if (stack !== 0) stackRestore(stack);
 return ret;
}

var UTF8Decoder = typeof TextDecoder !== "undefined" ? new TextDecoder("utf8") : undefined;

function UTF8ArrayToString(heap, idx, maxBytesToRead) {
 var endIdx = idx + maxBytesToRead;
 var endPtr = idx;
 while (heap[endPtr] && !(endPtr >= endIdx)) ++endPtr;
 if (endPtr - idx > 16 && heap.subarray && UTF8Decoder) {
  return UTF8Decoder.decode(heap.subarray(idx, endPtr));
 } else {
  var str = "";
  while (idx < endPtr) {
   var u0 = heap[idx++];
   if (!(u0 & 128)) {
    str += String.fromCharCode(u0);
    continue;
   }
   var u1 = heap[idx++] & 63;
   if ((u0 & 224) == 192) {
    str += String.fromCharCode((u0 & 31) << 6 | u1);
    continue;
   }
   var u2 = heap[idx++] & 63;
   if ((u0 & 240) == 224) {
    u0 = (u0 & 15) << 12 | u1 << 6 | u2;
   } else {
    if ((u0 & 248) != 240) warnOnce("Invalid UTF-8 leading byte 0x" + u0.toString(16) + " encountered when deserializing a UTF-8 string on the asm.js/wasm heap to a JS string!");
    u0 = (u0 & 7) << 18 | u1 << 12 | u2 << 6 | heap[idx++] & 63;
   }
   if (u0 < 65536) {
    str += String.fromCharCode(u0);
   } else {
    var ch = u0 - 65536;
    str += String.fromCharCode(55296 | ch >> 10, 56320 | ch & 1023);
   }
  }
 }
 return str;
}

function UTF8ToString(ptr, maxBytesToRead) {
 return ptr ? UTF8ArrayToString(HEAPU8, ptr, maxBytesToRead) : "";
}

function stringToUTF8Array(str, heap, outIdx, maxBytesToWrite) {
 if (!(maxBytesToWrite > 0)) return 0;
 var startIdx = outIdx;
 var endIdx = outIdx + maxBytesToWrite - 1;
 for (var i = 0; i < str.length; ++i) {
  var u = str.charCodeAt(i);
  if (u >= 55296 && u <= 57343) {
   var u1 = str.charCodeAt(++i);
   u = 65536 + ((u & 1023) << 10) | u1 & 1023;
  }
  if (u <= 127) {
   if (outIdx >= endIdx) break;
   heap[outIdx++] = u;
  } else if (u <= 2047) {
   if (outIdx + 1 >= endIdx) break;
   heap[outIdx++] = 192 | u >> 6;
   heap[outIdx++] = 128 | u & 63;
  } else if (u <= 65535) {
   if (outIdx + 2 >= endIdx) break;
   heap[outIdx++] = 224 | u >> 12;
   heap[outIdx++] = 128 | u >> 6 & 63;
   heap[outIdx++] = 128 | u & 63;
  } else {
   if (outIdx + 3 >= endIdx) break;
   if (u >= 2097152) warnOnce("Invalid Unicode code point 0x" + u.toString(16) + " encountered when serializing a JS string to an UTF-8 string on the asm.js/wasm heap! (Valid unicode code points should be in range 0-0x1FFFFF).");
   heap[outIdx++] = 240 | u >> 18;
   heap[outIdx++] = 128 | u >> 12 & 63;
   heap[outIdx++] = 128 | u >> 6 & 63;
   heap[outIdx++] = 128 | u & 63;
  }
 }
 heap[outIdx] = 0;
 return outIdx - startIdx;
}

function stringToUTF8(str, outPtr, maxBytesToWrite) {
 assert(typeof maxBytesToWrite == "number", "stringToUTF8(str, outPtr, maxBytesToWrite) is missing the third parameter that specifies the length of the output buffer!");
 return stringToUTF8Array(str, HEAPU8, outPtr, maxBytesToWrite);
}

function lengthBytesUTF8(str) {
 var len = 0;
 for (var i = 0; i < str.length; ++i) {
  var u = str.charCodeAt(i);
  if (u >= 55296 && u <= 57343) u = 65536 + ((u & 1023) << 10) | str.charCodeAt(++i) & 1023;
  if (u <= 127) ++len; else if (u <= 2047) len += 2; else if (u <= 65535) len += 3; else len += 4;
 }
 return len;
}

typeof TextDecoder !== "undefined" ? new TextDecoder("utf-16le") : undefined;

function allocateUTF8(str) {
 var size = lengthBytesUTF8(str) + 1;
 var ret = _malloc(size);
 if (ret) stringToUTF8Array(str, HEAP8, ret, size);
 return ret;
}

function allocateUTF8OnStack(str) {
 var size = lengthBytesUTF8(str) + 1;
 var ret = stackAlloc(size);
 stringToUTF8Array(str, HEAP8, ret, size);
 return ret;
}

function writeArrayToMemory(array, buffer) {
 assert(array.length >= 0, "writeArrayToMemory array must have a length (should be an array or typed array)");
 HEAP8.set(array, buffer);
}

function writeAsciiToMemory(str, buffer, dontAddNull) {
 for (var i = 0; i < str.length; ++i) {
  assert(str.charCodeAt(i) === str.charCodeAt(i) & 255);
  HEAP8[buffer++ >> 0] = str.charCodeAt(i);
 }
 if (!dontAddNull) HEAP8[buffer >> 0] = 0;
}

function alignUp(x, multiple) {
 if (x % multiple > 0) {
  x += multiple - x % multiple;
 }
 return x;
}

var buffer, HEAP8, HEAPU8, HEAP16, HEAP32, HEAPU32;

function updateGlobalBufferAndViews(buf) {
 buffer = buf;
 Module["HEAP8"] = HEAP8 = new Int8Array(buf);
 Module["HEAP16"] = HEAP16 = new Int16Array(buf);
 Module["HEAP32"] = HEAP32 = new Int32Array(buf);
 Module["HEAPU8"] = HEAPU8 = new Uint8Array(buf);
 Module["HEAPU16"] = new Uint16Array(buf);
 Module["HEAPU32"] = HEAPU32 = new Uint32Array(buf);
 Module["HEAPF32"] = new Float32Array(buf);
 Module["HEAPF64"] = new Float64Array(buf);
}

var TOTAL_STACK = 5242880;

if (Module["TOTAL_STACK"]) assert(TOTAL_STACK === Module["TOTAL_STACK"], "the stack size can no longer be determined at runtime");

var INITIAL_MEMORY = Module["INITIAL_MEMORY"] || 33554432;

if (!Object.getOwnPropertyDescriptor(Module, "INITIAL_MEMORY")) Object.defineProperty(Module, "INITIAL_MEMORY", {
 configurable: true,
 get: function() {
  abort("Module.INITIAL_MEMORY has been replaced with plain INITIAL_MEMORY (the initial value can be provided on Module, but after startup the value is only looked for on a local variable of that name)");
 }
});

assert(INITIAL_MEMORY >= TOTAL_STACK, "INITIAL_MEMORY should be larger than TOTAL_STACK, was " + INITIAL_MEMORY + "! (TOTAL_STACK=" + TOTAL_STACK + ")");

assert(typeof Int32Array !== "undefined" && typeof Float64Array !== "undefined" && Int32Array.prototype.subarray !== undefined && Int32Array.prototype.set !== undefined, "JS engine does not provide full typed array support");

assert(!Module["wasmMemory"], "Use of `wasmMemory` detected.  Use -s IMPORTED_MEMORY to define wasmMemory externally");

assert(INITIAL_MEMORY == 33554432, "Detected runtime INITIAL_MEMORY setting.  Use -s IMPORTED_MEMORY to define wasmMemory dynamically");

var wasmTable;

function writeStackCookie() {
 var max = _emscripten_stack_get_end();
 assert((max & 3) == 0);
 HEAPU32[(max >> 2) + 1] = 34821223;
 HEAPU32[(max >> 2) + 2] = 2310721022;
 HEAP32[0] = 1668509029;
}

function checkStackCookie() {
 if (ABORT) return;
 var max = _emscripten_stack_get_end();
 var cookie1 = HEAPU32[(max >> 2) + 1];
 var cookie2 = HEAPU32[(max >> 2) + 2];
 if (cookie1 != 34821223 || cookie2 != 2310721022) {
  abort("Stack overflow! Stack cookie has been overwritten, expected hex dwords 0x89BACDFE and 0x2135467, but received 0x" + cookie2.toString(16) + " " + cookie1.toString(16));
 }
 if (HEAP32[0] !== 1668509029) abort("Runtime error: The application has corrupted its heap memory area (address zero)!");
}

(function() {
 var h16 = new Int16Array(1);
 var h8 = new Int8Array(h16.buffer);
 h16[0] = 25459;
 if (h8[0] !== 115 || h8[1] !== 99) throw "Runtime error: expected the system to be little-endian!";
})();

var __ATPRERUN__ = [];

var __ATINIT__ = [];

var __ATMAIN__ = [];

var __ATPOSTRUN__ = [];

var runtimeInitialized = false;

var runtimeExited = false;

__ATINIT__.push({
 func: function() {
  ___wasm_call_ctors();
 }
});

function preRun() {
 if (Module["preRun"]) {
  if (typeof Module["preRun"] == "function") Module["preRun"] = [ Module["preRun"] ];
  while (Module["preRun"].length) {
   addOnPreRun(Module["preRun"].shift());
  }
 }
 callRuntimeCallbacks(__ATPRERUN__);
}

function initRuntime() {
 checkStackCookie();
 assert(!runtimeInitialized);
 runtimeInitialized = true;
 if (!Module["noFSInit"] && !FS.init.initialized) FS.init();
 TTY.init();
 callRuntimeCallbacks(__ATINIT__);
}

function preMain() {
 checkStackCookie();
 FS.ignorePermissions = false;
 callRuntimeCallbacks(__ATMAIN__);
}

function exitRuntime() {
 checkStackCookie();
 runtimeExited = true;
}

function postRun() {
 checkStackCookie();
 if (Module["postRun"]) {
  if (typeof Module["postRun"] == "function") Module["postRun"] = [ Module["postRun"] ];
  while (Module["postRun"].length) {
   addOnPostRun(Module["postRun"].shift());
  }
 }
 callRuntimeCallbacks(__ATPOSTRUN__);
}

function addOnPreRun(cb) {
 __ATPRERUN__.unshift(cb);
}

function addOnPostRun(cb) {
 __ATPOSTRUN__.unshift(cb);
}

assert(Math.imul, "This browser does not support Math.imul(), build with LEGACY_VM_SUPPORT or POLYFILL_OLD_MATH_FUNCTIONS to add in a polyfill");

assert(Math.fround, "This browser does not support Math.fround(), build with LEGACY_VM_SUPPORT or POLYFILL_OLD_MATH_FUNCTIONS to add in a polyfill");

assert(Math.clz32, "This browser does not support Math.clz32(), build with LEGACY_VM_SUPPORT or POLYFILL_OLD_MATH_FUNCTIONS to add in a polyfill");

assert(Math.trunc, "This browser does not support Math.trunc(), build with LEGACY_VM_SUPPORT or POLYFILL_OLD_MATH_FUNCTIONS to add in a polyfill");

var runDependencies = 0;

var runDependencyWatcher = null;

var dependenciesFulfilled = null;

var runDependencyTracking = {};

function getUniqueRunDependency(id) {
 var orig = id;
 while (1) {
  if (!runDependencyTracking[id]) return id;
  id = orig + Math.random();
 }
}

function addRunDependency(id) {
 runDependencies++;
 if (Module["monitorRunDependencies"]) {
  Module["monitorRunDependencies"](runDependencies);
 }
 if (id) {
  assert(!runDependencyTracking[id]);
  runDependencyTracking[id] = 1;
  if (runDependencyWatcher === null && typeof setInterval !== "undefined") {
   runDependencyWatcher = setInterval(function() {
    if (ABORT) {
     clearInterval(runDependencyWatcher);
     runDependencyWatcher = null;
     return;
    }
    var shown = false;
    for (var dep in runDependencyTracking) {
     if (!shown) {
      shown = true;
      err("still waiting on run dependencies:");
     }
     err("dependency: " + dep);
    }
    if (shown) {
     err("(end of list)");
    }
   }, 1e4);
  }
 } else {
  err("warning: run dependency added without ID");
 }
}

function removeRunDependency(id) {
 runDependencies--;
 if (Module["monitorRunDependencies"]) {
  Module["monitorRunDependencies"](runDependencies);
 }
 if (id) {
  assert(runDependencyTracking[id]);
  delete runDependencyTracking[id];
 } else {
  err("warning: run dependency removed without ID");
 }
 if (runDependencies == 0) {
  if (runDependencyWatcher !== null) {
   clearInterval(runDependencyWatcher);
   runDependencyWatcher = null;
  }
  if (dependenciesFulfilled) {
   var callback = dependenciesFulfilled;
   dependenciesFulfilled = null;
   callback();
  }
 }
}

Module["preloadedImages"] = {};

Module["preloadedAudios"] = {};

function abort(what) {
 if (Module["onAbort"]) {
  Module["onAbort"](what);
 }
 what += "";
 err(what);
 ABORT = true;
 var output = "abort(" + what + ") at " + stackTrace();
 what = output;
 var e = new WebAssembly.RuntimeError(what);
 readyPromiseReject(e);
 throw e;
}

function hasPrefix(str, prefix) {
 return String.prototype.startsWith ? str.startsWith(prefix) : str.indexOf(prefix) === 0;
}

var dataURIPrefix = "data:application/octet-stream;base64,";

function isDataURI(filename) {
 return hasPrefix(filename, dataURIPrefix);
}

function createExportWrapper(name, fixedasm) {
 return function() {
  var displayName = name;
  var asm = fixedasm;
  if (!fixedasm) {
   asm = Module["asm"];
  }
  assert(runtimeInitialized, "native function `" + displayName + "` called before runtime initialization");
  assert(!runtimeExited, "native function `" + displayName + "` called after runtime exit (use NO_EXIT_RUNTIME to keep it alive after main() exits)");
  if (!asm[name]) {
   assert(asm[name], "exported native function `" + displayName + "` not found");
  }
  return asm[name].apply(null, arguments);
 };
}

var wasmBinaryFile = "trace_to_text.wasm";

if (!isDataURI(wasmBinaryFile)) {
 wasmBinaryFile = locateFile(wasmBinaryFile);
}

function getBinary(file) {
 try {
  if (file == wasmBinaryFile && wasmBinary) {
   return new Uint8Array(wasmBinary);
  }
  if (readBinary) {
   return readBinary(file);
  } else {
   throw "sync fetching of the wasm failed: you can preload it to Module['wasmBinary'] manually, or emcc.py will do that for you when generating HTML (but not JS)";
  }
 } catch (err) {
  abort(err);
 }
}

function instantiateSync(file, info) {
 var instance;
 var module;
 var binary;
 try {
  binary = getBinary(file);
  module = new WebAssembly.Module(binary);
  instance = new WebAssembly.Instance(module, info);
 } catch (e) {
  var str = e.toString();
  err("failed to compile wasm module: " + str);
  if (str.indexOf("imported Memory") >= 0 || str.indexOf("memory import") >= 0) {
   err("Memory size incompatibility issues may be due to changing INITIAL_MEMORY at runtime to something too large. Use ALLOW_MEMORY_GROWTH to allow any size memory (and also make sure not to set INITIAL_MEMORY at runtime to something smaller than it was at compile time).");
  }
  throw e;
 }
 return [ instance, module ];
}

function createWasm() {
 var info = {
  "env": asmLibraryArg,
  "wasi_snapshot_preview1": asmLibraryArg
 };
 function receiveInstance(instance, module) {
  var exports = instance.exports;
  Module["asm"] = exports;
  wasmMemory = Module["asm"]["memory"];
  assert(wasmMemory, "memory not found in wasm exports");
  updateGlobalBufferAndViews(wasmMemory.buffer);
  wasmTable = Module["asm"]["__indirect_function_table"];
  assert(wasmTable, "table not found in wasm exports");
  removeRunDependency("wasm-instantiate");
 }
 addRunDependency("wasm-instantiate");
 if (Module["instantiateWasm"]) {
  try {
   var exports = Module["instantiateWasm"](info, receiveInstance);
   return exports;
  } catch (e) {
   err("Module.instantiateWasm callback failed with error: " + e);
   return false;
  }
 }
 var result = instantiateSync(wasmBinaryFile, info);
 receiveInstance(result[0]);
 return Module["asm"];
}

var tempDouble;

var tempI64;

function callRuntimeCallbacks(callbacks) {
 while (callbacks.length > 0) {
  var callback = callbacks.shift();
  if (typeof callback == "function") {
   callback(Module);
   continue;
  }
  var func = callback.func;
  if (typeof func === "number") {
   if (callback.arg === undefined) {
    wasmTable.get(func)();
   } else {
    wasmTable.get(func)(callback.arg);
   }
  } else {
   func(callback.arg === undefined ? null : callback.arg);
  }
 }
}

function demangle(func) {
 warnOnce("warning: build with  -s DEMANGLE_SUPPORT=1  to link in libcxxabi demangling");
 return func;
}

function demangleAll(text) {
 var regex = /\b_Z[\w\d_]+/g;
 return text.replace(regex, function(x) {
  var y = demangle(x);
  return x === y ? x : y + " [" + x + "]";
 });
}

function jsStackTrace() {
 var error = new Error();
 if (!error.stack) {
  try {
   throw new Error();
  } catch (e) {
   error = e;
  }
  if (!error.stack) {
   return "(no stack trace available)";
  }
 }
 return error.stack.toString();
}

function stackTrace() {
 var js = jsStackTrace();
 if (Module["extraStackTrace"]) js += "\n" + Module["extraStackTrace"]();
 return demangleAll(js);
}

var _emscripten_get_now;

if (ENVIRONMENT_IS_NODE) {
 _emscripten_get_now = function() {
  var t = process["hrtime"]();
  return t[0] * 1e3 + t[1] / 1e6;
 };
} else if (typeof dateNow !== "undefined") {
 _emscripten_get_now = dateNow;
} else _emscripten_get_now = function() {
 return performance.now();
};

var _emscripten_get_now_is_monotonic = true;

function setErrNo(value) {
 HEAP32[___errno_location() >> 2] = value;
 return value;
}

function _clock_gettime(clk_id, tp) {
 var now;
 if (clk_id === 0) {
  now = Date.now();
 } else if ((clk_id === 1 || clk_id === 4) && _emscripten_get_now_is_monotonic) {
  now = _emscripten_get_now();
 } else {
  setErrNo(28);
  return -1;
 }
 HEAP32[tp >> 2] = now / 1e3 | 0;
 HEAP32[tp + 4 >> 2] = now % 1e3 * 1e3 * 1e3 | 0;
 return 0;
}

function ___clock_gettime(a0, a1) {
 return _clock_gettime(a0, a1);
}

function _atexit(func, arg) {}

function ___cxa_atexit(a0, a1) {
 return _atexit();
}

function _tzset() {
 if (_tzset.called) return;
 _tzset.called = true;
 var currentYear = new Date().getFullYear();
 var winter = new Date(currentYear, 0, 1);
 var summer = new Date(currentYear, 6, 1);
 var winterOffset = winter.getTimezoneOffset();
 var summerOffset = summer.getTimezoneOffset();
 var stdTimezoneOffset = Math.max(winterOffset, summerOffset);
 HEAP32[__get_timezone() >> 2] = stdTimezoneOffset * 60;
 HEAP32[__get_daylight() >> 2] = Number(winterOffset != summerOffset);
 function extractZone(date) {
  var match = date.toTimeString().match(/\(([A-Za-z ]+)\)$/);
  return match ? match[1] : "GMT";
 }
 var winterName = extractZone(winter);
 var summerName = extractZone(summer);
 var winterNamePtr = allocateUTF8(winterName);
 var summerNamePtr = allocateUTF8(summerName);
 if (summerOffset < winterOffset) {
  HEAP32[__get_tzname() >> 2] = winterNamePtr;
  HEAP32[__get_tzname() + 4 >> 2] = summerNamePtr;
 } else {
  HEAP32[__get_tzname() >> 2] = summerNamePtr;
  HEAP32[__get_tzname() + 4 >> 2] = winterNamePtr;
 }
}

function _localtime_r(time, tmPtr) {
 _tzset();
 var date = new Date(HEAP32[time >> 2] * 1e3);
 HEAP32[tmPtr >> 2] = date.getSeconds();
 HEAP32[tmPtr + 4 >> 2] = date.getMinutes();
 HEAP32[tmPtr + 8 >> 2] = date.getHours();
 HEAP32[tmPtr + 12 >> 2] = date.getDate();
 HEAP32[tmPtr + 16 >> 2] = date.getMonth();
 HEAP32[tmPtr + 20 >> 2] = date.getFullYear() - 1900;
 HEAP32[tmPtr + 24 >> 2] = date.getDay();
 var start = new Date(date.getFullYear(), 0, 1);
 var yday = (date.getTime() - start.getTime()) / (1e3 * 60 * 60 * 24) | 0;
 HEAP32[tmPtr + 28 >> 2] = yday;
 HEAP32[tmPtr + 36 >> 2] = -(date.getTimezoneOffset() * 60);
 var summerOffset = new Date(date.getFullYear(), 6, 1).getTimezoneOffset();
 var winterOffset = start.getTimezoneOffset();
 var dst = (summerOffset != winterOffset && date.getTimezoneOffset() == Math.min(winterOffset, summerOffset)) | 0;
 HEAP32[tmPtr + 32 >> 2] = dst;
 var zonePtr = HEAP32[__get_tzname() + (dst ? 4 : 0) >> 2];
 HEAP32[tmPtr + 40 >> 2] = zonePtr;
 return tmPtr;
}

function ___localtime_r(a0, a1) {
 return _localtime_r(a0, a1);
}

var PATH = {
 splitPath: function(filename) {
  var splitPathRe = /^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/;
  return splitPathRe.exec(filename).slice(1);
 },
 normalizeArray: function(parts, allowAboveRoot) {
  var up = 0;
  for (var i = parts.length - 1; i >= 0; i--) {
   var last = parts[i];
   if (last === ".") {
    parts.splice(i, 1);
   } else if (last === "..") {
    parts.splice(i, 1);
    up++;
   } else if (up) {
    parts.splice(i, 1);
    up--;
   }
  }
  if (allowAboveRoot) {
   for (;up; up--) {
    parts.unshift("..");
   }
  }
  return parts;
 },
 normalize: function(path) {
  var isAbsolute = path.charAt(0) === "/", trailingSlash = path.substr(-1) === "/";
  path = PATH.normalizeArray(path.split("/").filter(function(p) {
   return !!p;
  }), !isAbsolute).join("/");
  if (!path && !isAbsolute) {
   path = ".";
  }
  if (path && trailingSlash) {
   path += "/";
  }
  return (isAbsolute ? "/" : "") + path;
 },
 dirname: function(path) {
  var result = PATH.splitPath(path), root = result[0], dir = result[1];
  if (!root && !dir) {
   return ".";
  }
  if (dir) {
   dir = dir.substr(0, dir.length - 1);
  }
  return root + dir;
 },
 basename: function(path) {
  if (path === "/") return "/";
  path = PATH.normalize(path);
  path = path.replace(/\/$/, "");
  var lastSlash = path.lastIndexOf("/");
  if (lastSlash === -1) return path;
  return path.substr(lastSlash + 1);
 },
 extname: function(path) {
  return PATH.splitPath(path)[3];
 },
 join: function() {
  var paths = Array.prototype.slice.call(arguments, 0);
  return PATH.normalize(paths.join("/"));
 },
 join2: function(l, r) {
  return PATH.normalize(l + "/" + r);
 }
};

function getRandomDevice() {
 if (typeof crypto === "object" && typeof crypto["getRandomValues"] === "function") {
  var randomBuffer = new Uint8Array(1);
  return function() {
   crypto.getRandomValues(randomBuffer);
   return randomBuffer[0];
  };
 } else if (ENVIRONMENT_IS_NODE) {
  try {
   var crypto_module = require("crypto");
   return function() {
    return crypto_module["randomBytes"](1)[0];
   };
  } catch (e) {}
 }
 return function() {
  abort("no cryptographic support found for randomDevice. consider polyfilling it if you want to use something insecure like Math.random(), e.g. put this in a --pre-js: var crypto = { getRandomValues: function(array) { for (var i = 0; i < array.length; i++) array[i] = (Math.random()*256)|0 } };");
 };
}

var PATH_FS = {
 resolve: function() {
  var resolvedPath = "", resolvedAbsolute = false;
  for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {
   var path = i >= 0 ? arguments[i] : FS.cwd();
   if (typeof path !== "string") {
    throw new TypeError("Arguments to path.resolve must be strings");
   } else if (!path) {
    return "";
   }
   resolvedPath = path + "/" + resolvedPath;
   resolvedAbsolute = path.charAt(0) === "/";
  }
  resolvedPath = PATH.normalizeArray(resolvedPath.split("/").filter(function(p) {
   return !!p;
  }), !resolvedAbsolute).join("/");
  return (resolvedAbsolute ? "/" : "") + resolvedPath || ".";
 },
 relative: function(from, to) {
  from = PATH_FS.resolve(from).substr(1);
  to = PATH_FS.resolve(to).substr(1);
  function trim(arr) {
   var start = 0;
   for (;start < arr.length; start++) {
    if (arr[start] !== "") break;
   }
   var end = arr.length - 1;
   for (;end >= 0; end--) {
    if (arr[end] !== "") break;
   }
   if (start > end) return [];
   return arr.slice(start, end - start + 1);
  }
  var fromParts = trim(from.split("/"));
  var toParts = trim(to.split("/"));
  var length = Math.min(fromParts.length, toParts.length);
  var samePartsLength = length;
  for (var i = 0; i < length; i++) {
   if (fromParts[i] !== toParts[i]) {
    samePartsLength = i;
    break;
   }
  }
  var outputParts = [];
  for (var i = samePartsLength; i < fromParts.length; i++) {
   outputParts.push("..");
  }
  outputParts = outputParts.concat(toParts.slice(samePartsLength));
  return outputParts.join("/");
 }
};

var TTY = {
 ttys: [],
 init: function() {},
 shutdown: function() {},
 register: function(dev, ops) {
  TTY.ttys[dev] = {
   input: [],
   output: [],
   ops: ops
  };
  FS.registerDevice(dev, TTY.stream_ops);
 },
 stream_ops: {
  open: function(stream) {
   var tty = TTY.ttys[stream.node.rdev];
   if (!tty) {
    throw new FS.ErrnoError(43);
   }
   stream.tty = tty;
   stream.seekable = false;
  },
  close: function(stream) {
   stream.tty.ops.flush(stream.tty);
  },
  flush: function(stream) {
   stream.tty.ops.flush(stream.tty);
  },
  read: function(stream, buffer, offset, length, pos) {
   if (!stream.tty || !stream.tty.ops.get_char) {
    throw new FS.ErrnoError(60);
   }
   var bytesRead = 0;
   for (var i = 0; i < length; i++) {
    var result;
    try {
     result = stream.tty.ops.get_char(stream.tty);
    } catch (e) {
     throw new FS.ErrnoError(29);
    }
    if (result === undefined && bytesRead === 0) {
     throw new FS.ErrnoError(6);
    }
    if (result === null || result === undefined) break;
    bytesRead++;
    buffer[offset + i] = result;
   }
   if (bytesRead) {
    stream.node.timestamp = Date.now();
   }
   return bytesRead;
  },
  write: function(stream, buffer, offset, length, pos) {
   if (!stream.tty || !stream.tty.ops.put_char) {
    throw new FS.ErrnoError(60);
   }
   try {
    for (var i = 0; i < length; i++) {
     stream.tty.ops.put_char(stream.tty, buffer[offset + i]);
    }
   } catch (e) {
    throw new FS.ErrnoError(29);
   }
   if (length) {
    stream.node.timestamp = Date.now();
   }
   return i;
  }
 },
 default_tty_ops: {
  get_char: function(tty) {
   if (!tty.input.length) {
    var result = null;
    if (ENVIRONMENT_IS_NODE) {
     var BUFSIZE = 256;
     var buf = Buffer.alloc ? Buffer.alloc(BUFSIZE) : new Buffer(BUFSIZE);
     var bytesRead = 0;
     try {
      bytesRead = nodeFS.readSync(process.stdin.fd, buf, 0, BUFSIZE, null);
     } catch (e) {
      if (e.toString().indexOf("EOF") != -1) bytesRead = 0; else throw e;
     }
     if (bytesRead > 0) {
      result = buf.slice(0, bytesRead).toString("utf-8");
     } else {
      result = null;
     }
    } else if (typeof window != "undefined" && typeof window.prompt == "function") {
     result = window.prompt("Input: ");
     if (result !== null) {
      result += "\n";
     }
    } else if (typeof readline == "function") {
     result = readline();
     if (result !== null) {
      result += "\n";
     }
    }
    if (!result) {
     return null;
    }
    tty.input = intArrayFromString(result, true);
   }
   return tty.input.shift();
  },
  put_char: function(tty, val) {
   if (val === null || val === 10) {
    out(UTF8ArrayToString(tty.output, 0));
    tty.output = [];
   } else {
    if (val != 0) tty.output.push(val);
   }
  },
  flush: function(tty) {
   if (tty.output && tty.output.length > 0) {
    out(UTF8ArrayToString(tty.output, 0));
    tty.output = [];
   }
  }
 },
 default_tty1_ops: {
  put_char: function(tty, val) {
   if (val === null || val === 10) {
    err(UTF8ArrayToString(tty.output, 0));
    tty.output = [];
   } else {
    if (val != 0) tty.output.push(val);
   }
  },
  flush: function(tty) {
   if (tty.output && tty.output.length > 0) {
    err(UTF8ArrayToString(tty.output, 0));
    tty.output = [];
   }
  }
 }
};

function mmapAlloc(size) {
 var alignedSize = alignMemory(size, 16384);
 var ptr = _malloc(alignedSize);
 while (size < alignedSize) HEAP8[ptr + size++] = 0;
 return ptr;
}

var MEMFS = {
 ops_table: null,
 mount: function(mount) {
  return MEMFS.createNode(null, "/", 16384 | 511, 0);
 },
 createNode: function(parent, name, mode, dev) {
  if (FS.isBlkdev(mode) || FS.isFIFO(mode)) {
   throw new FS.ErrnoError(63);
  }
  if (!MEMFS.ops_table) {
   MEMFS.ops_table = {
    dir: {
     node: {
      getattr: MEMFS.node_ops.getattr,
      setattr: MEMFS.node_ops.setattr,
      lookup: MEMFS.node_ops.lookup,
      mknod: MEMFS.node_ops.mknod,
      rename: MEMFS.node_ops.rename,
      unlink: MEMFS.node_ops.unlink,
      rmdir: MEMFS.node_ops.rmdir,
      readdir: MEMFS.node_ops.readdir,
      symlink: MEMFS.node_ops.symlink
     },
     stream: {
      llseek: MEMFS.stream_ops.llseek
     }
    },
    file: {
     node: {
      getattr: MEMFS.node_ops.getattr,
      setattr: MEMFS.node_ops.setattr
     },
     stream: {
      llseek: MEMFS.stream_ops.llseek,
      read: MEMFS.stream_ops.read,
      write: MEMFS.stream_ops.write,
      allocate: MEMFS.stream_ops.allocate,
      mmap: MEMFS.stream_ops.mmap,
      msync: MEMFS.stream_ops.msync
     }
    },
    link: {
     node: {
      getattr: MEMFS.node_ops.getattr,
      setattr: MEMFS.node_ops.setattr,
      readlink: MEMFS.node_ops.readlink
     },
     stream: {}
    },
    chrdev: {
     node: {
      getattr: MEMFS.node_ops.getattr,
      setattr: MEMFS.node_ops.setattr
     },
     stream: FS.chrdev_stream_ops
    }
   };
  }
  var node = FS.createNode(parent, name, mode, dev);
  if (FS.isDir(node.mode)) {
   node.node_ops = MEMFS.ops_table.dir.node;
   node.stream_ops = MEMFS.ops_table.dir.stream;
   node.contents = {};
  } else if (FS.isFile(node.mode)) {
   node.node_ops = MEMFS.ops_table.file.node;
   node.stream_ops = MEMFS.ops_table.file.stream;
   node.usedBytes = 0;
   node.contents = null;
  } else if (FS.isLink(node.mode)) {
   node.node_ops = MEMFS.ops_table.link.node;
   node.stream_ops = MEMFS.ops_table.link.stream;
  } else if (FS.isChrdev(node.mode)) {
   node.node_ops = MEMFS.ops_table.chrdev.node;
   node.stream_ops = MEMFS.ops_table.chrdev.stream;
  }
  node.timestamp = Date.now();
  if (parent) {
   parent.contents[name] = node;
   parent.timestamp = node.timestamp;
  }
  return node;
 },
 getFileDataAsRegularArray: function(node) {
  if (node.contents && node.contents.subarray) {
   var arr = [];
   for (var i = 0; i < node.usedBytes; ++i) arr.push(node.contents[i]);
   return arr;
  }
  return node.contents;
 },
 getFileDataAsTypedArray: function(node) {
  if (!node.contents) return new Uint8Array(0);
  if (node.contents.subarray) return node.contents.subarray(0, node.usedBytes);
  return new Uint8Array(node.contents);
 },
 expandFileStorage: function(node, newCapacity) {
  var prevCapacity = node.contents ? node.contents.length : 0;
  if (prevCapacity >= newCapacity) return;
  var CAPACITY_DOUBLING_MAX = 1024 * 1024;
  newCapacity = Math.max(newCapacity, prevCapacity * (prevCapacity < CAPACITY_DOUBLING_MAX ? 2 : 1.125) >>> 0);
  if (prevCapacity != 0) newCapacity = Math.max(newCapacity, 256);
  var oldContents = node.contents;
  node.contents = new Uint8Array(newCapacity);
  if (node.usedBytes > 0) node.contents.set(oldContents.subarray(0, node.usedBytes), 0);
  return;
 },
 resizeFileStorage: function(node, newSize) {
  if (node.usedBytes == newSize) return;
  if (newSize == 0) {
   node.contents = null;
   node.usedBytes = 0;
   return;
  }
  if (!node.contents || node.contents.subarray) {
   var oldContents = node.contents;
   node.contents = new Uint8Array(newSize);
   if (oldContents) {
    node.contents.set(oldContents.subarray(0, Math.min(newSize, node.usedBytes)));
   }
   node.usedBytes = newSize;
   return;
  }
  if (!node.contents) node.contents = [];
  if (node.contents.length > newSize) node.contents.length = newSize; else while (node.contents.length < newSize) node.contents.push(0);
  node.usedBytes = newSize;
 },
 node_ops: {
  getattr: function(node) {
   var attr = {};
   attr.dev = FS.isChrdev(node.mode) ? node.id : 1;
   attr.ino = node.id;
   attr.mode = node.mode;
   attr.nlink = 1;
   attr.uid = 0;
   attr.gid = 0;
   attr.rdev = node.rdev;
   if (FS.isDir(node.mode)) {
    attr.size = 4096;
   } else if (FS.isFile(node.mode)) {
    attr.size = node.usedBytes;
   } else if (FS.isLink(node.mode)) {
    attr.size = node.link.length;
   } else {
    attr.size = 0;
   }
   attr.atime = new Date(node.timestamp);
   attr.mtime = new Date(node.timestamp);
   attr.ctime = new Date(node.timestamp);
   attr.blksize = 4096;
   attr.blocks = Math.ceil(attr.size / attr.blksize);
   return attr;
  },
  setattr: function(node, attr) {
   if (attr.mode !== undefined) {
    node.mode = attr.mode;
   }
   if (attr.timestamp !== undefined) {
    node.timestamp = attr.timestamp;
   }
   if (attr.size !== undefined) {
    MEMFS.resizeFileStorage(node, attr.size);
   }
  },
  lookup: function(parent, name) {
   throw FS.genericErrors[44];
  },
  mknod: function(parent, name, mode, dev) {
   return MEMFS.createNode(parent, name, mode, dev);
  },
  rename: function(old_node, new_dir, new_name) {
   if (FS.isDir(old_node.mode)) {
    var new_node;
    try {
     new_node = FS.lookupNode(new_dir, new_name);
    } catch (e) {}
    if (new_node) {
     for (var i in new_node.contents) {
      throw new FS.ErrnoError(55);
     }
    }
   }
   delete old_node.parent.contents[old_node.name];
   old_node.parent.timestamp = Date.now();
   old_node.name = new_name;
   new_dir.contents[new_name] = old_node;
   new_dir.timestamp = old_node.parent.timestamp;
   old_node.parent = new_dir;
  },
  unlink: function(parent, name) {
   delete parent.contents[name];
   parent.timestamp = Date.now();
  },
  rmdir: function(parent, name) {
   var node = FS.lookupNode(parent, name);
   for (var i in node.contents) {
    throw new FS.ErrnoError(55);
   }
   delete parent.contents[name];
   parent.timestamp = Date.now();
  },
  readdir: function(node) {
   var entries = [ ".", ".." ];
   for (var key in node.contents) {
    if (!node.contents.hasOwnProperty(key)) {
     continue;
    }
    entries.push(key);
   }
   return entries;
  },
  symlink: function(parent, newname, oldpath) {
   var node = MEMFS.createNode(parent, newname, 511 | 40960, 0);
   node.link = oldpath;
   return node;
  },
  readlink: function(node) {
   if (!FS.isLink(node.mode)) {
    throw new FS.ErrnoError(28);
   }
   return node.link;
  }
 },
 stream_ops: {
  read: function(stream, buffer, offset, length, position) {
   var contents = stream.node.contents;
   if (position >= stream.node.usedBytes) return 0;
   var size = Math.min(stream.node.usedBytes - position, length);
   assert(size >= 0);
   if (size > 8 && contents.subarray) {
    buffer.set(contents.subarray(position, position + size), offset);
   } else {
    for (var i = 0; i < size; i++) buffer[offset + i] = contents[position + i];
   }
   return size;
  },
  write: function(stream, buffer, offset, length, position, canOwn) {
   assert(!(buffer instanceof ArrayBuffer));
   if (buffer.buffer === HEAP8.buffer) {
    canOwn = false;
   }
   if (!length) return 0;
   var node = stream.node;
   node.timestamp = Date.now();
   if (buffer.subarray && (!node.contents || node.contents.subarray)) {
    if (canOwn) {
     assert(position === 0, "canOwn must imply no weird position inside the file");
     node.contents = buffer.subarray(offset, offset + length);
     node.usedBytes = length;
     return length;
    } else if (node.usedBytes === 0 && position === 0) {
     node.contents = buffer.slice(offset, offset + length);
     node.usedBytes = length;
     return length;
    } else if (position + length <= node.usedBytes) {
     node.contents.set(buffer.subarray(offset, offset + length), position);
     return length;
    }
   }
   MEMFS.expandFileStorage(node, position + length);
   if (node.contents.subarray && buffer.subarray) {
    node.contents.set(buffer.subarray(offset, offset + length), position);
   } else {
    for (var i = 0; i < length; i++) {
     node.contents[position + i] = buffer[offset + i];
    }
   }
   node.usedBytes = Math.max(node.usedBytes, position + length);
   return length;
  },
  llseek: function(stream, offset, whence) {
   var position = offset;
   if (whence === 1) {
    position += stream.position;
   } else if (whence === 2) {
    if (FS.isFile(stream.node.mode)) {
     position += stream.node.usedBytes;
    }
   }
   if (position < 0) {
    throw new FS.ErrnoError(28);
   }
   return position;
  },
  allocate: function(stream, offset, length) {
   MEMFS.expandFileStorage(stream.node, offset + length);
   stream.node.usedBytes = Math.max(stream.node.usedBytes, offset + length);
  },
  mmap: function(stream, address, length, position, prot, flags) {
   if (address !== 0) {
    throw new FS.ErrnoError(28);
   }
   if (!FS.isFile(stream.node.mode)) {
    throw new FS.ErrnoError(43);
   }
   var ptr;
   var allocated;
   var contents = stream.node.contents;
   if (!(flags & 2) && contents.buffer === buffer) {
    allocated = false;
    ptr = contents.byteOffset;
   } else {
    if (position > 0 || position + length < contents.length) {
     if (contents.subarray) {
      contents = contents.subarray(position, position + length);
     } else {
      contents = Array.prototype.slice.call(contents, position, position + length);
     }
    }
    allocated = true;
    ptr = mmapAlloc(length);
    if (!ptr) {
     throw new FS.ErrnoError(48);
    }
    HEAP8.set(contents, ptr);
   }
   return {
    ptr: ptr,
    allocated: allocated
   };
  },
  msync: function(stream, buffer, offset, length, mmapFlags) {
   if (!FS.isFile(stream.node.mode)) {
    throw new FS.ErrnoError(43);
   }
   if (mmapFlags & 2) {
    return 0;
   }
   MEMFS.stream_ops.write(stream, buffer, 0, length, offset, false);
   return 0;
  }
 }
};

var WORKERFS = {
 DIR_MODE: 16895,
 FILE_MODE: 33279,
 reader: null,
 mount: function(mount) {
  assert(ENVIRONMENT_IS_WORKER);
  if (!WORKERFS.reader) WORKERFS.reader = new FileReaderSync();
  var root = WORKERFS.createNode(null, "/", WORKERFS.DIR_MODE, 0);
  var createdParents = {};
  function ensureParent(path) {
   var parts = path.split("/");
   var parent = root;
   for (var i = 0; i < parts.length - 1; i++) {
    var curr = parts.slice(0, i + 1).join("/");
    if (!createdParents[curr]) {
     createdParents[curr] = WORKERFS.createNode(parent, parts[i], WORKERFS.DIR_MODE, 0);
    }
    parent = createdParents[curr];
   }
   return parent;
  }
  function base(path) {
   var parts = path.split("/");
   return parts[parts.length - 1];
  }
  Array.prototype.forEach.call(mount.opts["files"] || [], function(file) {
   WORKERFS.createNode(ensureParent(file.name), base(file.name), WORKERFS.FILE_MODE, 0, file, file.lastModifiedDate);
  });
  (mount.opts["blobs"] || []).forEach(function(obj) {
   WORKERFS.createNode(ensureParent(obj["name"]), base(obj["name"]), WORKERFS.FILE_MODE, 0, obj["data"]);
  });
  (mount.opts["packages"] || []).forEach(function(pack) {
   pack["metadata"].files.forEach(function(file) {
    var name = file.filename.substr(1);
    WORKERFS.createNode(ensureParent(name), base(name), WORKERFS.FILE_MODE, 0, pack["blob"].slice(file.start, file.end));
   });
  });
  return root;
 },
 createNode: function(parent, name, mode, dev, contents, mtime) {
  var node = FS.createNode(parent, name, mode);
  node.mode = mode;
  node.node_ops = WORKERFS.node_ops;
  node.stream_ops = WORKERFS.stream_ops;
  node.timestamp = (mtime || new Date()).getTime();
  assert(WORKERFS.FILE_MODE !== WORKERFS.DIR_MODE);
  if (mode === WORKERFS.FILE_MODE) {
   node.size = contents.size;
   node.contents = contents;
  } else {
   node.size = 4096;
   node.contents = {};
  }
  if (parent) {
   parent.contents[name] = node;
  }
  return node;
 },
 node_ops: {
  getattr: function(node) {
   return {
    dev: 1,
    ino: node.id,
    mode: node.mode,
    nlink: 1,
    uid: 0,
    gid: 0,
    rdev: undefined,
    size: node.size,
    atime: new Date(node.timestamp),
    mtime: new Date(node.timestamp),
    ctime: new Date(node.timestamp),
    blksize: 4096,
    blocks: Math.ceil(node.size / 4096)
   };
  },
  setattr: function(node, attr) {
   if (attr.mode !== undefined) {
    node.mode = attr.mode;
   }
   if (attr.timestamp !== undefined) {
    node.timestamp = attr.timestamp;
   }
  },
  lookup: function(parent, name) {
   throw new FS.ErrnoError(44);
  },
  mknod: function(parent, name, mode, dev) {
   throw new FS.ErrnoError(63);
  },
  rename: function(oldNode, newDir, newName) {
   throw new FS.ErrnoError(63);
  },
  unlink: function(parent, name) {
   throw new FS.ErrnoError(63);
  },
  rmdir: function(parent, name) {
   throw new FS.ErrnoError(63);
  },
  readdir: function(node) {
   var entries = [ ".", ".." ];
   for (var key in node.contents) {
    if (!node.contents.hasOwnProperty(key)) {
     continue;
    }
    entries.push(key);
   }
   return entries;
  },
  symlink: function(parent, newName, oldPath) {
   throw new FS.ErrnoError(63);
  },
  readlink: function(node) {
   throw new FS.ErrnoError(63);
  }
 },
 stream_ops: {
  read: function(stream, buffer, offset, length, position) {
   if (position >= stream.node.size) return 0;
   var chunk = stream.node.contents.slice(position, position + length);
   var ab = WORKERFS.reader.readAsArrayBuffer(chunk);
   buffer.set(new Uint8Array(ab), offset);
   return chunk.size;
  },
  write: function(stream, buffer, offset, length, position) {
   throw new FS.ErrnoError(29);
  },
  llseek: function(stream, offset, whence) {
   var position = offset;
   if (whence === 1) {
    position += stream.position;
   } else if (whence === 2) {
    if (FS.isFile(stream.node.mode)) {
     position += stream.node.size;
    }
   }
   if (position < 0) {
    throw new FS.ErrnoError(28);
   }
   return position;
  }
 }
};

var ERRNO_MESSAGES = {
 0: "Success",
 1: "Arg list too long",
 2: "Permission denied",
 3: "Address already in use",
 4: "Address not available",
 5: "Address family not supported by protocol family",
 6: "No more processes",
 7: "Socket already connected",
 8: "Bad file number",
 9: "Trying to read unreadable message",
 10: "Mount device busy",
 11: "Operation canceled",
 12: "No children",
 13: "Connection aborted",
 14: "Connection refused",
 15: "Connection reset by peer",
 16: "File locking deadlock error",
 17: "Destination address required",
 18: "Math arg out of domain of func",
 19: "Quota exceeded",
 20: "File exists",
 21: "Bad address",
 22: "File too large",
 23: "Host is unreachable",
 24: "Identifier removed",
 25: "Illegal byte sequence",
 26: "Connection already in progress",
 27: "Interrupted system call",
 28: "Invalid argument",
 29: "I/O error",
 30: "Socket is already connected",
 31: "Is a directory",
 32: "Too many symbolic links",
 33: "Too many open files",
 34: "Too many links",
 35: "Message too long",
 36: "Multihop attempted",
 37: "File or path name too long",
 38: "Network interface is not configured",
 39: "Connection reset by network",
 40: "Network is unreachable",
 41: "Too many open files in system",
 42: "No buffer space available",
 43: "No such device",
 44: "No such file or directory",
 45: "Exec format error",
 46: "No record locks available",
 47: "The link has been severed",
 48: "Not enough core",
 49: "No message of desired type",
 50: "Protocol not available",
 51: "No space left on device",
 52: "Function not implemented",
 53: "Socket is not connected",
 54: "Not a directory",
 55: "Directory not empty",
 56: "State not recoverable",
 57: "Socket operation on non-socket",
 59: "Not a typewriter",
 60: "No such device or address",
 61: "Value too large for defined data type",
 62: "Previous owner died",
 63: "Not super-user",
 64: "Broken pipe",
 65: "Protocol error",
 66: "Unknown protocol",
 67: "Protocol wrong type for socket",
 68: "Math result not representable",
 69: "Read only file system",
 70: "Illegal seek",
 71: "No such process",
 72: "Stale file handle",
 73: "Connection timed out",
 74: "Text file busy",
 75: "Cross-device link",
 100: "Device not a stream",
 101: "Bad font file fmt",
 102: "Invalid slot",
 103: "Invalid request code",
 104: "No anode",
 105: "Block device required",
 106: "Channel number out of range",
 107: "Level 3 halted",
 108: "Level 3 reset",
 109: "Link number out of range",
 110: "Protocol driver not attached",
 111: "No CSI structure available",
 112: "Level 2 halted",
 113: "Invalid exchange",
 114: "Invalid request descriptor",
 115: "Exchange full",
 116: "No data (for no delay io)",
 117: "Timer expired",
 118: "Out of streams resources",
 119: "Machine is not on the network",
 120: "Package not installed",
 121: "The object is remote",
 122: "Advertise error",
 123: "Srmount error",
 124: "Communication error on send",
 125: "Cross mount point (not really error)",
 126: "Given log. name not unique",
 127: "f.d. invalid for this operation",
 128: "Remote address changed",
 129: "Can   access a needed shared lib",
 130: "Accessing a corrupted shared lib",
 131: ".lib section in a.out corrupted",
 132: "Attempting to link in too many libs",
 133: "Attempting to exec a shared library",
 135: "Streams pipe error",
 136: "Too many users",
 137: "Socket type not supported",
 138: "Not supported",
 139: "Protocol family not supported",
 140: "Can't send after socket shutdown",
 141: "Too many references",
 142: "Host is down",
 148: "No medium (in tape drive)",
 156: "Level 2 not synchronized"
};

var ERRNO_CODES = {
 EPERM: 63,
 ENOENT: 44,
 ESRCH: 71,
 EINTR: 27,
 EIO: 29,
 ENXIO: 60,
 E2BIG: 1,
 ENOEXEC: 45,
 EBADF: 8,
 ECHILD: 12,
 EAGAIN: 6,
 EWOULDBLOCK: 6,
 ENOMEM: 48,
 EACCES: 2,
 EFAULT: 21,
 ENOTBLK: 105,
 EBUSY: 10,
 EEXIST: 20,
 EXDEV: 75,
 ENODEV: 43,
 ENOTDIR: 54,
 EISDIR: 31,
 EINVAL: 28,
 ENFILE: 41,
 EMFILE: 33,
 ENOTTY: 59,
 ETXTBSY: 74,
 EFBIG: 22,
 ENOSPC: 51,
 ESPIPE: 70,
 EROFS: 69,
 EMLINK: 34,
 EPIPE: 64,
 EDOM: 18,
 ERANGE: 68,
 ENOMSG: 49,
 EIDRM: 24,
 ECHRNG: 106,
 EL2NSYNC: 156,
 EL3HLT: 107,
 EL3RST: 108,
 ELNRNG: 109,
 EUNATCH: 110,
 ENOCSI: 111,
 EL2HLT: 112,
 EDEADLK: 16,
 ENOLCK: 46,
 EBADE: 113,
 EBADR: 114,
 EXFULL: 115,
 ENOANO: 104,
 EBADRQC: 103,
 EBADSLT: 102,
 EDEADLOCK: 16,
 EBFONT: 101,
 ENOSTR: 100,
 ENODATA: 116,
 ETIME: 117,
 ENOSR: 118,
 ENONET: 119,
 ENOPKG: 120,
 EREMOTE: 121,
 ENOLINK: 47,
 EADV: 122,
 ESRMNT: 123,
 ECOMM: 124,
 EPROTO: 65,
 EMULTIHOP: 36,
 EDOTDOT: 125,
 EBADMSG: 9,
 ENOTUNIQ: 126,
 EBADFD: 127,
 EREMCHG: 128,
 ELIBACC: 129,
 ELIBBAD: 130,
 ELIBSCN: 131,
 ELIBMAX: 132,
 ELIBEXEC: 133,
 ENOSYS: 52,
 ENOTEMPTY: 55,
 ENAMETOOLONG: 37,
 ELOOP: 32,
 EOPNOTSUPP: 138,
 EPFNOSUPPORT: 139,
 ECONNRESET: 15,
 ENOBUFS: 42,
 EAFNOSUPPORT: 5,
 EPROTOTYPE: 67,
 ENOTSOCK: 57,
 ENOPROTOOPT: 50,
 ESHUTDOWN: 140,
 ECONNREFUSED: 14,
 EADDRINUSE: 3,
 ECONNABORTED: 13,
 ENETUNREACH: 40,
 ENETDOWN: 38,
 ETIMEDOUT: 73,
 EHOSTDOWN: 142,
 EHOSTUNREACH: 23,
 EINPROGRESS: 26,
 EALREADY: 7,
 EDESTADDRREQ: 17,
 EMSGSIZE: 35,
 EPROTONOSUPPORT: 66,
 ESOCKTNOSUPPORT: 137,
 EADDRNOTAVAIL: 4,
 ENETRESET: 39,
 EISCONN: 30,
 ENOTCONN: 53,
 ETOOMANYREFS: 141,
 EUSERS: 136,
 EDQUOT: 19,
 ESTALE: 72,
 ENOTSUP: 138,
 ENOMEDIUM: 148,
 EILSEQ: 25,
 EOVERFLOW: 61,
 ECANCELED: 11,
 ENOTRECOVERABLE: 56,
 EOWNERDEAD: 62,
 ESTRPIPE: 135
};

var FS = {
 root: null,
 mounts: [],
 devices: {},
 streams: [],
 nextInode: 1,
 nameTable: null,
 currentPath: "/",
 initialized: false,
 ignorePermissions: true,
 trackingDelegate: {},
 tracking: {
  openFlags: {
   READ: 1,
   WRITE: 2
  }
 },
 ErrnoError: null,
 genericErrors: {},
 filesystems: null,
 syncFSRequests: 0,
 lookupPath: function(path, opts) {
  path = PATH_FS.resolve(FS.cwd(), path);
  opts = opts || {};
  if (!path) return {
   path: "",
   node: null
  };
  var defaults = {
   follow_mount: true,
   recurse_count: 0
  };
  for (var key in defaults) {
   if (opts[key] === undefined) {
    opts[key] = defaults[key];
   }
  }
  if (opts.recurse_count > 8) {
   throw new FS.ErrnoError(32);
  }
  var parts = PATH.normalizeArray(path.split("/").filter(function(p) {
   return !!p;
  }), false);
  var current = FS.root;
  var current_path = "/";
  for (var i = 0; i < parts.length; i++) {
   var islast = i === parts.length - 1;
   if (islast && opts.parent) {
    break;
   }
   current = FS.lookupNode(current, parts[i]);
   current_path = PATH.join2(current_path, parts[i]);
   if (FS.isMountpoint(current)) {
    if (!islast || islast && opts.follow_mount) {
     current = current.mounted.root;
    }
   }
   if (!islast || opts.follow) {
    var count = 0;
    while (FS.isLink(current.mode)) {
     var link = FS.readlink(current_path);
     current_path = PATH_FS.resolve(PATH.dirname(current_path), link);
     var lookup = FS.lookupPath(current_path, {
      recurse_count: opts.recurse_count
     });
     current = lookup.node;
     if (count++ > 40) {
      throw new FS.ErrnoError(32);
     }
    }
   }
  }
  return {
   path: current_path,
   node: current
  };
 },
 getPath: function(node) {
  var path;
  while (true) {
   if (FS.isRoot(node)) {
    var mount = node.mount.mountpoint;
    if (!path) return mount;
    return mount[mount.length - 1] !== "/" ? mount + "/" + path : mount + path;
   }
   path = path ? node.name + "/" + path : node.name;
   node = node.parent;
  }
 },
 hashName: function(parentid, name) {
  var hash = 0;
  for (var i = 0; i < name.length; i++) {
   hash = (hash << 5) - hash + name.charCodeAt(i) | 0;
  }
  return (parentid + hash >>> 0) % FS.nameTable.length;
 },
 hashAddNode: function(node) {
  var hash = FS.hashName(node.parent.id, node.name);
  node.name_next = FS.nameTable[hash];
  FS.nameTable[hash] = node;
 },
 hashRemoveNode: function(node) {
  var hash = FS.hashName(node.parent.id, node.name);
  if (FS.nameTable[hash] === node) {
   FS.nameTable[hash] = node.name_next;
  } else {
   var current = FS.nameTable[hash];
   while (current) {
    if (current.name_next === node) {
     current.name_next = node.name_next;
     break;
    }
    current = current.name_next;
   }
  }
 },
 lookupNode: function(parent, name) {
  var errCode = FS.mayLookup(parent);
  if (errCode) {
   throw new FS.ErrnoError(errCode, parent);
  }
  var hash = FS.hashName(parent.id, name);
  for (var node = FS.nameTable[hash]; node; node = node.name_next) {
   var nodeName = node.name;
   if (node.parent.id === parent.id && nodeName === name) {
    return node;
   }
  }
  return FS.lookup(parent, name);
 },
 createNode: function(parent, name, mode, rdev) {
  assert(typeof parent === "object");
  var node = new FS.FSNode(parent, name, mode, rdev);
  FS.hashAddNode(node);
  return node;
 },
 destroyNode: function(node) {
  FS.hashRemoveNode(node);
 },
 isRoot: function(node) {
  return node === node.parent;
 },
 isMountpoint: function(node) {
  return !!node.mounted;
 },
 isFile: function(mode) {
  return (mode & 61440) === 32768;
 },
 isDir: function(mode) {
  return (mode & 61440) === 16384;
 },
 isLink: function(mode) {
  return (mode & 61440) === 40960;
 },
 isChrdev: function(mode) {
  return (mode & 61440) === 8192;
 },
 isBlkdev: function(mode) {
  return (mode & 61440) === 24576;
 },
 isFIFO: function(mode) {
  return (mode & 61440) === 4096;
 },
 isSocket: function(mode) {
  return (mode & 49152) === 49152;
 },
 flagModes: {
  "r": 0,
  "r+": 2,
  "w": 577,
  "w+": 578,
  "a": 1089,
  "a+": 1090
 },
 modeStringToFlags: function(str) {
  var flags = FS.flagModes[str];
  if (typeof flags === "undefined") {
   throw new Error("Unknown file open mode: " + str);
  }
  return flags;
 },
 flagsToPermissionString: function(flag) {
  var perms = [ "r", "w", "rw" ][flag & 3];
  if (flag & 512) {
   perms += "w";
  }
  return perms;
 },
 nodePermissions: function(node, perms) {
  if (FS.ignorePermissions) {
   return 0;
  }
  if (perms.indexOf("r") !== -1 && !(node.mode & 292)) {
   return 2;
  } else if (perms.indexOf("w") !== -1 && !(node.mode & 146)) {
   return 2;
  } else if (perms.indexOf("x") !== -1 && !(node.mode & 73)) {
   return 2;
  }
  return 0;
 },
 mayLookup: function(dir) {
  var errCode = FS.nodePermissions(dir, "x");
  if (errCode) return errCode;
  if (!dir.node_ops.lookup) return 2;
  return 0;
 },
 mayCreate: function(dir, name) {
  try {
   var node = FS.lookupNode(dir, name);
   return 20;
  } catch (e) {}
  return FS.nodePermissions(dir, "wx");
 },
 mayDelete: function(dir, name, isdir) {
  var node;
  try {
   node = FS.lookupNode(dir, name);
  } catch (e) {
   return e.errno;
  }
  var errCode = FS.nodePermissions(dir, "wx");
  if (errCode) {
   return errCode;
  }
  if (isdir) {
   if (!FS.isDir(node.mode)) {
    return 54;
   }
   if (FS.isRoot(node) || FS.getPath(node) === FS.cwd()) {
    return 10;
   }
  } else {
   if (FS.isDir(node.mode)) {
    return 31;
   }
  }
  return 0;
 },
 mayOpen: function(node, flags) {
  if (!node) {
   return 44;
  }
  if (FS.isLink(node.mode)) {
   return 32;
  } else if (FS.isDir(node.mode)) {
   if (FS.flagsToPermissionString(flags) !== "r" || flags & 512) {
    return 31;
   }
  }
  return FS.nodePermissions(node, FS.flagsToPermissionString(flags));
 },
 MAX_OPEN_FDS: 4096,
 nextfd: function(fd_start, fd_end) {
  fd_start = fd_start || 0;
  fd_end = fd_end || FS.MAX_OPEN_FDS;
  for (var fd = fd_start; fd <= fd_end; fd++) {
   if (!FS.streams[fd]) {
    return fd;
   }
  }
  throw new FS.ErrnoError(33);
 },
 getStream: function(fd) {
  return FS.streams[fd];
 },
 createStream: function(stream, fd_start, fd_end) {
  if (!FS.FSStream) {
   FS.FSStream = function() {};
   FS.FSStream.prototype = {
    object: {
     get: function() {
      return this.node;
     },
     set: function(val) {
      this.node = val;
     }
    },
    isRead: {
     get: function() {
      return (this.flags & 2097155) !== 1;
     }
    },
    isWrite: {
     get: function() {
      return (this.flags & 2097155) !== 0;
     }
    },
    isAppend: {
     get: function() {
      return this.flags & 1024;
     }
    }
   };
  }
  var newStream = new FS.FSStream();
  for (var p in stream) {
   newStream[p] = stream[p];
  }
  stream = newStream;
  var fd = FS.nextfd(fd_start, fd_end);
  stream.fd = fd;
  FS.streams[fd] = stream;
  return stream;
 },
 closeStream: function(fd) {
  FS.streams[fd] = null;
 },
 chrdev_stream_ops: {
  open: function(stream) {
   var device = FS.getDevice(stream.node.rdev);
   stream.stream_ops = device.stream_ops;
   if (stream.stream_ops.open) {
    stream.stream_ops.open(stream);
   }
  },
  llseek: function() {
   throw new FS.ErrnoError(70);
  }
 },
 major: function(dev) {
  return dev >> 8;
 },
 minor: function(dev) {
  return dev & 255;
 },
 makedev: function(ma, mi) {
  return ma << 8 | mi;
 },
 registerDevice: function(dev, ops) {
  FS.devices[dev] = {
   stream_ops: ops
  };
 },
 getDevice: function(dev) {
  return FS.devices[dev];
 },
 getMounts: function(mount) {
  var mounts = [];
  var check = [ mount ];
  while (check.length) {
   var m = check.pop();
   mounts.push(m);
   check.push.apply(check, m.mounts);
  }
  return mounts;
 },
 syncfs: function(populate, callback) {
  if (typeof populate === "function") {
   callback = populate;
   populate = false;
  }
  FS.syncFSRequests++;
  if (FS.syncFSRequests > 1) {
   err("warning: " + FS.syncFSRequests + " FS.syncfs operations in flight at once, probably just doing extra work");
  }
  var mounts = FS.getMounts(FS.root.mount);
  var completed = 0;
  function doCallback(errCode) {
   assert(FS.syncFSRequests > 0);
   FS.syncFSRequests--;
   return callback(errCode);
  }
  function done(errCode) {
   if (errCode) {
    if (!done.errored) {
     done.errored = true;
     return doCallback(errCode);
    }
    return;
   }
   if (++completed >= mounts.length) {
    doCallback(null);
   }
  }
  mounts.forEach(function(mount) {
   if (!mount.type.syncfs) {
    return done(null);
   }
   mount.type.syncfs(mount, populate, done);
  });
 },
 mount: function(type, opts, mountpoint) {
  if (typeof type === "string") {
   throw type;
  }
  var root = mountpoint === "/";
  var pseudo = !mountpoint;
  var node;
  if (root && FS.root) {
   throw new FS.ErrnoError(10);
  } else if (!root && !pseudo) {
   var lookup = FS.lookupPath(mountpoint, {
    follow_mount: false
   });
   mountpoint = lookup.path;
   node = lookup.node;
   if (FS.isMountpoint(node)) {
    throw new FS.ErrnoError(10);
   }
   if (!FS.isDir(node.mode)) {
    throw new FS.ErrnoError(54);
   }
  }
  var mount = {
   type: type,
   opts: opts,
   mountpoint: mountpoint,
   mounts: []
  };
  var mountRoot = type.mount(mount);
  mountRoot.mount = mount;
  mount.root = mountRoot;
  if (root) {
   FS.root = mountRoot;
  } else if (node) {
   node.mounted = mount;
   if (node.mount) {
    node.mount.mounts.push(mount);
   }
  }
  return mountRoot;
 },
 unmount: function(mountpoint) {
  var lookup = FS.lookupPath(mountpoint, {
   follow_mount: false
  });
  if (!FS.isMountpoint(lookup.node)) {
   throw new FS.ErrnoError(28);
  }
  var node = lookup.node;
  var mount = node.mounted;
  var mounts = FS.getMounts(mount);
  Object.keys(FS.nameTable).forEach(function(hash) {
   var current = FS.nameTable[hash];
   while (current) {
    var next = current.name_next;
    if (mounts.indexOf(current.mount) !== -1) {
     FS.destroyNode(current);
    }
    current = next;
   }
  });
  node.mounted = null;
  var idx = node.mount.mounts.indexOf(mount);
  assert(idx !== -1);
  node.mount.mounts.splice(idx, 1);
 },
 lookup: function(parent, name) {
  return parent.node_ops.lookup(parent, name);
 },
 mknod: function(path, mode, dev) {
  var lookup = FS.lookupPath(path, {
   parent: true
  });
  var parent = lookup.node;
  var name = PATH.basename(path);
  if (!name || name === "." || name === "..") {
   throw new FS.ErrnoError(28);
  }
  var errCode = FS.mayCreate(parent, name);
  if (errCode) {
   throw new FS.ErrnoError(errCode);
  }
  if (!parent.node_ops.mknod) {
   throw new FS.ErrnoError(63);
  }
  return parent.node_ops.mknod(parent, name, mode, dev);
 },
 create: function(path, mode) {
  mode = mode !== undefined ? mode : 438;
  mode &= 4095;
  mode |= 32768;
  return FS.mknod(path, mode, 0);
 },
 mkdir: function(path, mode) {
  mode = mode !== undefined ? mode : 511;
  mode &= 511 | 512;
  mode |= 16384;
  return FS.mknod(path, mode, 0);
 },
 mkdirTree: function(path, mode) {
  var dirs = path.split("/");
  var d = "";
  for (var i = 0; i < dirs.length; ++i) {
   if (!dirs[i]) continue;
   d += "/" + dirs[i];
   try {
    FS.mkdir(d, mode);
   } catch (e) {
    if (e.errno != 20) throw e;
   }
  }
 },
 mkdev: function(path, mode, dev) {
  if (typeof dev === "undefined") {
   dev = mode;
   mode = 438;
  }
  mode |= 8192;
  return FS.mknod(path, mode, dev);
 },
 symlink: function(oldpath, newpath) {
  if (!PATH_FS.resolve(oldpath)) {
   throw new FS.ErrnoError(44);
  }
  var lookup = FS.lookupPath(newpath, {
   parent: true
  });
  var parent = lookup.node;
  if (!parent) {
   throw new FS.ErrnoError(44);
  }
  var newname = PATH.basename(newpath);
  var errCode = FS.mayCreate(parent, newname);
  if (errCode) {
   throw new FS.ErrnoError(errCode);
  }
  if (!parent.node_ops.symlink) {
   throw new FS.ErrnoError(63);
  }
  return parent.node_ops.symlink(parent, newname, oldpath);
 },
 rename: function(old_path, new_path) {
  var old_dirname = PATH.dirname(old_path);
  var new_dirname = PATH.dirname(new_path);
  var old_name = PATH.basename(old_path);
  var new_name = PATH.basename(new_path);
  var lookup, old_dir, new_dir;
  lookup = FS.lookupPath(old_path, {
   parent: true
  });
  old_dir = lookup.node;
  lookup = FS.lookupPath(new_path, {
   parent: true
  });
  new_dir = lookup.node;
  if (!old_dir || !new_dir) throw new FS.ErrnoError(44);
  if (old_dir.mount !== new_dir.mount) {
   throw new FS.ErrnoError(75);
  }
  var old_node = FS.lookupNode(old_dir, old_name);
  var relative = PATH_FS.relative(old_path, new_dirname);
  if (relative.charAt(0) !== ".") {
   throw new FS.ErrnoError(28);
  }
  relative = PATH_FS.relative(new_path, old_dirname);
  if (relative.charAt(0) !== ".") {
   throw new FS.ErrnoError(55);
  }
  var new_node;
  try {
   new_node = FS.lookupNode(new_dir, new_name);
  } catch (e) {}
  if (old_node === new_node) {
   return;
  }
  var isdir = FS.isDir(old_node.mode);
  var errCode = FS.mayDelete(old_dir, old_name, isdir);
  if (errCode) {
   throw new FS.ErrnoError(errCode);
  }
  errCode = new_node ? FS.mayDelete(new_dir, new_name, isdir) : FS.mayCreate(new_dir, new_name);
  if (errCode) {
   throw new FS.ErrnoError(errCode);
  }
  if (!old_dir.node_ops.rename) {
   throw new FS.ErrnoError(63);
  }
  if (FS.isMountpoint(old_node) || new_node && FS.isMountpoint(new_node)) {
   throw new FS.ErrnoError(10);
  }
  if (new_dir !== old_dir) {
   errCode = FS.nodePermissions(old_dir, "w");
   if (errCode) {
    throw new FS.ErrnoError(errCode);
   }
  }
  try {
   if (FS.trackingDelegate["willMovePath"]) {
    FS.trackingDelegate["willMovePath"](old_path, new_path);
   }
  } catch (e) {
   err("FS.trackingDelegate['willMovePath']('" + old_path + "', '" + new_path + "') threw an exception: " + e.message);
  }
  FS.hashRemoveNode(old_node);
  try {
   old_dir.node_ops.rename(old_node, new_dir, new_name);
  } catch (e) {
   throw e;
  } finally {
   FS.hashAddNode(old_node);
  }
  try {
   if (FS.trackingDelegate["onMovePath"]) FS.trackingDelegate["onMovePath"](old_path, new_path);
  } catch (e) {
   err("FS.trackingDelegate['onMovePath']('" + old_path + "', '" + new_path + "') threw an exception: " + e.message);
  }
 },
 rmdir: function(path) {
  var lookup = FS.lookupPath(path, {
   parent: true
  });
  var parent = lookup.node;
  var name = PATH.basename(path);
  var node = FS.lookupNode(parent, name);
  var errCode = FS.mayDelete(parent, name, true);
  if (errCode) {
   throw new FS.ErrnoError(errCode);
  }
  if (!parent.node_ops.rmdir) {
   throw new FS.ErrnoError(63);
  }
  if (FS.isMountpoint(node)) {
   throw new FS.ErrnoError(10);
  }
  try {
   if (FS.trackingDelegate["willDeletePath"]) {
    FS.trackingDelegate["willDeletePath"](path);
   }
  } catch (e) {
   err("FS.trackingDelegate['willDeletePath']('" + path + "') threw an exception: " + e.message);
  }
  parent.node_ops.rmdir(parent, name);
  FS.destroyNode(node);
  try {
   if (FS.trackingDelegate["onDeletePath"]) FS.trackingDelegate["onDeletePath"](path);
  } catch (e) {
   err("FS.trackingDelegate['onDeletePath']('" + path + "') threw an exception: " + e.message);
  }
 },
 readdir: function(path) {
  var lookup = FS.lookupPath(path, {
   follow: true
  });
  var node = lookup.node;
  if (!node.node_ops.readdir) {
   throw new FS.ErrnoError(54);
  }
  return node.node_ops.readdir(node);
 },
 unlink: function(path) {
  var lookup = FS.lookupPath(path, {
   parent: true
  });
  var parent = lookup.node;
  var name = PATH.basename(path);
  var node = FS.lookupNode(parent, name);
  var errCode = FS.mayDelete(parent, name, false);
  if (errCode) {
   throw new FS.ErrnoError(errCode);
  }
  if (!parent.node_ops.unlink) {
   throw new FS.ErrnoError(63);
  }
  if (FS.isMountpoint(node)) {
   throw new FS.ErrnoError(10);
  }
  try {
   if (FS.trackingDelegate["willDeletePath"]) {
    FS.trackingDelegate["willDeletePath"](path);
   }
  } catch (e) {
   err("FS.trackingDelegate['willDeletePath']('" + path + "') threw an exception: " + e.message);
  }
  parent.node_ops.unlink(parent, name);
  FS.destroyNode(node);
  try {
   if (FS.trackingDelegate["onDeletePath"]) FS.trackingDelegate["onDeletePath"](path);
  } catch (e) {
   err("FS.trackingDelegate['onDeletePath']('" + path + "') threw an exception: " + e.message);
  }
 },
 readlink: function(path) {
  var lookup = FS.lookupPath(path);
  var link = lookup.node;
  if (!link) {
   throw new FS.ErrnoError(44);
  }
  if (!link.node_ops.readlink) {
   throw new FS.ErrnoError(28);
  }
  return PATH_FS.resolve(FS.getPath(link.parent), link.node_ops.readlink(link));
 },
 stat: function(path, dontFollow) {
  var lookup = FS.lookupPath(path, {
   follow: !dontFollow
  });
  var node = lookup.node;
  if (!node) {
   throw new FS.ErrnoError(44);
  }
  if (!node.node_ops.getattr) {
   throw new FS.ErrnoError(63);
  }
  return node.node_ops.getattr(node);
 },
 lstat: function(path) {
  return FS.stat(path, true);
 },
 chmod: function(path, mode, dontFollow) {
  var node;
  if (typeof path === "string") {
   var lookup = FS.lookupPath(path, {
    follow: !dontFollow
   });
   node = lookup.node;
  } else {
   node = path;
  }
  if (!node.node_ops.setattr) {
   throw new FS.ErrnoError(63);
  }
  node.node_ops.setattr(node, {
   mode: mode & 4095 | node.mode & ~4095,
   timestamp: Date.now()
  });
 },
 lchmod: function(path, mode) {
  FS.chmod(path, mode, true);
 },
 fchmod: function(fd, mode) {
  var stream = FS.getStream(fd);
  if (!stream) {
   throw new FS.ErrnoError(8);
  }
  FS.chmod(stream.node, mode);
 },
 chown: function(path, uid, gid, dontFollow) {
  var node;
  if (typeof path === "string") {
   var lookup = FS.lookupPath(path, {
    follow: !dontFollow
   });
   node = lookup.node;
  } else {
   node = path;
  }
  if (!node.node_ops.setattr) {
   throw new FS.ErrnoError(63);
  }
  node.node_ops.setattr(node, {
   timestamp: Date.now()
  });
 },
 lchown: function(path, uid, gid) {
  FS.chown(path, uid, gid, true);
 },
 fchown: function(fd, uid, gid) {
  var stream = FS.getStream(fd);
  if (!stream) {
   throw new FS.ErrnoError(8);
  }
  FS.chown(stream.node, uid, gid);
 },
 truncate: function(path, len) {
  if (len < 0) {
   throw new FS.ErrnoError(28);
  }
  var node;
  if (typeof path === "string") {
   var lookup = FS.lookupPath(path, {
    follow: true
   });
   node = lookup.node;
  } else {
   node = path;
  }
  if (!node.node_ops.setattr) {
   throw new FS.ErrnoError(63);
  }
  if (FS.isDir(node.mode)) {
   throw new FS.ErrnoError(31);
  }
  if (!FS.isFile(node.mode)) {
   throw new FS.ErrnoError(28);
  }
  var errCode = FS.nodePermissions(node, "w");
  if (errCode) {
   throw new FS.ErrnoError(errCode);
  }
  node.node_ops.setattr(node, {
   size: len,
   timestamp: Date.now()
  });
 },
 ftruncate: function(fd, len) {
  var stream = FS.getStream(fd);
  if (!stream) {
   throw new FS.ErrnoError(8);
  }
  if ((stream.flags & 2097155) === 0) {
   throw new FS.ErrnoError(28);
  }
  FS.truncate(stream.node, len);
 },
 utime: function(path, atime, mtime) {
  var lookup = FS.lookupPath(path, {
   follow: true
  });
  var node = lookup.node;
  node.node_ops.setattr(node, {
   timestamp: Math.max(atime, mtime)
  });
 },
 open: function(path, flags, mode, fd_start, fd_end) {
  if (path === "") {
   throw new FS.ErrnoError(44);
  }
  flags = typeof flags === "string" ? FS.modeStringToFlags(flags) : flags;
  mode = typeof mode === "undefined" ? 438 : mode;
  if (flags & 64) {
   mode = mode & 4095 | 32768;
  } else {
   mode = 0;
  }
  var node;
  if (typeof path === "object") {
   node = path;
  } else {
   path = PATH.normalize(path);
   try {
    var lookup = FS.lookupPath(path, {
     follow: !(flags & 131072)
    });
    node = lookup.node;
   } catch (e) {}
  }
  var created = false;
  if (flags & 64) {
   if (node) {
    if (flags & 128) {
     throw new FS.ErrnoError(20);
    }
   } else {
    node = FS.mknod(path, mode, 0);
    created = true;
   }
  }
  if (!node) {
   throw new FS.ErrnoError(44);
  }
  if (FS.isChrdev(node.mode)) {
   flags &= ~512;
  }
  if (flags & 65536 && !FS.isDir(node.mode)) {
   throw new FS.ErrnoError(54);
  }
  if (!created) {
   var errCode = FS.mayOpen(node, flags);
   if (errCode) {
    throw new FS.ErrnoError(errCode);
   }
  }
  if (flags & 512) {
   FS.truncate(node, 0);
  }
  flags &= ~(128 | 512 | 131072);
  var stream = FS.createStream({
   node: node,
   path: FS.getPath(node),
   flags: flags,
   seekable: true,
   position: 0,
   stream_ops: node.stream_ops,
   ungotten: [],
   error: false
  }, fd_start, fd_end);
  if (stream.stream_ops.open) {
   stream.stream_ops.open(stream);
  }
  if (Module["logReadFiles"] && !(flags & 1)) {
   if (!FS.readFiles) FS.readFiles = {};
   if (!(path in FS.readFiles)) {
    FS.readFiles[path] = 1;
    err("FS.trackingDelegate error on read file: " + path);
   }
  }
  try {
   if (FS.trackingDelegate["onOpenFile"]) {
    var trackingFlags = 0;
    if ((flags & 2097155) !== 1) {
     trackingFlags |= FS.tracking.openFlags.READ;
    }
    if ((flags & 2097155) !== 0) {
     trackingFlags |= FS.tracking.openFlags.WRITE;
    }
    FS.trackingDelegate["onOpenFile"](path, trackingFlags);
   }
  } catch (e) {
   err("FS.trackingDelegate['onOpenFile']('" + path + "', flags) threw an exception: " + e.message);
  }
  return stream;
 },
 close: function(stream) {
  if (FS.isClosed(stream)) {
   throw new FS.ErrnoError(8);
  }
  if (stream.getdents) stream.getdents = null;
  try {
   if (stream.stream_ops.close) {
    stream.stream_ops.close(stream);
   }
  } catch (e) {
   throw e;
  } finally {
   FS.closeStream(stream.fd);
  }
  stream.fd = null;
 },
 isClosed: function(stream) {
  return stream.fd === null;
 },
 llseek: function(stream, offset, whence) {
  if (FS.isClosed(stream)) {
   throw new FS.ErrnoError(8);
  }
  if (!stream.seekable || !stream.stream_ops.llseek) {
   throw new FS.ErrnoError(70);
  }
  if (whence != 0 && whence != 1 && whence != 2) {
   throw new FS.ErrnoError(28);
  }
  stream.position = stream.stream_ops.llseek(stream, offset, whence);
  stream.ungotten = [];
  return stream.position;
 },
 read: function(stream, buffer, offset, length, position) {
  if (length < 0 || position < 0) {
   throw new FS.ErrnoError(28);
  }
  if (FS.isClosed(stream)) {
   throw new FS.ErrnoError(8);
  }
  if ((stream.flags & 2097155) === 1) {
   throw new FS.ErrnoError(8);
  }
  if (FS.isDir(stream.node.mode)) {
   throw new FS.ErrnoError(31);
  }
  if (!stream.stream_ops.read) {
   throw new FS.ErrnoError(28);
  }
  var seeking = typeof position !== "undefined";
  if (!seeking) {
   position = stream.position;
  } else if (!stream.seekable) {
   throw new FS.ErrnoError(70);
  }
  var bytesRead = stream.stream_ops.read(stream, buffer, offset, length, position);
  if (!seeking) stream.position += bytesRead;
  return bytesRead;
 },
 write: function(stream, buffer, offset, length, position, canOwn) {
  if (length < 0 || position < 0) {
   throw new FS.ErrnoError(28);
  }
  if (FS.isClosed(stream)) {
   throw new FS.ErrnoError(8);
  }
  if ((stream.flags & 2097155) === 0) {
   throw new FS.ErrnoError(8);
  }
  if (FS.isDir(stream.node.mode)) {
   throw new FS.ErrnoError(31);
  }
  if (!stream.stream_ops.write) {
   throw new FS.ErrnoError(28);
  }
  if (stream.seekable && stream.flags & 1024) {
   FS.llseek(stream, 0, 2);
  }
  var seeking = typeof position !== "undefined";
  if (!seeking) {
   position = stream.position;
  } else if (!stream.seekable) {
   throw new FS.ErrnoError(70);
  }
  var bytesWritten = stream.stream_ops.write(stream, buffer, offset, length, position, canOwn);
  if (!seeking) stream.position += bytesWritten;
  try {
   if (stream.path && FS.trackingDelegate["onWriteToFile"]) FS.trackingDelegate["onWriteToFile"](stream.path);
  } catch (e) {
   err("FS.trackingDelegate['onWriteToFile']('" + stream.path + "') threw an exception: " + e.message);
  }
  return bytesWritten;
 },
 allocate: function(stream, offset, length) {
  if (FS.isClosed(stream)) {
   throw new FS.ErrnoError(8);
  }
  if (offset < 0 || length <= 0) {
   throw new FS.ErrnoError(28);
  }
  if ((stream.flags & 2097155) === 0) {
   throw new FS.ErrnoError(8);
  }
  if (!FS.isFile(stream.node.mode) && !FS.isDir(stream.node.mode)) {
   throw new FS.ErrnoError(43);
  }
  if (!stream.stream_ops.allocate) {
   throw new FS.ErrnoError(138);
  }
  stream.stream_ops.allocate(stream, offset, length);
 },
 mmap: function(stream, address, length, position, prot, flags) {
  if ((prot & 2) !== 0 && (flags & 2) === 0 && (stream.flags & 2097155) !== 2) {
   throw new FS.ErrnoError(2);
  }
  if ((stream.flags & 2097155) === 1) {
   throw new FS.ErrnoError(2);
  }
  if (!stream.stream_ops.mmap) {
   throw new FS.ErrnoError(43);
  }
  return stream.stream_ops.mmap(stream, address, length, position, prot, flags);
 },
 msync: function(stream, buffer, offset, length, mmapFlags) {
  if (!stream || !stream.stream_ops.msync) {
   return 0;
  }
  return stream.stream_ops.msync(stream, buffer, offset, length, mmapFlags);
 },
 munmap: function(stream) {
  return 0;
 },
 ioctl: function(stream, cmd, arg) {
  if (!stream.stream_ops.ioctl) {
   throw new FS.ErrnoError(59);
  }
  return stream.stream_ops.ioctl(stream, cmd, arg);
 },
 readFile: function(path, opts) {
  opts = opts || {};
  opts.flags = opts.flags || 0;
  opts.encoding = opts.encoding || "binary";
  if (opts.encoding !== "utf8" && opts.encoding !== "binary") {
   throw new Error('Invalid encoding type "' + opts.encoding + '"');
  }
  var ret;
  var stream = FS.open(path, opts.flags);
  var stat = FS.stat(path);
  var length = stat.size;
  var buf = new Uint8Array(length);
  FS.read(stream, buf, 0, length, 0);
  if (opts.encoding === "utf8") {
   ret = UTF8ArrayToString(buf, 0);
  } else if (opts.encoding === "binary") {
   ret = buf;
  }
  FS.close(stream);
  return ret;
 },
 writeFile: function(path, data, opts) {
  opts = opts || {};
  opts.flags = opts.flags || 577;
  var stream = FS.open(path, opts.flags, opts.mode);
  if (typeof data === "string") {
   var buf = new Uint8Array(lengthBytesUTF8(data) + 1);
   var actualNumBytes = stringToUTF8Array(data, buf, 0, buf.length);
   FS.write(stream, buf, 0, actualNumBytes, undefined, opts.canOwn);
  } else if (ArrayBuffer.isView(data)) {
   FS.write(stream, data, 0, data.byteLength, undefined, opts.canOwn);
  } else {
   throw new Error("Unsupported data type");
  }
  FS.close(stream);
 },
 cwd: function() {
  return FS.currentPath;
 },
 chdir: function(path) {
  var lookup = FS.lookupPath(path, {
   follow: true
  });
  if (lookup.node === null) {
   throw new FS.ErrnoError(44);
  }
  if (!FS.isDir(lookup.node.mode)) {
   throw new FS.ErrnoError(54);
  }
  var errCode = FS.nodePermissions(lookup.node, "x");
  if (errCode) {
   throw new FS.ErrnoError(errCode);
  }
  FS.currentPath = lookup.path;
 },
 createDefaultDirectories: function() {
  FS.mkdir("/tmp");
  FS.mkdir("/home");
  FS.mkdir("/home/web_user");
 },
 createDefaultDevices: function() {
  FS.mkdir("/dev");
  FS.registerDevice(FS.makedev(1, 3), {
   read: function() {
    return 0;
   },
   write: function(stream, buffer, offset, length, pos) {
    return length;
   }
  });
  FS.mkdev("/dev/null", FS.makedev(1, 3));
  TTY.register(FS.makedev(5, 0), TTY.default_tty_ops);
  TTY.register(FS.makedev(6, 0), TTY.default_tty1_ops);
  FS.mkdev("/dev/tty", FS.makedev(5, 0));
  FS.mkdev("/dev/tty1", FS.makedev(6, 0));
  var random_device = getRandomDevice();
  FS.createDevice("/dev", "random", random_device);
  FS.createDevice("/dev", "urandom", random_device);
  FS.mkdir("/dev/shm");
  FS.mkdir("/dev/shm/tmp");
 },
 createSpecialDirectories: function() {
  FS.mkdir("/proc");
  var proc_self = FS.mkdir("/proc/self");
  FS.mkdir("/proc/self/fd");
  FS.mount({
   mount: function() {
    var node = FS.createNode(proc_self, "fd", 16384 | 511, 73);
    node.node_ops = {
     lookup: function(parent, name) {
      var fd = +name;
      var stream = FS.getStream(fd);
      if (!stream) throw new FS.ErrnoError(8);
      var ret = {
       parent: null,
       mount: {
        mountpoint: "fake"
       },
       node_ops: {
        readlink: function() {
         return stream.path;
        }
       }
      };
      ret.parent = ret;
      return ret;
     }
    };
    return node;
   }
  }, {}, "/proc/self/fd");
 },
 createStandardStreams: function() {
  if (Module["stdin"]) {
   FS.createDevice("/dev", "stdin", Module["stdin"]);
  } else {
   FS.symlink("/dev/tty", "/dev/stdin");
  }
  if (Module["stdout"]) {
   FS.createDevice("/dev", "stdout", null, Module["stdout"]);
  } else {
   FS.symlink("/dev/tty", "/dev/stdout");
  }
  if (Module["stderr"]) {
   FS.createDevice("/dev", "stderr", null, Module["stderr"]);
  } else {
   FS.symlink("/dev/tty1", "/dev/stderr");
  }
  var stdin = FS.open("/dev/stdin", 0);
  var stdout = FS.open("/dev/stdout", 1);
  var stderr = FS.open("/dev/stderr", 1);
  assert(stdin.fd === 0, "invalid handle for stdin (" + stdin.fd + ")");
  assert(stdout.fd === 1, "invalid handle for stdout (" + stdout.fd + ")");
  assert(stderr.fd === 2, "invalid handle for stderr (" + stderr.fd + ")");
 },
 ensureErrnoError: function() {
  if (FS.ErrnoError) return;
  FS.ErrnoError = function ErrnoError(errno, node) {
   this.node = node;
   this.setErrno = function(errno) {
    this.errno = errno;
    for (var key in ERRNO_CODES) {
     if (ERRNO_CODES[key] === errno) {
      this.code = key;
      break;
     }
    }
   };
   this.setErrno(errno);
   this.message = ERRNO_MESSAGES[errno];
   if (this.stack) {
    Object.defineProperty(this, "stack", {
     value: new Error().stack,
     writable: true
    });
    this.stack = demangleAll(this.stack);
   }
  };
  FS.ErrnoError.prototype = new Error();
  FS.ErrnoError.prototype.constructor = FS.ErrnoError;
  [ 44 ].forEach(function(code) {
   FS.genericErrors[code] = new FS.ErrnoError(code);
   FS.genericErrors[code].stack = "<generic error, no stack>";
  });
 },
 staticInit: function() {
  FS.ensureErrnoError();
  FS.nameTable = new Array(4096);
  FS.mount(MEMFS, {}, "/");
  FS.createDefaultDirectories();
  FS.createDefaultDevices();
  FS.createSpecialDirectories();
  FS.filesystems = {
   "MEMFS": MEMFS,
   "WORKERFS": WORKERFS
  };
 },
 init: function(input, output, error) {
  assert(!FS.init.initialized, "FS.init was previously called. If you want to initialize later with custom parameters, remove any earlier calls (note that one is automatically added to the generated code)");
  FS.init.initialized = true;
  FS.ensureErrnoError();
  Module["stdin"] = input || Module["stdin"];
  Module["stdout"] = output || Module["stdout"];
  Module["stderr"] = error || Module["stderr"];
  FS.createStandardStreams();
 },
 quit: function() {
  FS.init.initialized = false;
  var fflush = Module["_fflush"];
  if (fflush) fflush(0);
  for (var i = 0; i < FS.streams.length; i++) {
   var stream = FS.streams[i];
   if (!stream) {
    continue;
   }
   FS.close(stream);
  }
 },
 getMode: function(canRead, canWrite) {
  var mode = 0;
  if (canRead) mode |= 292 | 73;
  if (canWrite) mode |= 146;
  return mode;
 },
 findObject: function(path, dontResolveLastLink) {
  var ret = FS.analyzePath(path, dontResolveLastLink);
  if (ret.exists) {
   return ret.object;
  } else {
   return null;
  }
 },
 analyzePath: function(path, dontResolveLastLink) {
  try {
   var lookup = FS.lookupPath(path, {
    follow: !dontResolveLastLink
   });
   path = lookup.path;
  } catch (e) {}
  var ret = {
   isRoot: false,
   exists: false,
   error: 0,
   name: null,
   path: null,
   object: null,
   parentExists: false,
   parentPath: null,
   parentObject: null
  };
  try {
   var lookup = FS.lookupPath(path, {
    parent: true
   });
   ret.parentExists = true;
   ret.parentPath = lookup.path;
   ret.parentObject = lookup.node;
   ret.name = PATH.basename(path);
   lookup = FS.lookupPath(path, {
    follow: !dontResolveLastLink
   });
   ret.exists = true;
   ret.path = lookup.path;
   ret.object = lookup.node;
   ret.name = lookup.node.name;
   ret.isRoot = lookup.path === "/";
  } catch (e) {
   ret.error = e.errno;
  }
  return ret;
 },
 createPath: function(parent, path, canRead, canWrite) {
  parent = typeof parent === "string" ? parent : FS.getPath(parent);
  var parts = path.split("/").reverse();
  while (parts.length) {
   var part = parts.pop();
   if (!part) continue;
   var current = PATH.join2(parent, part);
   try {
    FS.mkdir(current);
   } catch (e) {}
   parent = current;
  }
  return current;
 },
 createFile: function(parent, name, properties, canRead, canWrite) {
  var path = PATH.join2(typeof parent === "string" ? parent : FS.getPath(parent), name);
  var mode = FS.getMode(canRead, canWrite);
  return FS.create(path, mode);
 },
 createDataFile: function(parent, name, data, canRead, canWrite, canOwn) {
  var path = name ? PATH.join2(typeof parent === "string" ? parent : FS.getPath(parent), name) : parent;
  var mode = FS.getMode(canRead, canWrite);
  var node = FS.create(path, mode);
  if (data) {
   if (typeof data === "string") {
    var arr = new Array(data.length);
    for (var i = 0, len = data.length; i < len; ++i) arr[i] = data.charCodeAt(i);
    data = arr;
   }
   FS.chmod(node, mode | 146);
   var stream = FS.open(node, 577);
   FS.write(stream, data, 0, data.length, 0, canOwn);
   FS.close(stream);
   FS.chmod(node, mode);
  }
  return node;
 },
 createDevice: function(parent, name, input, output) {
  var path = PATH.join2(typeof parent === "string" ? parent : FS.getPath(parent), name);
  var mode = FS.getMode(!!input, !!output);
  if (!FS.createDevice.major) FS.createDevice.major = 64;
  var dev = FS.makedev(FS.createDevice.major++, 0);
  FS.registerDevice(dev, {
   open: function(stream) {
    stream.seekable = false;
   },
   close: function(stream) {
    if (output && output.buffer && output.buffer.length) {
     output(10);
    }
   },
   read: function(stream, buffer, offset, length, pos) {
    var bytesRead = 0;
    for (var i = 0; i < length; i++) {
     var result;
     try {
      result = input();
     } catch (e) {
      throw new FS.ErrnoError(29);
     }
     if (result === undefined && bytesRead === 0) {
      throw new FS.ErrnoError(6);
     }
     if (result === null || result === undefined) break;
     bytesRead++;
     buffer[offset + i] = result;
    }
    if (bytesRead) {
     stream.node.timestamp = Date.now();
    }
    return bytesRead;
   },
   write: function(stream, buffer, offset, length, pos) {
    for (var i = 0; i < length; i++) {
     try {
      output(buffer[offset + i]);
     } catch (e) {
      throw new FS.ErrnoError(29);
     }
    }
    if (length) {
     stream.node.timestamp = Date.now();
    }
    return i;
   }
  });
  return FS.mkdev(path, mode, dev);
 },
 forceLoadFile: function(obj) {
  if (obj.isDevice || obj.isFolder || obj.link || obj.contents) return true;
  if (typeof XMLHttpRequest !== "undefined") {
   throw new Error("Lazy loading should have been performed (contents set) in createLazyFile, but it was not. Lazy loading only works in web workers. Use --embed-file or --preload-file in emcc on the main thread.");
  } else if (read_) {
   try {
    obj.contents = intArrayFromString(read_(obj.url), true);
    obj.usedBytes = obj.contents.length;
   } catch (e) {
    throw new FS.ErrnoError(29);
   }
  } else {
   throw new Error("Cannot load without read() or XMLHttpRequest.");
  }
 },
 createLazyFile: function(parent, name, url, canRead, canWrite) {
  function LazyUint8Array() {
   this.lengthKnown = false;
   this.chunks = [];
  }
  LazyUint8Array.prototype.get = function LazyUint8Array_get(idx) {
   if (idx > this.length - 1 || idx < 0) {
    return undefined;
   }
   var chunkOffset = idx % this.chunkSize;
   var chunkNum = idx / this.chunkSize | 0;
   return this.getter(chunkNum)[chunkOffset];
  };
  LazyUint8Array.prototype.setDataGetter = function LazyUint8Array_setDataGetter(getter) {
   this.getter = getter;
  };
  LazyUint8Array.prototype.cacheLength = function LazyUint8Array_cacheLength() {
   var xhr = new XMLHttpRequest();
   xhr.open("HEAD", url, false);
   xhr.send(null);
   if (!(xhr.status >= 200 && xhr.status < 300 || xhr.status === 304)) throw new Error("Couldn't load " + url + ". Status: " + xhr.status);
   var datalength = Number(xhr.getResponseHeader("Content-length"));
   var header;
   var hasByteServing = (header = xhr.getResponseHeader("Accept-Ranges")) && header === "bytes";
   var usesGzip = (header = xhr.getResponseHeader("Content-Encoding")) && header === "gzip";
   var chunkSize = 1024 * 1024;
   if (!hasByteServing) chunkSize = datalength;
   var doXHR = function(from, to) {
    if (from > to) throw new Error("invalid range (" + from + ", " + to + ") or no bytes requested!");
    if (to > datalength - 1) throw new Error("only " + datalength + " bytes available! programmer error!");
    var xhr = new XMLHttpRequest();
    xhr.open("GET", url, false);
    if (datalength !== chunkSize) xhr.setRequestHeader("Range", "bytes=" + from + "-" + to);
    if (typeof Uint8Array != "undefined") xhr.responseType = "arraybuffer";
    if (xhr.overrideMimeType) {
     xhr.overrideMimeType("text/plain; charset=x-user-defined");
    }
    xhr.send(null);
    if (!(xhr.status >= 200 && xhr.status < 300 || xhr.status === 304)) throw new Error("Couldn't load " + url + ". Status: " + xhr.status);
    if (xhr.response !== undefined) {
     return new Uint8Array(xhr.response || []);
    } else {
     return intArrayFromString(xhr.responseText || "", true);
    }
   };
   var lazyArray = this;
   lazyArray.setDataGetter(function(chunkNum) {
    var start = chunkNum * chunkSize;
    var end = (chunkNum + 1) * chunkSize - 1;
    end = Math.min(end, datalength - 1);
    if (typeof lazyArray.chunks[chunkNum] === "undefined") {
     lazyArray.chunks[chunkNum] = doXHR(start, end);
    }
    if (typeof lazyArray.chunks[chunkNum] === "undefined") throw new Error("doXHR failed!");
    return lazyArray.chunks[chunkNum];
   });
   if (usesGzip || !datalength) {
    chunkSize = datalength = 1;
    datalength = this.getter(0).length;
    chunkSize = datalength;
    out("LazyFiles on gzip forces download of the whole file when length is accessed");
   }
   this._length = datalength;
   this._chunkSize = chunkSize;
   this.lengthKnown = true;
  };
  if (typeof XMLHttpRequest !== "undefined") {
   if (!ENVIRONMENT_IS_WORKER) throw "Cannot do synchronous binary XHRs outside webworkers in modern browsers. Use --embed-file or --preload-file in emcc";
   var lazyArray = new LazyUint8Array();
   Object.defineProperties(lazyArray, {
    length: {
     get: function() {
      if (!this.lengthKnown) {
       this.cacheLength();
      }
      return this._length;
     }
    },
    chunkSize: {
     get: function() {
      if (!this.lengthKnown) {
       this.cacheLength();
      }
      return this._chunkSize;
     }
    }
   });
   var properties = {
    isDevice: false,
    contents: lazyArray
   };
  } else {
   var properties = {
    isDevice: false,
    url: url
   };
  }
  var node = FS.createFile(parent, name, properties, canRead, canWrite);
  if (properties.contents) {
   node.contents = properties.contents;
  } else if (properties.url) {
   node.contents = null;
   node.url = properties.url;
  }
  Object.defineProperties(node, {
   usedBytes: {
    get: function() {
     return this.contents.length;
    }
   }
  });
  var stream_ops = {};
  var keys = Object.keys(node.stream_ops);
  keys.forEach(function(key) {
   var fn = node.stream_ops[key];
   stream_ops[key] = function forceLoadLazyFile() {
    FS.forceLoadFile(node);
    return fn.apply(null, arguments);
   };
  });
  stream_ops.read = function stream_ops_read(stream, buffer, offset, length, position) {
   FS.forceLoadFile(node);
   var contents = stream.node.contents;
   if (position >= contents.length) return 0;
   var size = Math.min(contents.length - position, length);
   assert(size >= 0);
   if (contents.slice) {
    for (var i = 0; i < size; i++) {
     buffer[offset + i] = contents[position + i];
    }
   } else {
    for (var i = 0; i < size; i++) {
     buffer[offset + i] = contents.get(position + i);
    }
   }
   return size;
  };
  node.stream_ops = stream_ops;
  return node;
 },
 createPreloadedFile: function(parent, name, url, canRead, canWrite, onload, onerror, dontCreateFile, canOwn, preFinish) {
  Browser.init();
  var fullname = name ? PATH_FS.resolve(PATH.join2(parent, name)) : parent;
  var dep = getUniqueRunDependency("cp " + fullname);
  function processData(byteArray) {
   function finish(byteArray) {
    if (preFinish) preFinish();
    if (!dontCreateFile) {
     FS.createDataFile(parent, name, byteArray, canRead, canWrite, canOwn);
    }
    if (onload) onload();
    removeRunDependency(dep);
   }
   var handled = false;
   Module["preloadPlugins"].forEach(function(plugin) {
    if (handled) return;
    if (plugin["canHandle"](fullname)) {
     plugin["handle"](byteArray, fullname, finish, function() {
      if (onerror) onerror();
      removeRunDependency(dep);
     });
     handled = true;
    }
   });
   if (!handled) finish(byteArray);
  }
  addRunDependency(dep);
  if (typeof url == "string") {
   Browser.asyncLoad(url, function(byteArray) {
    processData(byteArray);
   }, onerror);
  } else {
   processData(url);
  }
 },
 indexedDB: function() {
  return window.indexedDB || window.mozIndexedDB || window.webkitIndexedDB || window.msIndexedDB;
 },
 DB_NAME: function() {
  return "EM_FS_" + window.location.pathname;
 },
 DB_VERSION: 20,
 DB_STORE_NAME: "FILE_DATA",
 saveFilesToDB: function(paths, onload, onerror) {
  onload = onload || function() {};
  onerror = onerror || function() {};
  var indexedDB = FS.indexedDB();
  try {
   var openRequest = indexedDB.open(FS.DB_NAME(), FS.DB_VERSION);
  } catch (e) {
   return onerror(e);
  }
  openRequest.onupgradeneeded = function openRequest_onupgradeneeded() {
   out("creating db");
   var db = openRequest.result;
   db.createObjectStore(FS.DB_STORE_NAME);
  };
  openRequest.onsuccess = function openRequest_onsuccess() {
   var db = openRequest.result;
   var transaction = db.transaction([ FS.DB_STORE_NAME ], "readwrite");
   var files = transaction.objectStore(FS.DB_STORE_NAME);
   var ok = 0, fail = 0, total = paths.length;
   function finish() {
    if (fail == 0) onload(); else onerror();
   }
   paths.forEach(function(path) {
    var putRequest = files.put(FS.analyzePath(path).object.contents, path);
    putRequest.onsuccess = function putRequest_onsuccess() {
     ok++;
     if (ok + fail == total) finish();
    };
    putRequest.onerror = function putRequest_onerror() {
     fail++;
     if (ok + fail == total) finish();
    };
   });
   transaction.onerror = onerror;
  };
  openRequest.onerror = onerror;
 },
 loadFilesFromDB: function(paths, onload, onerror) {
  onload = onload || function() {};
  onerror = onerror || function() {};
  var indexedDB = FS.indexedDB();
  try {
   var openRequest = indexedDB.open(FS.DB_NAME(), FS.DB_VERSION);
  } catch (e) {
   return onerror(e);
  }
  openRequest.onupgradeneeded = onerror;
  openRequest.onsuccess = function openRequest_onsuccess() {
   var db = openRequest.result;
   try {
    var transaction = db.transaction([ FS.DB_STORE_NAME ], "readonly");
   } catch (e) {
    onerror(e);
    return;
   }
   var files = transaction.objectStore(FS.DB_STORE_NAME);
   var ok = 0, fail = 0, total = paths.length;
   function finish() {
    if (fail == 0) onload(); else onerror();
   }
   paths.forEach(function(path) {
    var getRequest = files.get(path);
    getRequest.onsuccess = function getRequest_onsuccess() {
     if (FS.analyzePath(path).exists) {
      FS.unlink(path);
     }
     FS.createDataFile(PATH.dirname(path), PATH.basename(path), getRequest.result, true, true, true);
     ok++;
     if (ok + fail == total) finish();
    };
    getRequest.onerror = function getRequest_onerror() {
     fail++;
     if (ok + fail == total) finish();
    };
   });
   transaction.onerror = onerror;
  };
  openRequest.onerror = onerror;
 },
 absolutePath: function() {
  abort("FS.absolutePath has been removed; use PATH_FS.resolve instead");
 },
 createFolder: function() {
  abort("FS.createFolder has been removed; use FS.mkdir instead");
 },
 createLink: function() {
  abort("FS.createLink has been removed; use FS.symlink instead");
 },
 joinPath: function() {
  abort("FS.joinPath has been removed; use PATH.join instead");
 },
 mmapAlloc: function() {
  abort("FS.mmapAlloc has been replaced by the top level function mmapAlloc");
 },
 standardizePath: function() {
  abort("FS.standardizePath has been removed; use PATH.normalize instead");
 }
};

var SYSCALLS = {
 mappings: {},
 DEFAULT_POLLMASK: 5,
 umask: 511,
 calculateAt: function(dirfd, path) {
  if (path[0] !== "/") {
   var dir;
   if (dirfd === -100) {
    dir = FS.cwd();
   } else {
    var dirstream = FS.getStream(dirfd);
    if (!dirstream) throw new FS.ErrnoError(8);
    dir = dirstream.path;
   }
   path = PATH.join2(dir, path);
  }
  return path;
 },
 doStat: function(func, path, buf) {
  try {
   var stat = func(path);
  } catch (e) {
   if (e && e.node && PATH.normalize(path) !== PATH.normalize(FS.getPath(e.node))) {
    return -54;
   }
   throw e;
  }
  HEAP32[buf >> 2] = stat.dev;
  HEAP32[buf + 4 >> 2] = 0;
  HEAP32[buf + 8 >> 2] = stat.ino;
  HEAP32[buf + 12 >> 2] = stat.mode;
  HEAP32[buf + 16 >> 2] = stat.nlink;
  HEAP32[buf + 20 >> 2] = stat.uid;
  HEAP32[buf + 24 >> 2] = stat.gid;
  HEAP32[buf + 28 >> 2] = stat.rdev;
  HEAP32[buf + 32 >> 2] = 0;
  tempI64 = [ stat.size >>> 0, (tempDouble = stat.size, +Math.abs(tempDouble) >= 1 ? tempDouble > 0 ? (Math.min(+Math.floor(tempDouble / 4294967296), 4294967295) | 0) >>> 0 : ~~+Math.ceil((tempDouble - +(~~tempDouble >>> 0)) / 4294967296) >>> 0 : 0) ], 
  HEAP32[buf + 40 >> 2] = tempI64[0], HEAP32[buf + 44 >> 2] = tempI64[1];
  HEAP32[buf + 48 >> 2] = 4096;
  HEAP32[buf + 52 >> 2] = stat.blocks;
  HEAP32[buf + 56 >> 2] = stat.atime.getTime() / 1e3 | 0;
  HEAP32[buf + 60 >> 2] = 0;
  HEAP32[buf + 64 >> 2] = stat.mtime.getTime() / 1e3 | 0;
  HEAP32[buf + 68 >> 2] = 0;
  HEAP32[buf + 72 >> 2] = stat.ctime.getTime() / 1e3 | 0;
  HEAP32[buf + 76 >> 2] = 0;
  tempI64 = [ stat.ino >>> 0, (tempDouble = stat.ino, +Math.abs(tempDouble) >= 1 ? tempDouble > 0 ? (Math.min(+Math.floor(tempDouble / 4294967296), 4294967295) | 0) >>> 0 : ~~+Math.ceil((tempDouble - +(~~tempDouble >>> 0)) / 4294967296) >>> 0 : 0) ], 
  HEAP32[buf + 80 >> 2] = tempI64[0], HEAP32[buf + 84 >> 2] = tempI64[1];
  return 0;
 },
 doMsync: function(addr, stream, len, flags, offset) {
  var buffer = HEAPU8.slice(addr, addr + len);
  FS.msync(stream, buffer, offset, len, flags);
 },
 doMkdir: function(path, mode) {
  path = PATH.normalize(path);
  if (path[path.length - 1] === "/") path = path.substr(0, path.length - 1);
  FS.mkdir(path, mode, 0);
  return 0;
 },
 doMknod: function(path, mode, dev) {
  switch (mode & 61440) {
  case 32768:
  case 8192:
  case 24576:
  case 4096:
  case 49152:
   break;

  default:
   return -28;
  }
  FS.mknod(path, mode, dev);
  return 0;
 },
 doReadlink: function(path, buf, bufsize) {
  if (bufsize <= 0) return -28;
  var ret = FS.readlink(path);
  var len = Math.min(bufsize, lengthBytesUTF8(ret));
  var endChar = HEAP8[buf + len];
  stringToUTF8(ret, buf, bufsize + 1);
  HEAP8[buf + len] = endChar;
  return len;
 },
 doAccess: function(path, amode) {
  if (amode & ~7) {
   return -28;
  }
  var node;
  var lookup = FS.lookupPath(path, {
   follow: true
  });
  node = lookup.node;
  if (!node) {
   return -44;
  }
  var perms = "";
  if (amode & 4) perms += "r";
  if (amode & 2) perms += "w";
  if (amode & 1) perms += "x";
  if (perms && FS.nodePermissions(node, perms)) {
   return -2;
  }
  return 0;
 },
 doDup: function(path, flags, suggestFD) {
  var suggest = FS.getStream(suggestFD);
  if (suggest) FS.close(suggest);
  return FS.open(path, flags, 0, suggestFD, suggestFD).fd;
 },
 doReadv: function(stream, iov, iovcnt, offset) {
  var ret = 0;
  for (var i = 0; i < iovcnt; i++) {
   var ptr = HEAP32[iov + i * 8 >> 2];
   var len = HEAP32[iov + (i * 8 + 4) >> 2];
   var curr = FS.read(stream, HEAP8, ptr, len, offset);
   if (curr < 0) return -1;
   ret += curr;
   if (curr < len) break;
  }
  return ret;
 },
 doWritev: function(stream, iov, iovcnt, offset) {
  var ret = 0;
  for (var i = 0; i < iovcnt; i++) {
   var ptr = HEAP32[iov + i * 8 >> 2];
   var len = HEAP32[iov + (i * 8 + 4) >> 2];
   var curr = FS.write(stream, HEAP8, ptr, len, offset);
   if (curr < 0) return -1;
   ret += curr;
  }
  return ret;
 },
 varargs: undefined,
 get: function() {
  assert(SYSCALLS.varargs != undefined);
  SYSCALLS.varargs += 4;
  var ret = HEAP32[SYSCALLS.varargs - 4 >> 2];
  return ret;
 },
 getStr: function(ptr) {
  var ret = UTF8ToString(ptr);
  return ret;
 },
 getStreamFromFD: function(fd) {
  var stream = FS.getStream(fd);
  if (!stream) throw new FS.ErrnoError(8);
  return stream;
 },
 get64: function(low, high) {
  if (low >= 0) assert(high === 0); else assert(high === -1);
  return low;
 }
};

function ___sys_access(path, amode) {
 try {
  path = SYSCALLS.getStr(path);
  return SYSCALLS.doAccess(path, amode);
 } catch (e) {
  if (typeof FS === "undefined" || !(e instanceof FS.ErrnoError)) abort(e);
  return -e.errno;
 }
}

function ___sys_chmod(path, mode) {
 try {
  path = SYSCALLS.getStr(path);
  FS.chmod(path, mode);
  return 0;
 } catch (e) {
  if (typeof FS === "undefined" || !(e instanceof FS.ErrnoError)) abort(e);
  return -e.errno;
 }
}

function ___sys_chown32(path, owner, group) {
 try {
  path = SYSCALLS.getStr(path);
  FS.chown(path, owner, group);
  return 0;
 } catch (e) {
  if (typeof FS === "undefined" || !(e instanceof FS.ErrnoError)) abort(e);
  return -e.errno;
 }
}

function ___sys_fchmod(fd, mode) {
 try {
  FS.fchmod(fd, mode);
  return 0;
 } catch (e) {
  if (typeof FS === "undefined" || !(e instanceof FS.ErrnoError)) abort(e);
  return -e.errno;
 }
}

function ___sys_fchown32(fd, owner, group) {
 try {
  FS.fchown(fd, owner, group);
  return 0;
 } catch (e) {
  if (typeof FS === "undefined" || !(e instanceof FS.ErrnoError)) abort(e);
  return -e.errno;
 }
}

function ___sys_fcntl64(fd, cmd, varargs) {
 SYSCALLS.varargs = varargs;
 try {
  var stream = SYSCALLS.getStreamFromFD(fd);
  switch (cmd) {
  case 0:
   {
    var arg = SYSCALLS.get();
    if (arg < 0) {
     return -28;
    }
    var newStream;
    newStream = FS.open(stream.path, stream.flags, 0, arg);
    return newStream.fd;
   }

  case 1:
  case 2:
   return 0;

  case 3:
   return stream.flags;

  case 4:
   {
    var arg = SYSCALLS.get();
    stream.flags |= arg;
    return 0;
   }

  case 12:
   {
    var arg = SYSCALLS.get();
    var offset = 0;
    HEAP16[arg + offset >> 1] = 2;
    return 0;
   }

  case 13:
  case 14:
   return 0;

  case 16:
  case 8:
   return -28;

  case 9:
   setErrNo(28);
   return -1;

  default:
   {
    return -28;
   }
  }
 } catch (e) {
  if (typeof FS === "undefined" || !(e instanceof FS.ErrnoError)) abort(e);
  return -e.errno;
 }
}

function ___sys_fstat64(fd, buf) {
 try {
  var stream = SYSCALLS.getStreamFromFD(fd);
  return SYSCALLS.doStat(FS.stat, stream.path, buf);
 } catch (e) {
  if (typeof FS === "undefined" || !(e instanceof FS.ErrnoError)) abort(e);
  return -e.errno;
 }
}

function ___sys_ftruncate64(fd, zero, low, high) {
 try {
  var length = SYSCALLS.get64(low, high);
  FS.ftruncate(fd, length);
  return 0;
 } catch (e) {
  if (typeof FS === "undefined" || !(e instanceof FS.ErrnoError)) abort(e);
  return -e.errno;
 }
}

function ___sys_getcwd(buf, size) {
 try {
  if (size === 0) return -28;
  var cwd = FS.cwd();
  var cwdLengthInBytes = lengthBytesUTF8(cwd);
  if (size < cwdLengthInBytes + 1) return -68;
  stringToUTF8(cwd, buf, size);
  return buf;
 } catch (e) {
  if (typeof FS === "undefined" || !(e instanceof FS.ErrnoError)) abort(e);
  return -e.errno;
 }
}

function ___sys_getegid32() {
 return 0;
}

function ___sys_geteuid32() {
 return ___sys_getegid32();
}

function ___sys_getpid() {
 return 42;
}

function ___sys_ioctl(fd, op, varargs) {
 SYSCALLS.varargs = varargs;
 try {
  var stream = SYSCALLS.getStreamFromFD(fd);
  switch (op) {
  case 21509:
  case 21505:
   {
    if (!stream.tty) return -59;
    return 0;
   }

  case 21510:
  case 21511:
  case 21512:
  case 21506:
  case 21507:
  case 21508:
   {
    if (!stream.tty) return -59;
    return 0;
   }

  case 21519:
   {
    if (!stream.tty) return -59;
    var argp = SYSCALLS.get();
    HEAP32[argp >> 2] = 0;
    return 0;
   }

  case 21520:
   {
    if (!stream.tty) return -59;
    return -28;
   }

  case 21531:
   {
    var argp = SYSCALLS.get();
    return FS.ioctl(stream, op, argp);
   }

  case 21523:
   {
    if (!stream.tty) return -59;
    return 0;
   }

  case 21524:
   {
    if (!stream.tty) return -59;
    return 0;
   }

  default:
   abort("bad ioctl syscall " + op);
  }
 } catch (e) {
  if (typeof FS === "undefined" || !(e instanceof FS.ErrnoError)) abort(e);
  return -e.errno;
 }
}

function ___sys_lstat64(path, buf) {
 try {
  path = SYSCALLS.getStr(path);
  return SYSCALLS.doStat(FS.lstat, path, buf);
 } catch (e) {
  if (typeof FS === "undefined" || !(e instanceof FS.ErrnoError)) abort(e);
  return -e.errno;
 }
}

function ___sys_mkdir(path, mode) {
 try {
  path = SYSCALLS.getStr(path);
  return SYSCALLS.doMkdir(path, mode);
 } catch (e) {
  if (typeof FS === "undefined" || !(e instanceof FS.ErrnoError)) abort(e);
  return -e.errno;
 }
}

function syscallMmap2(addr, len, prot, flags, fd, off) {
 off <<= 12;
 var ptr;
 var allocated = false;
 if ((flags & 16) !== 0 && addr % 16384 !== 0) {
  return -28;
 }
 if ((flags & 32) !== 0) {
  ptr = _memalign(16384, len);
  if (!ptr) return -48;
  _memset(ptr, 0, len);
  allocated = true;
 } else {
  var info = FS.getStream(fd);
  if (!info) return -8;
  var res = FS.mmap(info, addr, len, off, prot, flags);
  ptr = res.ptr;
  allocated = res.allocated;
 }
 SYSCALLS.mappings[ptr] = {
  malloc: ptr,
  len: len,
  allocated: allocated,
  fd: fd,
  prot: prot,
  flags: flags,
  offset: off
 };
 return ptr;
}

function ___sys_mmap2(addr, len, prot, flags, fd, off) {
 try {
  return syscallMmap2(addr, len, prot, flags, fd, off);
 } catch (e) {
  if (typeof FS === "undefined" || !(e instanceof FS.ErrnoError)) abort(e);
  return -e.errno;
 }
}

function ___sys_mprotect(addr, len, size) {
 return 0;
}

function syscallMunmap(addr, len) {
 if ((addr | 0) === -1 || len === 0) {
  return -28;
 }
 var info = SYSCALLS.mappings[addr];
 if (!info) return 0;
 if (len === info.len) {
  var stream = FS.getStream(info.fd);
  if (stream) {
   if (info.prot & 2) {
    SYSCALLS.doMsync(addr, stream, len, info.flags, info.offset);
   }
   FS.munmap(stream);
  }
  SYSCALLS.mappings[addr] = null;
  if (info.allocated) {
   _free(info.malloc);
  }
 }
 return 0;
}

function ___sys_munmap(addr, len) {
 try {
  return syscallMunmap(addr, len);
 } catch (e) {
  if (typeof FS === "undefined" || !(e instanceof FS.ErrnoError)) abort(e);
  return -e.errno;
 }
}

function ___sys_open(path, flags, varargs) {
 SYSCALLS.varargs = varargs;
 try {
  var pathname = SYSCALLS.getStr(path);
  var mode = varargs ? SYSCALLS.get() : 0;
  var stream = FS.open(pathname, flags, mode);
  return stream.fd;
 } catch (e) {
  if (typeof FS === "undefined" || !(e instanceof FS.ErrnoError)) abort(e);
  return -e.errno;
 }
}

function ___sys_readlink(path, buf, bufsize) {
 try {
  path = SYSCALLS.getStr(path);
  return SYSCALLS.doReadlink(path, buf, bufsize);
 } catch (e) {
  if (typeof FS === "undefined" || !(e instanceof FS.ErrnoError)) abort(e);
  return -e.errno;
 }
}

function ___sys_rmdir(path) {
 try {
  path = SYSCALLS.getStr(path);
  FS.rmdir(path);
  return 0;
 } catch (e) {
  if (typeof FS === "undefined" || !(e instanceof FS.ErrnoError)) abort(e);
  return -e.errno;
 }
}

function ___sys_stat64(path, buf) {
 try {
  path = SYSCALLS.getStr(path);
  return SYSCALLS.doStat(FS.stat, path, buf);
 } catch (e) {
  if (typeof FS === "undefined" || !(e instanceof FS.ErrnoError)) abort(e);
  return -e.errno;
 }
}

function ___sys_unlink(path) {
 try {
  path = SYSCALLS.getStr(path);
  FS.unlink(path);
  return 0;
 } catch (e) {
  if (typeof FS === "undefined" || !(e instanceof FS.ErrnoError)) abort(e);
  return -e.errno;
 }
}

function _abort() {
 abort();
}

function _emscripten_memcpy_big(dest, src, num) {
 HEAPU8.copyWithin(dest, src, src + num);
}

function _emscripten_get_heap_size() {
 return HEAPU8.length;
}

function emscripten_realloc_buffer(size) {
 try {
  wasmMemory.grow(size - buffer.byteLength + 65535 >>> 16);
  updateGlobalBufferAndViews(wasmMemory.buffer);
  return 1;
 } catch (e) {
  console.error("emscripten_realloc_buffer: Attempted to grow heap from " + buffer.byteLength + " bytes to " + size + " bytes, but got error: " + e);
 }
}

function _emscripten_resize_heap(requestedSize) {
 requestedSize = requestedSize >>> 0;
 var oldSize = _emscripten_get_heap_size();
 assert(requestedSize > oldSize);
 var maxHeapSize = 2147483648;
 if (requestedSize > maxHeapSize) {
  err("Cannot enlarge memory, asked to go up to " + requestedSize + " bytes, but the limit is " + maxHeapSize + " bytes!");
  return false;
 }
 var minHeapSize = 16777216;
 for (var cutDown = 1; cutDown <= 4; cutDown *= 2) {
  var overGrownHeapSize = oldSize * (1 + .2 / cutDown);
  overGrownHeapSize = Math.min(overGrownHeapSize, requestedSize + 100663296);
  var newSize = Math.min(maxHeapSize, alignUp(Math.max(minHeapSize, requestedSize, overGrownHeapSize), 65536));
  var replacement = emscripten_realloc_buffer(newSize);
  if (replacement) {
   return true;
  }
 }
 err("Failed to grow the heap from " + oldSize + " bytes to " + newSize + " bytes, not enough memory!");
 return false;
}

function _emscripten_thread_sleep(msecs) {
 var start = _emscripten_get_now();
 while (_emscripten_get_now() - start < msecs) {}
}

var ENV = {};

function getExecutableName() {
 return thisProgram || "./this.program";
}

function getEnvStrings() {
 if (!getEnvStrings.strings) {
  var lang = (typeof navigator === "object" && navigator.languages && navigator.languages[0] || "C").replace("-", "_") + ".UTF-8";
  var env = {
   "USER": "web_user",
   "LOGNAME": "web_user",
   "PATH": "/",
   "PWD": "/",
   "HOME": "/home/web_user",
   "LANG": lang,
   "_": getExecutableName()
  };
  for (var x in ENV) {
   env[x] = ENV[x];
  }
  var strings = [];
  for (var x in env) {
   strings.push(x + "=" + env[x]);
  }
  getEnvStrings.strings = strings;
 }
 return getEnvStrings.strings;
}

function _environ_get(__environ, environ_buf) {
 try {
  var bufSize = 0;
  getEnvStrings().forEach(function(string, i) {
   var ptr = environ_buf + bufSize;
   HEAP32[__environ + i * 4 >> 2] = ptr;
   writeAsciiToMemory(string, ptr);
   bufSize += string.length + 1;
  });
  return 0;
 } catch (e) {
  if (typeof FS === "undefined" || !(e instanceof FS.ErrnoError)) abort(e);
  return e.errno;
 }
}

function _environ_sizes_get(penviron_count, penviron_buf_size) {
 try {
  var strings = getEnvStrings();
  HEAP32[penviron_count >> 2] = strings.length;
  var bufSize = 0;
  strings.forEach(function(string) {
   bufSize += string.length + 1;
  });
  HEAP32[penviron_buf_size >> 2] = bufSize;
  return 0;
 } catch (e) {
  if (typeof FS === "undefined" || !(e instanceof FS.ErrnoError)) abort(e);
  return e.errno;
 }
}

function _exit(status) {
 exit(status);
}

function _fd_close(fd) {
 try {
  var stream = SYSCALLS.getStreamFromFD(fd);
  FS.close(stream);
  return 0;
 } catch (e) {
  if (typeof FS === "undefined" || !(e instanceof FS.ErrnoError)) abort(e);
  return e.errno;
 }
}

function _fd_fdstat_get(fd, pbuf) {
 try {
  var stream = SYSCALLS.getStreamFromFD(fd);
  var type = stream.tty ? 2 : FS.isDir(stream.mode) ? 3 : FS.isLink(stream.mode) ? 7 : 4;
  HEAP8[pbuf >> 0] = type;
  return 0;
 } catch (e) {
  if (typeof FS === "undefined" || !(e instanceof FS.ErrnoError)) abort(e);
  return e.errno;
 }
}

function _fd_read(fd, iov, iovcnt, pnum) {
 try {
  var stream = SYSCALLS.getStreamFromFD(fd);
  var num = SYSCALLS.doReadv(stream, iov, iovcnt);
  HEAP32[pnum >> 2] = num;
  return 0;
 } catch (e) {
  if (typeof FS === "undefined" || !(e instanceof FS.ErrnoError)) abort(e);
  return e.errno;
 }
}

function _fd_seek(fd, offset_low, offset_high, whence, newOffset) {
 try {
  var stream = SYSCALLS.getStreamFromFD(fd);
  var HIGH_OFFSET = 4294967296;
  var offset = offset_high * HIGH_OFFSET + (offset_low >>> 0);
  var DOUBLE_LIMIT = 9007199254740992;
  if (offset <= -DOUBLE_LIMIT || offset >= DOUBLE_LIMIT) {
   return -61;
  }
  FS.llseek(stream, offset, whence);
  tempI64 = [ stream.position >>> 0, (tempDouble = stream.position, +Math.abs(tempDouble) >= 1 ? tempDouble > 0 ? (Math.min(+Math.floor(tempDouble / 4294967296), 4294967295) | 0) >>> 0 : ~~+Math.ceil((tempDouble - +(~~tempDouble >>> 0)) / 4294967296) >>> 0 : 0) ], 
  HEAP32[newOffset >> 2] = tempI64[0], HEAP32[newOffset + 4 >> 2] = tempI64[1];
  if (stream.getdents && offset === 0 && whence === 0) stream.getdents = null;
  return 0;
 } catch (e) {
  if (typeof FS === "undefined" || !(e instanceof FS.ErrnoError)) abort(e);
  return e.errno;
 }
}

function _fd_sync(fd) {
 try {
  var stream = SYSCALLS.getStreamFromFD(fd);
  if (stream.stream_ops && stream.stream_ops.fsync) {
   return -stream.stream_ops.fsync(stream);
  }
  return 0;
 } catch (e) {
  if (typeof FS === "undefined" || !(e instanceof FS.ErrnoError)) abort(e);
  return e.errno;
 }
}

function _fd_write(fd, iov, iovcnt, pnum) {
 try {
  var stream = SYSCALLS.getStreamFromFD(fd);
  var num = SYSCALLS.doWritev(stream, iov, iovcnt);
  HEAP32[pnum >> 2] = num;
  return 0;
 } catch (e) {
  if (typeof FS === "undefined" || !(e instanceof FS.ErrnoError)) abort(e);
  return e.errno;
 }
}

function _getentropy(buffer, size) {
 if (!_getentropy.randomDevice) {
  _getentropy.randomDevice = getRandomDevice();
 }
 for (var i = 0; i < size; i++) {
  HEAP8[buffer + i >> 0] = _getentropy.randomDevice();
 }
 return 0;
}

function _gettimeofday(ptr) {
 var now = Date.now();
 HEAP32[ptr >> 2] = now / 1e3 | 0;
 HEAP32[ptr + 4 >> 2] = now % 1e3 * 1e3 | 0;
 return 0;
}

function _setTempRet0($i) {
}

function __isLeapYear(year) {
 return year % 4 === 0 && (year % 100 !== 0 || year % 400 === 0);
}

function __arraySum(array, index) {
 var sum = 0;
 for (var i = 0; i <= index; sum += array[i++]) {}
 return sum;
}

var __MONTH_DAYS_LEAP = [ 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 ];

var __MONTH_DAYS_REGULAR = [ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 ];

function __addDays(date, days) {
 var newDate = new Date(date.getTime());
 while (days > 0) {
  var leap = __isLeapYear(newDate.getFullYear());
  var currentMonth = newDate.getMonth();
  var daysInCurrentMonth = (leap ? __MONTH_DAYS_LEAP : __MONTH_DAYS_REGULAR)[currentMonth];
  if (days > daysInCurrentMonth - newDate.getDate()) {
   days -= daysInCurrentMonth - newDate.getDate() + 1;
   newDate.setDate(1);
   if (currentMonth < 11) {
    newDate.setMonth(currentMonth + 1);
   } else {
    newDate.setMonth(0);
    newDate.setFullYear(newDate.getFullYear() + 1);
   }
  } else {
   newDate.setDate(newDate.getDate() + days);
   return newDate;
  }
 }
 return newDate;
}

function _strftime(s, maxsize, format, tm) {
 var tm_zone = HEAP32[tm + 40 >> 2];
 var date = {
  tm_sec: HEAP32[tm >> 2],
  tm_min: HEAP32[tm + 4 >> 2],
  tm_hour: HEAP32[tm + 8 >> 2],
  tm_mday: HEAP32[tm + 12 >> 2],
  tm_mon: HEAP32[tm + 16 >> 2],
  tm_year: HEAP32[tm + 20 >> 2],
  tm_wday: HEAP32[tm + 24 >> 2],
  tm_yday: HEAP32[tm + 28 >> 2],
  tm_isdst: HEAP32[tm + 32 >> 2],
  tm_gmtoff: HEAP32[tm + 36 >> 2],
  tm_zone: tm_zone ? UTF8ToString(tm_zone) : ""
 };
 var pattern = UTF8ToString(format);
 var EXPANSION_RULES_1 = {
  "%c": "%a %b %d %H:%M:%S %Y",
  "%D": "%m/%d/%y",
  "%F": "%Y-%m-%d",
  "%h": "%b",
  "%r": "%I:%M:%S %p",
  "%R": "%H:%M",
  "%T": "%H:%M:%S",
  "%x": "%m/%d/%y",
  "%X": "%H:%M:%S",
  "%Ec": "%c",
  "%EC": "%C",
  "%Ex": "%m/%d/%y",
  "%EX": "%H:%M:%S",
  "%Ey": "%y",
  "%EY": "%Y",
  "%Od": "%d",
  "%Oe": "%e",
  "%OH": "%H",
  "%OI": "%I",
  "%Om": "%m",
  "%OM": "%M",
  "%OS": "%S",
  "%Ou": "%u",
  "%OU": "%U",
  "%OV": "%V",
  "%Ow": "%w",
  "%OW": "%W",
  "%Oy": "%y"
 };
 for (var rule in EXPANSION_RULES_1) {
  pattern = pattern.replace(new RegExp(rule, "g"), EXPANSION_RULES_1[rule]);
 }
 var WEEKDAYS = [ "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" ];
 var MONTHS = [ "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" ];
 function leadingSomething(value, digits, character) {
  var str = typeof value === "number" ? value.toString() : value || "";
  while (str.length < digits) {
   str = character[0] + str;
  }
  return str;
 }
 function leadingNulls(value, digits) {
  return leadingSomething(value, digits, "0");
 }
 function compareByDay(date1, date2) {
  function sgn(value) {
   return value < 0 ? -1 : value > 0 ? 1 : 0;
  }
  var compare;
  if ((compare = sgn(date1.getFullYear() - date2.getFullYear())) === 0) {
   if ((compare = sgn(date1.getMonth() - date2.getMonth())) === 0) {
    compare = sgn(date1.getDate() - date2.getDate());
   }
  }
  return compare;
 }
 function getFirstWeekStartDate(janFourth) {
  switch (janFourth.getDay()) {
  case 0:
   return new Date(janFourth.getFullYear() - 1, 11, 29);

  case 1:
   return janFourth;

  case 2:
   return new Date(janFourth.getFullYear(), 0, 3);

  case 3:
   return new Date(janFourth.getFullYear(), 0, 2);

  case 4:
   return new Date(janFourth.getFullYear(), 0, 1);

  case 5:
   return new Date(janFourth.getFullYear() - 1, 11, 31);

  case 6:
   return new Date(janFourth.getFullYear() - 1, 11, 30);
  }
 }
 function getWeekBasedYear(date) {
  var thisDate = __addDays(new Date(date.tm_year + 1900, 0, 1), date.tm_yday);
  var janFourthThisYear = new Date(thisDate.getFullYear(), 0, 4);
  var janFourthNextYear = new Date(thisDate.getFullYear() + 1, 0, 4);
  var firstWeekStartThisYear = getFirstWeekStartDate(janFourthThisYear);
  var firstWeekStartNextYear = getFirstWeekStartDate(janFourthNextYear);
  if (compareByDay(firstWeekStartThisYear, thisDate) <= 0) {
   if (compareByDay(firstWeekStartNextYear, thisDate) <= 0) {
    return thisDate.getFullYear() + 1;
   } else {
    return thisDate.getFullYear();
   }
  } else {
   return thisDate.getFullYear() - 1;
  }
 }
 var EXPANSION_RULES_2 = {
  "%a": function(date) {
   return WEEKDAYS[date.tm_wday].substring(0, 3);
  },
  "%A": function(date) {
   return WEEKDAYS[date.tm_wday];
  },
  "%b": function(date) {
   return MONTHS[date.tm_mon].substring(0, 3);
  },
  "%B": function(date) {
   return MONTHS[date.tm_mon];
  },
  "%C": function(date) {
   var year = date.tm_year + 1900;
   return leadingNulls(year / 100 | 0, 2);
  },
  "%d": function(date) {
   return leadingNulls(date.tm_mday, 2);
  },
  "%e": function(date) {
   return leadingSomething(date.tm_mday, 2, " ");
  },
  "%g": function(date) {
   return getWeekBasedYear(date).toString().substring(2);
  },
  "%G": function(date) {
   return getWeekBasedYear(date);
  },
  "%H": function(date) {
   return leadingNulls(date.tm_hour, 2);
  },
  "%I": function(date) {
   var twelveHour = date.tm_hour;
   if (twelveHour == 0) twelveHour = 12; else if (twelveHour > 12) twelveHour -= 12;
   return leadingNulls(twelveHour, 2);
  },
  "%j": function(date) {
   return leadingNulls(date.tm_mday + __arraySum(__isLeapYear(date.tm_year + 1900) ? __MONTH_DAYS_LEAP : __MONTH_DAYS_REGULAR, date.tm_mon - 1), 3);
  },
  "%m": function(date) {
   return leadingNulls(date.tm_mon + 1, 2);
  },
  "%M": function(date) {
   return leadingNulls(date.tm_min, 2);
  },
  "%n": function() {
   return "\n";
  },
  "%p": function(date) {
   if (date.tm_hour >= 0 && date.tm_hour < 12) {
    return "AM";
   } else {
    return "PM";
   }
  },
  "%S": function(date) {
   return leadingNulls(date.tm_sec, 2);
  },
  "%t": function() {
   return "\t";
  },
  "%u": function(date) {
   return date.tm_wday || 7;
  },
  "%U": function(date) {
   var janFirst = new Date(date.tm_year + 1900, 0, 1);
   var firstSunday = janFirst.getDay() === 0 ? janFirst : __addDays(janFirst, 7 - janFirst.getDay());
   var endDate = new Date(date.tm_year + 1900, date.tm_mon, date.tm_mday);
   if (compareByDay(firstSunday, endDate) < 0) {
    var februaryFirstUntilEndMonth = __arraySum(__isLeapYear(endDate.getFullYear()) ? __MONTH_DAYS_LEAP : __MONTH_DAYS_REGULAR, endDate.getMonth() - 1) - 31;
    var firstSundayUntilEndJanuary = 31 - firstSunday.getDate();
    var days = firstSundayUntilEndJanuary + februaryFirstUntilEndMonth + endDate.getDate();
    return leadingNulls(Math.ceil(days / 7), 2);
   }
   return compareByDay(firstSunday, janFirst) === 0 ? "01" : "00";
  },
  "%V": function(date) {
   var janFourthThisYear = new Date(date.tm_year + 1900, 0, 4);
   var janFourthNextYear = new Date(date.tm_year + 1901, 0, 4);
   var firstWeekStartThisYear = getFirstWeekStartDate(janFourthThisYear);
   var firstWeekStartNextYear = getFirstWeekStartDate(janFourthNextYear);
   var endDate = __addDays(new Date(date.tm_year + 1900, 0, 1), date.tm_yday);
   if (compareByDay(endDate, firstWeekStartThisYear) < 0) {
    return "53";
   }
   if (compareByDay(firstWeekStartNextYear, endDate) <= 0) {
    return "01";
   }
   var daysDifference;
   if (firstWeekStartThisYear.getFullYear() < date.tm_year + 1900) {
    daysDifference = date.tm_yday + 32 - firstWeekStartThisYear.getDate();
   } else {
    daysDifference = date.tm_yday + 1 - firstWeekStartThisYear.getDate();
   }
   return leadingNulls(Math.ceil(daysDifference / 7), 2);
  },
  "%w": function(date) {
   return date.tm_wday;
  },
  "%W": function(date) {
   var janFirst = new Date(date.tm_year, 0, 1);
   var firstMonday = janFirst.getDay() === 1 ? janFirst : __addDays(janFirst, janFirst.getDay() === 0 ? 1 : 7 - janFirst.getDay() + 1);
   var endDate = new Date(date.tm_year + 1900, date.tm_mon, date.tm_mday);
   if (compareByDay(firstMonday, endDate) < 0) {
    var februaryFirstUntilEndMonth = __arraySum(__isLeapYear(endDate.getFullYear()) ? __MONTH_DAYS_LEAP : __MONTH_DAYS_REGULAR, endDate.getMonth() - 1) - 31;
    var firstMondayUntilEndJanuary = 31 - firstMonday.getDate();
    var days = firstMondayUntilEndJanuary + februaryFirstUntilEndMonth + endDate.getDate();
    return leadingNulls(Math.ceil(days / 7), 2);
   }
   return compareByDay(firstMonday, janFirst) === 0 ? "01" : "00";
  },
  "%y": function(date) {
   return (date.tm_year + 1900).toString().substring(2);
  },
  "%Y": function(date) {
   return date.tm_year + 1900;
  },
  "%z": function(date) {
   var off = date.tm_gmtoff;
   var ahead = off >= 0;
   off = Math.abs(off) / 60;
   off = off / 60 * 100 + off % 60;
   return (ahead ? "+" : "-") + String("0000" + off).slice(-4);
  },
  "%Z": function(date) {
   return date.tm_zone;
  },
  "%%": function() {
   return "%";
  }
 };
 for (var rule in EXPANSION_RULES_2) {
  if (pattern.indexOf(rule) >= 0) {
   pattern = pattern.replace(new RegExp(rule, "g"), EXPANSION_RULES_2[rule](date));
  }
 }
 var bytes = intArrayFromString(pattern, false);
 if (bytes.length > maxsize) {
  return 0;
 }
 writeArrayToMemory(bytes, s);
 return bytes.length - 1;
}

function _strftime_l(s, maxsize, format, tm) {
 return _strftime(s, maxsize, format, tm);
}

function _sysconf(name) {
 switch (name) {
 case 30:
  return 16384;

 case 85:
  var maxHeapSize = 2147483648;
  return maxHeapSize / 16384;

 case 132:
 case 133:
 case 12:
 case 137:
 case 138:
 case 15:
 case 235:
 case 16:
 case 17:
 case 18:
 case 19:
 case 20:
 case 149:
 case 13:
 case 10:
 case 236:
 case 153:
 case 9:
 case 21:
 case 22:
 case 159:
 case 154:
 case 14:
 case 77:
 case 78:
 case 139:
 case 82:
 case 68:
 case 67:
 case 164:
 case 11:
 case 29:
 case 47:
 case 48:
 case 95:
 case 52:
 case 51:
 case 46:
  return 200809;

 case 27:
 case 246:
 case 127:
 case 128:
 case 23:
 case 24:
 case 160:
 case 161:
 case 181:
 case 182:
 case 242:
 case 183:
 case 184:
 case 243:
 case 244:
 case 245:
 case 165:
 case 178:
 case 179:
 case 49:
 case 50:
 case 168:
 case 169:
 case 175:
 case 170:
 case 171:
 case 172:
 case 97:
 case 76:
 case 32:
 case 173:
 case 35:
 case 80:
 case 81:
 case 79:
  return -1;

 case 176:
 case 177:
 case 7:
 case 155:
 case 8:
 case 157:
 case 125:
 case 126:
 case 92:
 case 93:
 case 129:
 case 130:
 case 131:
 case 94:
 case 91:
  return 1;

 case 74:
 case 60:
 case 69:
 case 70:
 case 4:
  return 1024;

 case 31:
 case 42:
 case 72:
  return 32;

 case 87:
 case 26:
 case 33:
  return 2147483647;

 case 34:
 case 1:
  return 47839;

 case 38:
 case 36:
  return 99;

 case 43:
 case 37:
  return 2048;

 case 0:
  return 2097152;

 case 3:
  return 65536;

 case 28:
  return 32768;

 case 44:
  return 32767;

 case 75:
  return 16384;

 case 39:
  return 1e3;

 case 89:
  return 700;

 case 71:
  return 256;

 case 40:
  return 255;

 case 2:
  return 100;

 case 180:
  return 64;

 case 25:
  return 20;

 case 5:
  return 16;

 case 6:
  return 6;

 case 73:
  return 4;

 case 84:
  {
   if (typeof navigator === "object") return navigator["hardwareConcurrency"] || 1;
   return 1;
  }
 }
 setErrNo(28);
 return -1;
}

function _time(ptr) {
 var ret = Date.now() / 1e3 | 0;
 if (ptr) {
  HEAP32[ptr >> 2] = ret;
 }
 return ret;
}

function setFileTime(path, time) {
 path = UTF8ToString(path);
 try {
  FS.utime(path, time, time);
  return 0;
 } catch (e) {
  if (!(e instanceof FS.ErrnoError)) throw e + " : " + stackTrace();
  setErrNo(e.errno);
  return -1;
 }
}

function _utime(path, times) {
 var time;
 if (times) {
  time = HEAP32[times + 4 >> 2] * 1e3;
 } else {
  time = Date.now();
 }
 return setFileTime(path, time);
}

var FSNode = function(parent, name, mode, rdev) {
 if (!parent) {
  parent = this;
 }
 this.parent = parent;
 this.mount = parent.mount;
 this.mounted = null;
 this.id = FS.nextInode++;
 this.name = name;
 this.mode = mode;
 this.node_ops = {};
 this.stream_ops = {};
 this.rdev = rdev;
};

var readMode = 292 | 73;

var writeMode = 146;

Object.defineProperties(FSNode.prototype, {
 read: {
  get: function() {
   return (this.mode & readMode) === readMode;
  },
  set: function(val) {
   val ? this.mode |= readMode : this.mode &= ~readMode;
  }
 },
 write: {
  get: function() {
   return (this.mode & writeMode) === writeMode;
  },
  set: function(val) {
   val ? this.mode |= writeMode : this.mode &= ~writeMode;
  }
 },
 isFolder: {
  get: function() {
   return FS.isDir(this.mode);
  }
 },
 isDevice: {
  get: function() {
   return FS.isChrdev(this.mode);
  }
 }
});

FS.FSNode = FSNode;

FS.staticInit();

function intArrayFromString(stringy, dontAddNull, length) {
 var len = length > 0 ? length : lengthBytesUTF8(stringy) + 1;
 var u8array = new Array(len);
 var numBytesWritten = stringToUTF8Array(stringy, u8array, 0, u8array.length);
 if (dontAddNull) u8array.length = numBytesWritten;
 return u8array;
}

var asmLibraryArg = {
 "__clock_gettime": ___clock_gettime,
 "__cxa_atexit": ___cxa_atexit,
 "__localtime_r": ___localtime_r,
 "__sys_access": ___sys_access,
 "__sys_chmod": ___sys_chmod,
 "__sys_chown32": ___sys_chown32,
 "__sys_fchmod": ___sys_fchmod,
 "__sys_fchown32": ___sys_fchown32,
 "__sys_fcntl64": ___sys_fcntl64,
 "__sys_fstat64": ___sys_fstat64,
 "__sys_ftruncate64": ___sys_ftruncate64,
 "__sys_getcwd": ___sys_getcwd,
 "__sys_geteuid32": ___sys_geteuid32,
 "__sys_getpid": ___sys_getpid,
 "__sys_ioctl": ___sys_ioctl,
 "__sys_lstat64": ___sys_lstat64,
 "__sys_mkdir": ___sys_mkdir,
 "__sys_mmap2": ___sys_mmap2,
 "__sys_mprotect": ___sys_mprotect,
 "__sys_munmap": ___sys_munmap,
 "__sys_open": ___sys_open,
 "__sys_readlink": ___sys_readlink,
 "__sys_rmdir": ___sys_rmdir,
 "__sys_stat64": ___sys_stat64,
 "__sys_unlink": ___sys_unlink,
 "abort": _abort,
 "emscripten_get_now": _emscripten_get_now,
 "emscripten_memcpy_big": _emscripten_memcpy_big,
 "emscripten_resize_heap": _emscripten_resize_heap,
 "emscripten_thread_sleep": _emscripten_thread_sleep,
 "environ_get": _environ_get,
 "environ_sizes_get": _environ_sizes_get,
 "exit": _exit,
 "fd_close": _fd_close,
 "fd_fdstat_get": _fd_fdstat_get,
 "fd_read": _fd_read,
 "fd_seek": _fd_seek,
 "fd_sync": _fd_sync,
 "fd_write": _fd_write,
 "getentropy": _getentropy,
 "gettimeofday": _gettimeofday,
 "setTempRet0": _setTempRet0,
 "strftime": _strftime,
 "strftime_l": _strftime_l,
 "sysconf": _sysconf,
 "time": _time,
 "utime": _utime
};

var asm = createWasm();

var ___wasm_call_ctors = Module["___wasm_call_ctors"] = createExportWrapper("__wasm_call_ctors", asm);

var ___errno_location = Module["___errno_location"] = createExportWrapper("__errno_location", asm);

var _memset = Module["_memset"] = createExportWrapper("memset", asm);

Module["_main"] = createExportWrapper("main", asm);

Module["_fflush"] = createExportWrapper("fflush", asm);

var _free = Module["_free"] = createExportWrapper("free", asm);

var _malloc = Module["_malloc"] = createExportWrapper("malloc", asm);

Module["_usleep"] = createExportWrapper("usleep", asm);

var __get_tzname = Module["__get_tzname"] = createExportWrapper("_get_tzname", asm);

var __get_daylight = Module["__get_daylight"] = createExportWrapper("_get_daylight", asm);

var __get_timezone = Module["__get_timezone"] = createExportWrapper("_get_timezone", asm);

Module["_emscripten_main_thread_process_queued_calls"] = createExportWrapper("emscripten_main_thread_process_queued_calls", asm);

var _emscripten_stack_get_end = Module["_emscripten_stack_get_end"] = asm["emscripten_stack_get_end"];

var stackSave = Module["stackSave"] = createExportWrapper("stackSave", asm);

var stackRestore = Module["stackRestore"] = createExportWrapper("stackRestore", asm);

var stackAlloc = Module["stackAlloc"] = createExportWrapper("stackAlloc", asm);

var _emscripten_stack_init = Module["_emscripten_stack_init"] = asm["emscripten_stack_init"];

Module["_emscripten_stack_get_free"] = asm["emscripten_stack_get_free"];

var _memalign = Module["_memalign"] = createExportWrapper("memalign", asm);

Module["dynCall_viijii"] = createExportWrapper("dynCall_viijii", asm);

Module["dynCall_viiij"] = createExportWrapper("dynCall_viiij", asm);

Module["dynCall_iiiij"] = createExportWrapper("dynCall_iiiij", asm);

Module["dynCall_iij"] = createExportWrapper("dynCall_iij", asm);

Module["dynCall_iijii"] = createExportWrapper("dynCall_iijii", asm);

Module["dynCall_iiji"] = createExportWrapper("dynCall_iiji", asm);

Module["dynCall_iiiiiij"] = createExportWrapper("dynCall_iiiiiij", asm);

Module["dynCall_viiiijii"] = createExportWrapper("dynCall_viiiijii", asm);

Module["dynCall_viiji"] = createExportWrapper("dynCall_viiji", asm);

Module["dynCall_viij"] = createExportWrapper("dynCall_viij", asm);

Module["dynCall_viji"] = createExportWrapper("dynCall_viji", asm);

Module["dynCall_iiij"] = createExportWrapper("dynCall_iiij", asm);

Module["dynCall_viijdi"] = createExportWrapper("dynCall_viijdi", asm);

Module["dynCall_viijdii"] = createExportWrapper("dynCall_viijdii", asm);

Module["dynCall_iijijii"] = createExportWrapper("dynCall_iijijii", asm);

Module["dynCall_viijiiii"] = createExportWrapper("dynCall_viijiiii", asm);

Module["dynCall_viijiiiji"] = createExportWrapper("dynCall_viijiiiji", asm);

Module["dynCall_viijiii"] = createExportWrapper("dynCall_viijiii", asm);

Module["dynCall_viijiiijiii"] = createExportWrapper("dynCall_viijiiijiii", asm);

Module["dynCall_jiji"] = createExportWrapper("dynCall_jiji", asm);

Module["dynCall_iiiiij"] = createExportWrapper("dynCall_iiiiij", asm);

Module["dynCall_iiiiijj"] = createExportWrapper("dynCall_iiiiijj", asm);

Module["dynCall_iiiiiijj"] = createExportWrapper("dynCall_iiiiiijj", asm);

if (!Object.getOwnPropertyDescriptor(Module, "intArrayFromString")) Module["intArrayFromString"] = function() {
 abort("'intArrayFromString' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "intArrayToString")) Module["intArrayToString"] = function() {
 abort("'intArrayToString' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

Module["ccall"] = ccall;

if (!Object.getOwnPropertyDescriptor(Module, "cwrap")) Module["cwrap"] = function() {
 abort("'cwrap' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "setValue")) Module["setValue"] = function() {
 abort("'setValue' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "getValue")) Module["getValue"] = function() {
 abort("'getValue' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "allocate")) Module["allocate"] = function() {
 abort("'allocate' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "UTF8ArrayToString")) Module["UTF8ArrayToString"] = function() {
 abort("'UTF8ArrayToString' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "UTF8ToString")) Module["UTF8ToString"] = function() {
 abort("'UTF8ToString' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "stringToUTF8Array")) Module["stringToUTF8Array"] = function() {
 abort("'stringToUTF8Array' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "stringToUTF8")) Module["stringToUTF8"] = function() {
 abort("'stringToUTF8' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "lengthBytesUTF8")) Module["lengthBytesUTF8"] = function() {
 abort("'lengthBytesUTF8' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "stackTrace")) Module["stackTrace"] = function() {
 abort("'stackTrace' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "addOnPreRun")) Module["addOnPreRun"] = function() {
 abort("'addOnPreRun' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "addOnInit")) Module["addOnInit"] = function() {
 abort("'addOnInit' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "addOnPreMain")) Module["addOnPreMain"] = function() {
 abort("'addOnPreMain' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "addOnExit")) Module["addOnExit"] = function() {
 abort("'addOnExit' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "addOnPostRun")) Module["addOnPostRun"] = function() {
 abort("'addOnPostRun' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "writeStringToMemory")) Module["writeStringToMemory"] = function() {
 abort("'writeStringToMemory' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "writeArrayToMemory")) Module["writeArrayToMemory"] = function() {
 abort("'writeArrayToMemory' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "writeAsciiToMemory")) Module["writeAsciiToMemory"] = function() {
 abort("'writeAsciiToMemory' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "addRunDependency")) Module["addRunDependency"] = function() {
 abort("'addRunDependency' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ). Alternatively, forcing filesystem support (-s FORCE_FILESYSTEM=1) can export this for you");
};

if (!Object.getOwnPropertyDescriptor(Module, "removeRunDependency")) Module["removeRunDependency"] = function() {
 abort("'removeRunDependency' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ). Alternatively, forcing filesystem support (-s FORCE_FILESYSTEM=1) can export this for you");
};

if (!Object.getOwnPropertyDescriptor(Module, "FS_createFolder")) Module["FS_createFolder"] = function() {
 abort("'FS_createFolder' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "FS_createPath")) Module["FS_createPath"] = function() {
 abort("'FS_createPath' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ). Alternatively, forcing filesystem support (-s FORCE_FILESYSTEM=1) can export this for you");
};

if (!Object.getOwnPropertyDescriptor(Module, "FS_createDataFile")) Module["FS_createDataFile"] = function() {
 abort("'FS_createDataFile' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ). Alternatively, forcing filesystem support (-s FORCE_FILESYSTEM=1) can export this for you");
};

if (!Object.getOwnPropertyDescriptor(Module, "FS_createPreloadedFile")) Module["FS_createPreloadedFile"] = function() {
 abort("'FS_createPreloadedFile' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ). Alternatively, forcing filesystem support (-s FORCE_FILESYSTEM=1) can export this for you");
};

if (!Object.getOwnPropertyDescriptor(Module, "FS_createLazyFile")) Module["FS_createLazyFile"] = function() {
 abort("'FS_createLazyFile' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ). Alternatively, forcing filesystem support (-s FORCE_FILESYSTEM=1) can export this for you");
};

if (!Object.getOwnPropertyDescriptor(Module, "FS_createLink")) Module["FS_createLink"] = function() {
 abort("'FS_createLink' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "FS_createDevice")) Module["FS_createDevice"] = function() {
 abort("'FS_createDevice' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ). Alternatively, forcing filesystem support (-s FORCE_FILESYSTEM=1) can export this for you");
};

if (!Object.getOwnPropertyDescriptor(Module, "FS_unlink")) Module["FS_unlink"] = function() {
 abort("'FS_unlink' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ). Alternatively, forcing filesystem support (-s FORCE_FILESYSTEM=1) can export this for you");
};

if (!Object.getOwnPropertyDescriptor(Module, "getLEB")) Module["getLEB"] = function() {
 abort("'getLEB' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "getFunctionTables")) Module["getFunctionTables"] = function() {
 abort("'getFunctionTables' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "alignFunctionTables")) Module["alignFunctionTables"] = function() {
 abort("'alignFunctionTables' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "registerFunctions")) Module["registerFunctions"] = function() {
 abort("'registerFunctions' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

Module["addFunction"] = addFunction;

if (!Object.getOwnPropertyDescriptor(Module, "removeFunction")) Module["removeFunction"] = function() {
 abort("'removeFunction' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "getFuncWrapper")) Module["getFuncWrapper"] = function() {
 abort("'getFuncWrapper' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "prettyPrint")) Module["prettyPrint"] = function() {
 abort("'prettyPrint' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "makeBigInt")) Module["makeBigInt"] = function() {
 abort("'makeBigInt' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "dynCall")) Module["dynCall"] = function() {
 abort("'dynCall' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "getCompilerSetting")) Module["getCompilerSetting"] = function() {
 abort("'getCompilerSetting' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "print")) Module["print"] = function() {
 abort("'print' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "printErr")) Module["printErr"] = function() {
 abort("'printErr' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "getTempRet0")) Module["getTempRet0"] = function() {
 abort("'getTempRet0' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "setTempRet0")) Module["setTempRet0"] = function() {
 abort("'setTempRet0' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

Module["callMain"] = callMain;

if (!Object.getOwnPropertyDescriptor(Module, "abort")) Module["abort"] = function() {
 abort("'abort' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "stringToNewUTF8")) Module["stringToNewUTF8"] = function() {
 abort("'stringToNewUTF8' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "setFileTime")) Module["setFileTime"] = function() {
 abort("'setFileTime' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "emscripten_realloc_buffer")) Module["emscripten_realloc_buffer"] = function() {
 abort("'emscripten_realloc_buffer' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "ENV")) Module["ENV"] = function() {
 abort("'ENV' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "ERRNO_CODES")) Module["ERRNO_CODES"] = function() {
 abort("'ERRNO_CODES' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "ERRNO_MESSAGES")) Module["ERRNO_MESSAGES"] = function() {
 abort("'ERRNO_MESSAGES' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "setErrNo")) Module["setErrNo"] = function() {
 abort("'setErrNo' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "DNS")) Module["DNS"] = function() {
 abort("'DNS' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "getHostByName")) Module["getHostByName"] = function() {
 abort("'getHostByName' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "GAI_ERRNO_MESSAGES")) Module["GAI_ERRNO_MESSAGES"] = function() {
 abort("'GAI_ERRNO_MESSAGES' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "Protocols")) Module["Protocols"] = function() {
 abort("'Protocols' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "Sockets")) Module["Sockets"] = function() {
 abort("'Sockets' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "getRandomDevice")) Module["getRandomDevice"] = function() {
 abort("'getRandomDevice' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "traverseStack")) Module["traverseStack"] = function() {
 abort("'traverseStack' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "UNWIND_CACHE")) Module["UNWIND_CACHE"] = function() {
 abort("'UNWIND_CACHE' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "withBuiltinMalloc")) Module["withBuiltinMalloc"] = function() {
 abort("'withBuiltinMalloc' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "readAsmConstArgsArray")) Module["readAsmConstArgsArray"] = function() {
 abort("'readAsmConstArgsArray' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "readAsmConstArgs")) Module["readAsmConstArgs"] = function() {
 abort("'readAsmConstArgs' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "mainThreadEM_ASM")) Module["mainThreadEM_ASM"] = function() {
 abort("'mainThreadEM_ASM' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "jstoi_q")) Module["jstoi_q"] = function() {
 abort("'jstoi_q' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "jstoi_s")) Module["jstoi_s"] = function() {
 abort("'jstoi_s' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "getExecutableName")) Module["getExecutableName"] = function() {
 abort("'getExecutableName' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "listenOnce")) Module["listenOnce"] = function() {
 abort("'listenOnce' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "autoResumeAudioContext")) Module["autoResumeAudioContext"] = function() {
 abort("'autoResumeAudioContext' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "dynCallLegacy")) Module["dynCallLegacy"] = function() {
 abort("'dynCallLegacy' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "getDynCaller")) Module["getDynCaller"] = function() {
 abort("'getDynCaller' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "dynCall")) Module["dynCall"] = function() {
 abort("'dynCall' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "callRuntimeCallbacks")) Module["callRuntimeCallbacks"] = function() {
 abort("'callRuntimeCallbacks' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "abortStackOverflow")) Module["abortStackOverflow"] = function() {
 abort("'abortStackOverflow' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "reallyNegative")) Module["reallyNegative"] = function() {
 abort("'reallyNegative' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "unSign")) Module["unSign"] = function() {
 abort("'unSign' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "reSign")) Module["reSign"] = function() {
 abort("'reSign' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "formatString")) Module["formatString"] = function() {
 abort("'formatString' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "PATH")) Module["PATH"] = function() {
 abort("'PATH' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "PATH_FS")) Module["PATH_FS"] = function() {
 abort("'PATH_FS' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "SYSCALLS")) Module["SYSCALLS"] = function() {
 abort("'SYSCALLS' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "syscallMmap2")) Module["syscallMmap2"] = function() {
 abort("'syscallMmap2' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "syscallMunmap")) Module["syscallMunmap"] = function() {
 abort("'syscallMunmap' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "JSEvents")) Module["JSEvents"] = function() {
 abort("'JSEvents' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "registerKeyEventCallback")) Module["registerKeyEventCallback"] = function() {
 abort("'registerKeyEventCallback' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "specialHTMLTargets")) Module["specialHTMLTargets"] = function() {
 abort("'specialHTMLTargets' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "maybeCStringToJsString")) Module["maybeCStringToJsString"] = function() {
 abort("'maybeCStringToJsString' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "findEventTarget")) Module["findEventTarget"] = function() {
 abort("'findEventTarget' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "findCanvasEventTarget")) Module["findCanvasEventTarget"] = function() {
 abort("'findCanvasEventTarget' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "getBoundingClientRect")) Module["getBoundingClientRect"] = function() {
 abort("'getBoundingClientRect' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "fillMouseEventData")) Module["fillMouseEventData"] = function() {
 abort("'fillMouseEventData' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "registerMouseEventCallback")) Module["registerMouseEventCallback"] = function() {
 abort("'registerMouseEventCallback' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "registerWheelEventCallback")) Module["registerWheelEventCallback"] = function() {
 abort("'registerWheelEventCallback' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "registerUiEventCallback")) Module["registerUiEventCallback"] = function() {
 abort("'registerUiEventCallback' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "registerFocusEventCallback")) Module["registerFocusEventCallback"] = function() {
 abort("'registerFocusEventCallback' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "fillDeviceOrientationEventData")) Module["fillDeviceOrientationEventData"] = function() {
 abort("'fillDeviceOrientationEventData' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "registerDeviceOrientationEventCallback")) Module["registerDeviceOrientationEventCallback"] = function() {
 abort("'registerDeviceOrientationEventCallback' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "fillDeviceMotionEventData")) Module["fillDeviceMotionEventData"] = function() {
 abort("'fillDeviceMotionEventData' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "registerDeviceMotionEventCallback")) Module["registerDeviceMotionEventCallback"] = function() {
 abort("'registerDeviceMotionEventCallback' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "screenOrientation")) Module["screenOrientation"] = function() {
 abort("'screenOrientation' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "fillOrientationChangeEventData")) Module["fillOrientationChangeEventData"] = function() {
 abort("'fillOrientationChangeEventData' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "registerOrientationChangeEventCallback")) Module["registerOrientationChangeEventCallback"] = function() {
 abort("'registerOrientationChangeEventCallback' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "fillFullscreenChangeEventData")) Module["fillFullscreenChangeEventData"] = function() {
 abort("'fillFullscreenChangeEventData' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "registerFullscreenChangeEventCallback")) Module["registerFullscreenChangeEventCallback"] = function() {
 abort("'registerFullscreenChangeEventCallback' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "registerRestoreOldStyle")) Module["registerRestoreOldStyle"] = function() {
 abort("'registerRestoreOldStyle' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "hideEverythingExceptGivenElement")) Module["hideEverythingExceptGivenElement"] = function() {
 abort("'hideEverythingExceptGivenElement' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "restoreHiddenElements")) Module["restoreHiddenElements"] = function() {
 abort("'restoreHiddenElements' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "setLetterbox")) Module["setLetterbox"] = function() {
 abort("'setLetterbox' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "currentFullscreenStrategy")) Module["currentFullscreenStrategy"] = function() {
 abort("'currentFullscreenStrategy' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "restoreOldWindowedStyle")) Module["restoreOldWindowedStyle"] = function() {
 abort("'restoreOldWindowedStyle' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "softFullscreenResizeWebGLRenderTarget")) Module["softFullscreenResizeWebGLRenderTarget"] = function() {
 abort("'softFullscreenResizeWebGLRenderTarget' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "doRequestFullscreen")) Module["doRequestFullscreen"] = function() {
 abort("'doRequestFullscreen' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "fillPointerlockChangeEventData")) Module["fillPointerlockChangeEventData"] = function() {
 abort("'fillPointerlockChangeEventData' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "registerPointerlockChangeEventCallback")) Module["registerPointerlockChangeEventCallback"] = function() {
 abort("'registerPointerlockChangeEventCallback' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "registerPointerlockErrorEventCallback")) Module["registerPointerlockErrorEventCallback"] = function() {
 abort("'registerPointerlockErrorEventCallback' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "requestPointerLock")) Module["requestPointerLock"] = function() {
 abort("'requestPointerLock' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "fillVisibilityChangeEventData")) Module["fillVisibilityChangeEventData"] = function() {
 abort("'fillVisibilityChangeEventData' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "registerVisibilityChangeEventCallback")) Module["registerVisibilityChangeEventCallback"] = function() {
 abort("'registerVisibilityChangeEventCallback' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "registerTouchEventCallback")) Module["registerTouchEventCallback"] = function() {
 abort("'registerTouchEventCallback' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "fillGamepadEventData")) Module["fillGamepadEventData"] = function() {
 abort("'fillGamepadEventData' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "registerGamepadEventCallback")) Module["registerGamepadEventCallback"] = function() {
 abort("'registerGamepadEventCallback' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "registerBeforeUnloadEventCallback")) Module["registerBeforeUnloadEventCallback"] = function() {
 abort("'registerBeforeUnloadEventCallback' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "fillBatteryEventData")) Module["fillBatteryEventData"] = function() {
 abort("'fillBatteryEventData' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "battery")) Module["battery"] = function() {
 abort("'battery' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "registerBatteryEventCallback")) Module["registerBatteryEventCallback"] = function() {
 abort("'registerBatteryEventCallback' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "setCanvasElementSize")) Module["setCanvasElementSize"] = function() {
 abort("'setCanvasElementSize' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "getCanvasElementSize")) Module["getCanvasElementSize"] = function() {
 abort("'getCanvasElementSize' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "polyfillSetImmediate")) Module["polyfillSetImmediate"] = function() {
 abort("'polyfillSetImmediate' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "demangle")) Module["demangle"] = function() {
 abort("'demangle' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "demangleAll")) Module["demangleAll"] = function() {
 abort("'demangleAll' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "jsStackTrace")) Module["jsStackTrace"] = function() {
 abort("'jsStackTrace' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "stackTrace")) Module["stackTrace"] = function() {
 abort("'stackTrace' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "getEnvStrings")) Module["getEnvStrings"] = function() {
 abort("'getEnvStrings' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "checkWasiClock")) Module["checkWasiClock"] = function() {
 abort("'checkWasiClock' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "writeI53ToI64")) Module["writeI53ToI64"] = function() {
 abort("'writeI53ToI64' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "writeI53ToI64Clamped")) Module["writeI53ToI64Clamped"] = function() {
 abort("'writeI53ToI64Clamped' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "writeI53ToI64Signaling")) Module["writeI53ToI64Signaling"] = function() {
 abort("'writeI53ToI64Signaling' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "writeI53ToU64Clamped")) Module["writeI53ToU64Clamped"] = function() {
 abort("'writeI53ToU64Clamped' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "writeI53ToU64Signaling")) Module["writeI53ToU64Signaling"] = function() {
 abort("'writeI53ToU64Signaling' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "readI53FromI64")) Module["readI53FromI64"] = function() {
 abort("'readI53FromI64' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "readI53FromU64")) Module["readI53FromU64"] = function() {
 abort("'readI53FromU64' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "convertI32PairToI53")) Module["convertI32PairToI53"] = function() {
 abort("'convertI32PairToI53' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "convertU32PairToI53")) Module["convertU32PairToI53"] = function() {
 abort("'convertU32PairToI53' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "uncaughtExceptionCount")) Module["uncaughtExceptionCount"] = function() {
 abort("'uncaughtExceptionCount' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "exceptionLast")) Module["exceptionLast"] = function() {
 abort("'exceptionLast' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "exceptionCaught")) Module["exceptionCaught"] = function() {
 abort("'exceptionCaught' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "ExceptionInfoAttrs")) Module["ExceptionInfoAttrs"] = function() {
 abort("'ExceptionInfoAttrs' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "ExceptionInfo")) Module["ExceptionInfo"] = function() {
 abort("'ExceptionInfo' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "CatchInfo")) Module["CatchInfo"] = function() {
 abort("'CatchInfo' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "exception_addRef")) Module["exception_addRef"] = function() {
 abort("'exception_addRef' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "exception_decRef")) Module["exception_decRef"] = function() {
 abort("'exception_decRef' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "Browser")) Module["Browser"] = function() {
 abort("'Browser' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "funcWrappers")) Module["funcWrappers"] = function() {
 abort("'funcWrappers' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "getFuncWrapper")) Module["getFuncWrapper"] = function() {
 abort("'getFuncWrapper' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "setMainLoop")) Module["setMainLoop"] = function() {
 abort("'setMainLoop' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

Module["FS"] = FS;

if (!Object.getOwnPropertyDescriptor(Module, "mmapAlloc")) Module["mmapAlloc"] = function() {
 abort("'mmapAlloc' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "MEMFS")) Module["MEMFS"] = function() {
 abort("'MEMFS' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "TTY")) Module["TTY"] = function() {
 abort("'TTY' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "PIPEFS")) Module["PIPEFS"] = function() {
 abort("'PIPEFS' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "SOCKFS")) Module["SOCKFS"] = function() {
 abort("'SOCKFS' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "tempFixedLengthArray")) Module["tempFixedLengthArray"] = function() {
 abort("'tempFixedLengthArray' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "miniTempWebGLFloatBuffers")) Module["miniTempWebGLFloatBuffers"] = function() {
 abort("'miniTempWebGLFloatBuffers' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "heapObjectForWebGLType")) Module["heapObjectForWebGLType"] = function() {
 abort("'heapObjectForWebGLType' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "heapAccessShiftForWebGLHeap")) Module["heapAccessShiftForWebGLHeap"] = function() {
 abort("'heapAccessShiftForWebGLHeap' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "GL")) Module["GL"] = function() {
 abort("'GL' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "emscriptenWebGLGet")) Module["emscriptenWebGLGet"] = function() {
 abort("'emscriptenWebGLGet' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "computeUnpackAlignedImageSize")) Module["computeUnpackAlignedImageSize"] = function() {
 abort("'computeUnpackAlignedImageSize' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "emscriptenWebGLGetTexPixelData")) Module["emscriptenWebGLGetTexPixelData"] = function() {
 abort("'emscriptenWebGLGetTexPixelData' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "emscriptenWebGLGetUniform")) Module["emscriptenWebGLGetUniform"] = function() {
 abort("'emscriptenWebGLGetUniform' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "emscriptenWebGLGetVertexAttrib")) Module["emscriptenWebGLGetVertexAttrib"] = function() {
 abort("'emscriptenWebGLGetVertexAttrib' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "writeGLArray")) Module["writeGLArray"] = function() {
 abort("'writeGLArray' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "AL")) Module["AL"] = function() {
 abort("'AL' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "SDL_unicode")) Module["SDL_unicode"] = function() {
 abort("'SDL_unicode' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "SDL_ttfContext")) Module["SDL_ttfContext"] = function() {
 abort("'SDL_ttfContext' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "SDL_audio")) Module["SDL_audio"] = function() {
 abort("'SDL_audio' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "SDL")) Module["SDL"] = function() {
 abort("'SDL' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "SDL_gfx")) Module["SDL_gfx"] = function() {
 abort("'SDL_gfx' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "GLUT")) Module["GLUT"] = function() {
 abort("'GLUT' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "EGL")) Module["EGL"] = function() {
 abort("'EGL' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "GLFW_Window")) Module["GLFW_Window"] = function() {
 abort("'GLFW_Window' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "GLFW")) Module["GLFW"] = function() {
 abort("'GLFW' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "GLEW")) Module["GLEW"] = function() {
 abort("'GLEW' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "IDBStore")) Module["IDBStore"] = function() {
 abort("'IDBStore' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "runAndAbortIfError")) Module["runAndAbortIfError"] = function() {
 abort("'runAndAbortIfError' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "WORKERFS")) Module["WORKERFS"] = function() {
 abort("'WORKERFS' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "warnOnce")) Module["warnOnce"] = function() {
 abort("'warnOnce' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "stackSave")) Module["stackSave"] = function() {
 abort("'stackSave' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "stackRestore")) Module["stackRestore"] = function() {
 abort("'stackRestore' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "stackAlloc")) Module["stackAlloc"] = function() {
 abort("'stackAlloc' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "AsciiToString")) Module["AsciiToString"] = function() {
 abort("'AsciiToString' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "stringToAscii")) Module["stringToAscii"] = function() {
 abort("'stringToAscii' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "UTF16ToString")) Module["UTF16ToString"] = function() {
 abort("'UTF16ToString' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "stringToUTF16")) Module["stringToUTF16"] = function() {
 abort("'stringToUTF16' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "lengthBytesUTF16")) Module["lengthBytesUTF16"] = function() {
 abort("'lengthBytesUTF16' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "UTF32ToString")) Module["UTF32ToString"] = function() {
 abort("'UTF32ToString' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "stringToUTF32")) Module["stringToUTF32"] = function() {
 abort("'stringToUTF32' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "lengthBytesUTF32")) Module["lengthBytesUTF32"] = function() {
 abort("'lengthBytesUTF32' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "allocateUTF8")) Module["allocateUTF8"] = function() {
 abort("'allocateUTF8' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

if (!Object.getOwnPropertyDescriptor(Module, "allocateUTF8OnStack")) Module["allocateUTF8OnStack"] = function() {
 abort("'allocateUTF8OnStack' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
};

Module["writeStackCookie"] = writeStackCookie;

Module["checkStackCookie"] = checkStackCookie;

if (!Object.getOwnPropertyDescriptor(Module, "ALLOC_NORMAL")) Object.defineProperty(Module, "ALLOC_NORMAL", {
 configurable: true,
 get: function() {
  abort("'ALLOC_NORMAL' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
 }
});

if (!Object.getOwnPropertyDescriptor(Module, "ALLOC_STACK")) Object.defineProperty(Module, "ALLOC_STACK", {
 configurable: true,
 get: function() {
  abort("'ALLOC_STACK' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");
 }
});

var calledRun;

function ExitStatus(status) {
 this.name = "ExitStatus";
 this.message = "Program terminated with exit(" + status + ")";
 this.status = status;
}

dependenciesFulfilled = function runCaller() {
 if (!calledRun) run();
 if (!calledRun) dependenciesFulfilled = runCaller;
};

function callMain(args) {
 assert(runDependencies == 0, 'cannot call main when async dependencies remain! (listen on Module["onRuntimeInitialized"])');
 assert(__ATPRERUN__.length == 0, "cannot call main when preRun functions remain to be called");
 var entryFunction = Module["_main"];
 args = args || [];
 var argc = args.length + 1;
 var argv = stackAlloc((argc + 1) * 4);
 HEAP32[argv >> 2] = allocateUTF8OnStack(thisProgram);
 for (var i = 1; i < argc; i++) {
  HEAP32[(argv >> 2) + i] = allocateUTF8OnStack(args[i - 1]);
 }
 HEAP32[(argv >> 2) + argc] = 0;
 try {
  var ret = entryFunction(argc, argv);
  exit(ret, true);
 } catch (e) {
  if (e instanceof ExitStatus) {
   return;
  } else if (e == "unwind") {
   noExitRuntime = true;
   return;
  } else {
   var toLog = e;
   if (e && typeof e === "object" && e.stack) {
    toLog = [ e, e.stack ];
   }
   err("exception thrown: " + toLog);
   quit_(1, e);
  }
 } finally {
 }
}

function run(args) {
 args = args || arguments_;
 if (runDependencies > 0) {
  return;
 }
 _emscripten_stack_init();
 writeStackCookie();
 preRun();
 if (runDependencies > 0) return;
 function doRun() {
  if (calledRun) return;
  calledRun = true;
  Module["calledRun"] = true;
  if (ABORT) return;
  initRuntime();
  preMain();
  readyPromiseResolve(Module);
  if (Module["onRuntimeInitialized"]) Module["onRuntimeInitialized"]();
  if (shouldRunNow) callMain(args);
  postRun();
 }
 if (Module["setStatus"]) {
  Module["setStatus"]("Running...");
  setTimeout(function() {
   setTimeout(function() {
    Module["setStatus"]("");
   }, 1);
   doRun();
  }, 1);
 } else {
  doRun();
 }
 checkStackCookie();
}

Module["run"] = run;

function checkUnflushedContent() {
 var oldOut = out;
 var oldErr = err;
 var has = false;
 out = err = function(x) {
  has = true;
 };
 try {
  var flush = Module["_fflush"];
  if (flush) flush(0);
  [ "stdout", "stderr" ].forEach(function(name) {
   var info = FS.analyzePath("/dev/" + name);
   if (!info) return;
   var stream = info.object;
   var rdev = stream.rdev;
   var tty = TTY.ttys[rdev];
   if (tty && tty.output && tty.output.length) {
    has = true;
   }
  });
 } catch (e) {}
 out = oldOut;
 err = oldErr;
 if (has) {
  warnOnce("stdio streams had content in them that was not flushed. you should set EXIT_RUNTIME to 1 (see the FAQ), or make sure to emit a newline when you printf etc.");
 }
}

function exit(status, implicit) {
 checkUnflushedContent();
 if (implicit && noExitRuntime && status === 0) {
  return;
 }
 if (noExitRuntime) {
  if (!implicit) {
   var msg = "program exited (with status: " + status + "), but EXIT_RUNTIME is not set, so halting execution but not exiting the runtime or preventing further async execution (build with EXIT_RUNTIME=1, if you want a true shutdown)";
   readyPromiseReject(msg);
   err(msg);
  }
 } else {
  exitRuntime();
  if (Module["onExit"]) Module["onExit"](status);
  ABORT = true;
 }
 quit_(status, new ExitStatus(status));
}

if (Module["preInit"]) {
 if (typeof Module["preInit"] == "function") Module["preInit"] = [ Module["preInit"] ];
 while (Module["preInit"].length > 0) {
  Module["preInit"].pop()();
 }
}

var shouldRunNow = true;

if (Module["noInitialRun"]) shouldRunNow = false;

noExitRuntime = true;

run();


  return trace_to_text_wasm
}
);
})();
module.exports = trace_to_text_wasm;
});

var immer_1 = createCommonjsModule(function (module, exports) {

Object.defineProperty(exports, '__esModule', { value: true });

var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) {
  return typeof obj;
} : function (obj) {
  return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
};











var classCallCheck = function (instance, Constructor) {
  if (!(instance instanceof Constructor)) {
    throw new TypeError("Cannot call a class as a function");
  }
};

var createClass = function () {
  function defineProperties(target, props) {
    for (var i = 0; i < props.length; i++) {
      var descriptor = props[i];
      descriptor.enumerable = descriptor.enumerable || false;
      descriptor.configurable = true;
      if ("value" in descriptor) descriptor.writable = true;
      Object.defineProperty(target, descriptor.key, descriptor);
    }
  }

  return function (Constructor, protoProps, staticProps) {
    if (protoProps) defineProperties(Constructor.prototype, protoProps);
    if (staticProps) defineProperties(Constructor, staticProps);
    return Constructor;
  };
}();





var defineProperty = function (obj, key, value) {
  if (key in obj) {
    Object.defineProperty(obj, key, {
      value: value,
      enumerable: true,
      configurable: true,
      writable: true
    });
  } else {
    obj[key] = value;
  }

  return obj;
};

var NOTHING = typeof Symbol !== "undefined" ? Symbol("immer-nothing") : defineProperty({}, "immer-nothing", true);

var DRAFTABLE = typeof Symbol !== "undefined" ? Symbol("immer-draftable") : "__$immer_draftable";

var DRAFT_STATE = typeof Symbol !== "undefined" ? Symbol("immer-state") : "__$immer_state";

function isDraft(value) {
    return !!value && !!value[DRAFT_STATE];
}

function isDraftable(value) {
    if (!value || (typeof value === "undefined" ? "undefined" : _typeof(value)) !== "object") return false;
    if (Array.isArray(value)) return true;
    var proto = Object.getPrototypeOf(value);
    if (!proto || proto === Object.prototype) return true;
    return !!value[DRAFTABLE] || !!value.constructor[DRAFTABLE];
}

function original(value) {
    if (value && value[DRAFT_STATE]) {
        return value[DRAFT_STATE].base;
    }
    // otherwise return undefined
}

var assign = Object.assign || function assign(target, value) {
    for (var key in value) {
        if (has(value, key)) {
            target[key] = value[key];
        }
    }
    return target;
};

var ownKeys = typeof Reflect !== "undefined" && Reflect.ownKeys ? Reflect.ownKeys : typeof Object.getOwnPropertySymbols !== "undefined" ? function (obj) {
    return Object.getOwnPropertyNames(obj).concat(Object.getOwnPropertySymbols(obj));
} : Object.getOwnPropertyNames;

function shallowCopy(base) {
    var invokeGetters = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;

    if (Array.isArray(base)) return base.slice();
    var clone = Object.create(Object.getPrototypeOf(base));
    ownKeys(base).forEach(function (key) {
        if (key === DRAFT_STATE) {
            return; // Never copy over draft state.
        }
        var desc = Object.getOwnPropertyDescriptor(base, key);
        if (desc.get) {
            if (!invokeGetters) {
                throw new Error("Immer drafts cannot have computed properties");
            }
            desc.value = desc.get.call(base);
        }
        if (desc.enumerable) {
            clone[key] = desc.value;
        } else {
            Object.defineProperty(clone, key, {
                value: desc.value,
                writable: true,
                configurable: true
            });
        }
    });
    return clone;
}

function each(value, cb) {
    if (Array.isArray(value)) {
        for (var i = 0; i < value.length; i++) {
            cb(i, value[i], value);
        }
    } else {
        ownKeys(value).forEach(function (key) {
            return cb(key, value[key], value);
        });
    }
}

function isEnumerable(base, prop) {
    return Object.getOwnPropertyDescriptor(base, prop).enumerable;
}

function has(thing, prop) {
    return Object.prototype.hasOwnProperty.call(thing, prop);
}

function is(x, y) {
    // From: https://github.com/facebook/fbjs/blob/c69904a511b900266935168223063dd8772dfc40/packages/fbjs/src/core/shallowEqual.js
    if (x === y) {
        return x !== 0 || 1 / x === 1 / y;
    } else {
        return x !== x && y !== y;
    }
}

// @ts-check

var descriptors = {};

// For nested produce calls:
var scopes = [];
var currentScope = function currentScope() {
    return scopes[scopes.length - 1];
};

function willFinalize(result, baseDraft, needPatches) {
    var scope = currentScope();
    scope.forEach(function (state) {
        return state.finalizing = true;
    });
    if (result === undefined || result === baseDraft) {
        if (needPatches) markChangesRecursively(baseDraft);
        // This is faster when we don't care about which attributes changed.
        markChangesSweep(scope);
    }
}

function createDraft(base, parent) {
    var isArray = Array.isArray(base);
    var draft = clonePotentialDraft(base);
    each(draft, function (prop) {
        proxyProperty(draft, prop, isArray || isEnumerable(base, prop));
    });

    // See "proxy.js" for property documentation.
    var state = {
        scope: parent ? parent.scope : currentScope(),
        modified: false,
        finalizing: false, // es5 only
        finalized: false,
        assigned: {},
        parent: parent,
        base: base,
        draft: draft,
        copy: null,
        revoke: revoke,
        revoked: false // es5 only
    };

    createHiddenProperty(draft, DRAFT_STATE, state);
    state.scope.push(state);
    return draft;
}

function revoke() {
    this.revoked = true;
}

function source(state) {
    return state.copy || state.base;
}

function _get(state, prop) {
    assertUnrevoked(state);
    var value = source(state)[prop];
    // Drafts are only created for proxyable values that exist in the base state.
    if (!state.finalizing && value === state.base[prop] && isDraftable(value)) {
        prepareCopy(state);
        return state.copy[prop] = createDraft(value, state);
    }
    return value;
}

function _set(state, prop, value) {
    assertUnrevoked(state);
    state.assigned[prop] = true;
    if (!state.modified) {
        if (is(source(state)[prop], value)) return;
        markChanged(state);
        prepareCopy(state);
    }
    state.copy[prop] = value;
}

function markChanged(state) {
    if (!state.modified) {
        state.modified = true;
        if (state.parent) markChanged(state.parent);
    }
}

function prepareCopy(state) {
    if (!state.copy) state.copy = clonePotentialDraft(state.base);
}

function clonePotentialDraft(base) {
    var state = base && base[DRAFT_STATE];
    if (state) {
        state.finalizing = true;
        var draft = shallowCopy(state.draft, true);
        state.finalizing = false;
        return draft;
    }
    return shallowCopy(base);
}

function proxyProperty(draft, prop, enumerable) {
    var desc = descriptors[prop];
    if (desc) {
        desc.enumerable = enumerable;
    } else {
        descriptors[prop] = desc = {
            configurable: true,
            enumerable: enumerable,
            get: function get$$1() {
                return _get(this[DRAFT_STATE], prop);
            },
            set: function set$$1(value) {
                _set(this[DRAFT_STATE], prop, value);
            }
        };
    }
    Object.defineProperty(draft, prop, desc);
}

function assertUnrevoked(state) {
    if (state.revoked === true) throw new Error("Cannot use a proxy that has been revoked. Did you pass an object from inside an immer function to an async process? " + JSON.stringify(source(state)));
}

// This looks expensive, but only proxies are visited, and only objects without known changes are scanned.
function markChangesSweep(scope) {
    // The natural order of drafts in the `scope` array is based on when they
    // were accessed. By processing drafts in reverse natural order, we have a
    // better chance of processing leaf nodes first. When a leaf node is known to
    // have changed, we can avoid any traversal of its ancestor nodes.
    for (var i = scope.length - 1; i >= 0; i--) {
        var state = scope[i];
        if (state.modified === false) {
            if (Array.isArray(state.base)) {
                if (hasArrayChanges(state)) markChanged(state);
            } else if (hasObjectChanges(state)) markChanged(state);
        }
    }
}

function markChangesRecursively(object) {
    if (!object || (typeof object === "undefined" ? "undefined" : _typeof(object)) !== "object") return;
    var state = object[DRAFT_STATE];
    if (!state) return;
    var base = state.base,
        draft = state.draft,
        assigned = state.assigned;

    if (!Array.isArray(object)) {
        // Look for added keys.
        Object.keys(draft).forEach(function (key) {
            // The `undefined` check is a fast path for pre-existing keys.
            if (base[key] === undefined && !has(base, key)) {
                assigned[key] = true;
                markChanged(state);
            } else if (!assigned[key]) {
                // Only untouched properties trigger recursion.
                markChangesRecursively(draft[key]);
            }
        });
        // Look for removed keys.
        Object.keys(base).forEach(function (key) {
            // The `undefined` check is a fast path for pre-existing keys.
            if (draft[key] === undefined && !has(draft, key)) {
                assigned[key] = false;
                markChanged(state);
            }
        });
    } else if (hasArrayChanges(state)) {
        markChanged(state);
        assigned.length = true;
        if (draft.length < base.length) {
            for (var i = draft.length; i < base.length; i++) {
                assigned[i] = false;
            }
        } else {
            for (var _i = base.length; _i < draft.length; _i++) {
                assigned[_i] = true;
            }
        }
        for (var _i2 = 0; _i2 < draft.length; _i2++) {
            // Only untouched indices trigger recursion.
            if (assigned[_i2] === undefined) markChangesRecursively(draft[_i2]);
        }
    }
}

function hasObjectChanges(state) {
    var base = state.base,
        draft = state.draft;

    // Search for added keys. Start at the back, because non-numeric keys
    // are ordered by time of definition on the object.

    var keys = Object.keys(draft);
    for (var i = keys.length - 1; i >= 0; i--) {
        // The `undefined` check is a fast path for pre-existing keys.
        if (base[keys[i]] === undefined && !has(base, keys[i])) {
            return true;
        }
    }

    // Since no keys have been added, we can compare lengths to know if an
    // object has been deleted.
    return keys.length !== Object.keys(base).length;
}

function hasArrayChanges(state) {
    var draft = state.draft;

    if (draft.length !== state.base.length) return true;
    // See #116
    // If we first shorten the length, our array interceptors will be removed.
    // If after that new items are added, result in the same original length,
    // those last items will have no intercepting property.
    // So if there is no own descriptor on the last position, we know that items were removed and added
    // N.B.: splice, unshift, etc only shift values around, but not prop descriptors, so we only have to check
    // the last one
    var descriptor = Object.getOwnPropertyDescriptor(draft, draft.length - 1);
    // descriptor can be null, but only for newly created sparse arrays, eg. new Array(10)
    if (descriptor && !descriptor.get) return true;
    // For all other cases, we don't have to compare, as they would have been picked up by the index setters
    return false;
}

function createHiddenProperty(target, prop, value) {
    Object.defineProperty(target, prop, {
        value: value,
        enumerable: false,
        writable: true
    });
}



var legacyProxy = Object.freeze({
	scopes: scopes,
	currentScope: currentScope,
	willFinalize: willFinalize,
	createDraft: createDraft
});

// @ts-check

// For nested produce calls:
var scopes$1 = [];
var currentScope$1 = function currentScope() {
    return scopes$1[scopes$1.length - 1];
};

// Do nothing before being finalized.
function willFinalize$1() {}

function createDraft$1(base, parent) {
    var state = {
        // Track which produce call this is associated with.
        scope: parent ? parent.scope : currentScope$1(),
        // True for both shallow and deep changes.
        modified: false,
        // Used during finalization.
        finalized: false,
        // Track which properties have been assigned (true) or deleted (false).
        assigned: {},
        // The parent draft state.
        parent: parent,
        // The base state.
        base: base,
        // The base proxy.
        draft: null,
        // Any property proxies.
        drafts: {},
        // The base copy with any updated values.
        copy: null,
        // Called by the `produce` function.
        revoke: null
    };

    var _ref = Array.isArray(base) ? Proxy.revocable([state], arrayTraps) : Proxy.revocable(state, objectTraps),
        revoke = _ref.revoke,
        proxy = _ref.proxy;

    state.draft = proxy;
    state.revoke = revoke;

    state.scope.push(state);
    return proxy;
}

var objectTraps = {
    get: get$1,
    has: function has$$1(target, prop) {
        return prop in source$1(target);
    },
    ownKeys: function ownKeys$$1(target) {
        return Reflect.ownKeys(source$1(target));
    },

    set: set$1,
    deleteProperty: deleteProperty,
    getOwnPropertyDescriptor: getOwnPropertyDescriptor,
    defineProperty: function defineProperty() {
        throw new Error("Object.defineProperty() cannot be used on an Immer draft"); // prettier-ignore
    },
    getPrototypeOf: function getPrototypeOf(target) {
        return Object.getPrototypeOf(target.base);
    },
    setPrototypeOf: function setPrototypeOf() {
        throw new Error("Object.setPrototypeOf() cannot be used on an Immer draft"); // prettier-ignore
    }
};

var arrayTraps = {};
each(objectTraps, function (key, fn) {
    arrayTraps[key] = function () {
        arguments[0] = arguments[0][0];
        return fn.apply(this, arguments);
    };
});
arrayTraps.deleteProperty = function (state, prop) {
    if (isNaN(parseInt(prop))) {
        throw new Error("Immer only supports deleting array indices"); // prettier-ignore
    }
    return objectTraps.deleteProperty.call(this, state[0], prop);
};
arrayTraps.set = function (state, prop, value) {
    if (prop !== "length" && isNaN(parseInt(prop))) {
        throw new Error("Immer only supports setting array indices and the 'length' property"); // prettier-ignore
    }
    return objectTraps.set.call(this, state[0], prop, value);
};

function source$1(state) {
    return state.copy || state.base;
}

function get$1(state, prop) {
    if (prop === DRAFT_STATE) return state;
    var drafts = state.drafts;

    // Check for existing draft in unmodified state.

    if (!state.modified && has(drafts, prop)) {
        return drafts[prop];
    }

    var value = source$1(state)[prop];
    if (state.finalized || !isDraftable(value)) return value;

    // Check for existing draft in modified state.
    if (state.modified) {
        // Assigned values are never drafted. This catches any drafts we created, too.
        if (value !== state.base[prop]) return value;
        // Store drafts on the copy (when one exists).
        drafts = state.copy;
    }

    return drafts[prop] = createDraft$1(value, state);
}

function set$1(state, prop, value) {
    if (!state.modified) {
        // Optimize based on value's truthiness. Truthy values are guaranteed to
        // never be undefined, so we can avoid the `in` operator. Lastly, truthy
        // values may be drafts, but falsy values are never drafts.
        var isUnchanged = value ? is(state.base[prop], value) || value === state.drafts[prop] : is(state.base[prop], value) && prop in state.base;
        if (isUnchanged) return true;
        markChanged$1(state);
    }
    state.assigned[prop] = true;
    state.copy[prop] = value;
    return true;
}

function deleteProperty(state, prop) {
    // The `undefined` check is a fast path for pre-existing keys.
    if (state.base[prop] !== undefined || prop in state.base) {
        state.assigned[prop] = false;
        markChanged$1(state);
    }
    if (state.copy) delete state.copy[prop];
    return true;
}

function getOwnPropertyDescriptor(state, prop) {
    var owner = source$1(state);
    var desc = Reflect.getOwnPropertyDescriptor(owner, prop);
    if (desc) {
        desc.writable = true;
        desc.configurable = !Array.isArray(owner) || prop !== "length";
    }
    return desc;
}

function markChanged$1(state) {
    if (!state.modified) {
        state.modified = true;
        state.copy = assign(shallowCopy(state.base), state.drafts);
        state.drafts = null;
        if (state.parent) markChanged$1(state.parent);
    }
}

var modernProxy = Object.freeze({
	scopes: scopes$1,
	currentScope: currentScope$1,
	willFinalize: willFinalize$1,
	createDraft: createDraft$1
});

function generatePatches(state, basePath, patches, inversePatches) {
    Array.isArray(state.base) ? generateArrayPatches(state, basePath, patches, inversePatches) : generateObjectPatches(state, basePath, patches, inversePatches);
}

function generateArrayPatches(state, basePath, patches, inversePatches) {
    var base = state.base,
        copy = state.copy,
        assigned = state.assigned;

    var minLength = Math.min(base.length, copy.length);

    // Look for replaced indices.
    for (var i = 0; i < minLength; i++) {
        if (assigned[i] && base[i] !== copy[i]) {
            var path = basePath.concat(i);
            patches.push({ op: "replace", path: path, value: copy[i] });
            inversePatches.push({ op: "replace", path: path, value: base[i] });
        }
    }

    // Did the array expand?
    if (minLength < copy.length) {
        for (var _i = minLength; _i < copy.length; _i++) {
            patches.push({
                op: "add",
                path: basePath.concat(_i),
                value: copy[_i]
            });
        }
        inversePatches.push({
            op: "replace",
            path: basePath.concat("length"),
            value: base.length
        });
    }

    // ...or did it shrink?
    else if (minLength < base.length) {
            patches.push({
                op: "replace",
                path: basePath.concat("length"),
                value: copy.length
            });
            for (var _i2 = minLength; _i2 < base.length; _i2++) {
                inversePatches.push({
                    op: "add",
                    path: basePath.concat(_i2),
                    value: base[_i2]
                });
            }
        }
}

function generateObjectPatches(state, basePath, patches, inversePatches) {
    var base = state.base,
        copy = state.copy;

    each(state.assigned, function (key, assignedValue) {
        var origValue = base[key];
        var value = copy[key];
        var op = !assignedValue ? "remove" : key in base ? "replace" : "add";
        if (origValue === value && op === "replace") return;
        var path = basePath.concat(key);
        patches.push(op === "remove" ? { op: op, path: path } : { op: op, path: path, value: value });
        inversePatches.push(op === "add" ? { op: "remove", path: path } : op === "remove" ? { op: "add", path: path, value: origValue } : { op: "replace", path: path, value: origValue });
    });
}

function applyPatches(draft, patches) {
    for (var i = 0; i < patches.length; i++) {
        var patch = patches[i];
        var path = patch.path;

        if (path.length === 0 && patch.op === "replace") {
            draft = patch.value;
        } else {
            var base = draft;
            for (var _i3 = 0; _i3 < path.length - 1; _i3++) {
                base = base[path[_i3]];
                if (!base || (typeof base === "undefined" ? "undefined" : _typeof(base)) !== "object") throw new Error("Cannot apply patch, path doesn't resolve: " + path.join("/")); // prettier-ignore
            }
            var key = path[path.length - 1];
            switch (patch.op) {
                case "replace":
                case "add":
                    // TODO: add support is not extensive, it does not support insertion or `-` atm!
                    base[key] = patch.value;
                    break;
                case "remove":
                    if (Array.isArray(base)) {
                        if (key !== base.length - 1) throw new Error("Only the last index of an array can be removed, index: " + key + ", length: " + base.length); // prettier-ignore
                        base.length -= 1;
                    } else {
                        delete base[key];
                    }
                    break;
                default:
                    throw new Error("Unsupported patch operation: " + patch.op);
            }
        }
    }
    return draft;
}

function verifyMinified() {}

var configDefaults = {
    useProxies: typeof Proxy !== "undefined" && typeof Reflect !== "undefined",
    autoFreeze: typeof process !== "undefined" ? process.env.NODE_ENV !== "production" : verifyMinified.name === "verifyMinified",
    onAssign: null,
    onDelete: null,
    onCopy: null
};

var Immer = function () {
    function Immer(config) {
        classCallCheck(this, Immer);

        assign(this, configDefaults, config);
        this.setUseProxies(this.useProxies);
        this.produce = this.produce.bind(this);
    }

    createClass(Immer, [{
        key: "produce",
        value: function produce(base, recipe, patchListener) {
            var _this = this;

            // curried invocation
            if (typeof base === "function" && typeof recipe !== "function") {
                var defaultBase = recipe;
                recipe = base;

                // prettier-ignore
                return function () {
                    for (var _len = arguments.length, args = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
                        args[_key - 1] = arguments[_key];
                    }

                    var base = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : defaultBase;
                    return _this.produce(base, function (draft) {
                        var _recipe;

                        return (_recipe = recipe).call.apply(_recipe, [draft, draft].concat(args));
                    });
                };
            }

            // prettier-ignore
            {
                if (typeof recipe !== "function") throw new Error("if first argument is not a function, the second argument to produce should be a function");
                if (patchListener !== undefined && typeof patchListener !== "function") throw new Error("the third argument of a producer should not be set or a function");
            }

            var result = void 0;
            // Only create proxies for plain objects/arrays.
            if (!isDraftable(base)) {
                result = recipe(base);
                if (result === undefined) return base;
            }
            // The given value must be proxied.
            else {
                    this.scopes.push([]);
                    var baseDraft = this.createDraft(base);
                    try {
                        result = recipe.call(baseDraft, baseDraft);
                        this.willFinalize(result, baseDraft, !!patchListener);

                        // Never generate patches when no listener exists.
                        var patches = patchListener && [],
                            inversePatches = patchListener && [];

                        // Finalize the modified draft...
                        if (result === undefined || result === baseDraft) {
                            result = this.finalize(baseDraft, [], patches, inversePatches);
                        }
                        // ...or use a replacement value.
                        else {
                                // Users must never modify the draft _and_ return something else.
                                if (baseDraft[DRAFT_STATE].modified) throw new Error("An immer producer returned a new value *and* modified its draft. Either return a new value *or* modify the draft."); // prettier-ignore

                                // Finalize the replacement in case it contains (or is) a subset of the draft.
                                if (isDraftable(result)) result = this.finalize(result);

                                if (patchListener) {
                                    patches.push({
                                        op: "replace",
                                        path: [],
                                        value: result
                                    });
                                    inversePatches.push({
                                        op: "replace",
                                        path: [],
                                        value: base
                                    });
                                }
                            }
                    } finally {
                        this.currentScope().forEach(function (state) {
                            return state.revoke();
                        });
                        this.scopes.pop();
                    }
                    patchListener && patchListener(patches, inversePatches);
                }
            // Normalize the result.
            return result === NOTHING ? undefined : result;
        }
    }, {
        key: "setAutoFreeze",
        value: function setAutoFreeze(value) {
            this.autoFreeze = value;
        }
    }, {
        key: "setUseProxies",
        value: function setUseProxies(value) {
            this.useProxies = value;
            assign(this, value ? modernProxy : legacyProxy);
        }
    }, {
        key: "applyPatches",
        value: function applyPatches$$1(base, patches) {
            // Mutate the base state when a draft is passed.
            if (isDraft(base)) {
                return applyPatches(base, patches);
            }
            // Otherwise, produce a copy of the base state.
            return this.produce(base, function (draft) {
                return applyPatches(draft, patches);
            });
        }
        /**
         * @internal
         * Finalize a draft, returning either the unmodified base state or a modified
         * copy of the base state.
         */

    }, {
        key: "finalize",
        value: function finalize(draft, path, patches, inversePatches) {
            var _this2 = this;

            var state = draft[DRAFT_STATE];
            if (!state) {
                if (Object.isFrozen(draft)) return draft;
                return this.finalizeTree(draft);
            }
            // Never finalize drafts owned by an outer scope.
            if (state.scope !== this.currentScope()) {
                return draft;
            }
            if (!state.modified) return state.base;
            if (!state.finalized) {
                state.finalized = true;
                this.finalizeTree(state.draft, path, patches, inversePatches);
                if (this.onDelete) {
                    // The `assigned` object is unreliable with ES5 drafts.
                    if (this.useProxies) {
                        var assigned = state.assigned;

                        for (var prop in assigned) {
                            if (!assigned[prop]) this.onDelete(state, prop);
                        }
                    } else {
                        var base = state.base,
                            copy = state.copy;

                        each(base, function (prop) {
                            if (!has(copy, prop)) _this2.onDelete(state, prop);
                        });
                    }
                }
                if (this.onCopy) this.onCopy(state);

                // Nested producers must never auto-freeze their result,
                // because it may contain drafts from parent producers.
                if (this.autoFreeze && this.scopes.length === 1) {
                    Object.freeze(state.copy);
                }

                if (patches) generatePatches(state, path, patches, inversePatches);
            }
            return state.copy;
        }
        /**
         * @internal
         * Finalize all drafts in the given state tree.
         */

    }, {
        key: "finalizeTree",
        value: function finalizeTree(root, path, patches, inversePatches) {
            var _this3 = this;

            var state = root[DRAFT_STATE];
            if (state) {
                if (!this.useProxies) {
                    state.finalizing = true;
                    state.copy = shallowCopy(state.draft, true);
                    state.finalizing = false;
                }
                root = state.copy;
            }

            var onAssign = this.onAssign;

            var finalizeProperty = function finalizeProperty(prop, value, parent) {
                if (value === parent) {
                    throw Error("Immer forbids circular references");
                }

                // The only possible draft (in the scope of a `finalizeTree` call) is the `root` object.
                var inDraft = !!state && parent === root;

                if (isDraft(value)) {
                    value =
                    // Patches are never generated for assigned properties.
                    patches && inDraft && !state.assigned[prop] ? _this3.finalize(value, path.concat(prop), patches, inversePatches) // prettier-ignore
                    : _this3.finalize(value);

                    // Preserve non-enumerable properties.
                    if (Array.isArray(parent) || isEnumerable(parent, prop)) {
                        parent[prop] = value;
                    } else {
                        Object.defineProperty(parent, prop, { value: value });
                    }

                    // Unchanged drafts are never passed to the `onAssign` hook.
                    if (inDraft && value === state.base[prop]) return;
                }
                // Unchanged draft properties are ignored.
                else if (inDraft && is(value, state.base[prop])) {
                        return;
                    }
                    // Search new objects for unfinalized drafts. Frozen objects should never contain drafts.
                    else if (isDraftable(value) && !Object.isFrozen(value)) {
                            each(value, finalizeProperty);
                        }

                if (inDraft && onAssign) {
                    onAssign(state, prop, value);
                }
            };

            each(root, finalizeProperty);
            return root;
        }
    }]);
    return Immer;
}();

var immer = new Immer();

/**
 * The `produce` function takes a value and a "recipe function" (whose
 * return value often depends on the base state). The recipe function is
 * free to mutate its first argument however it wants. All mutations are
 * only ever applied to a __copy__ of the base state.
 *
 * Pass only a function to create a "curried producer" which relieves you
 * from passing the recipe function every time.
 *
 * Only plain objects and arrays are made mutable. All other objects are
 * considered uncopyable.
 *
 * Note: This function is __bound__ to its `Immer` instance.
 *
 * @param {any} base - the initial state
 * @param {Function} producer - function that receives a proxy of the base state as first argument and which can be freely modified
 * @param {Function} patchListener - optional function that will be called with all the patches produced here
 * @returns {any} a new state, or the initial state if nothing was modified
 */
var produce = immer.produce;
/**
 * Pass true to automatically freeze all copies created by Immer.
 *
 * By default, auto-freezing is disabled in production.
 */
var setAutoFreeze = immer.setAutoFreeze.bind(immer);

/**
 * Pass true to use the ES2015 `Proxy` class when creating drafts, which is
 * always faster than using ES5 proxies.
 *
 * By default, feature detection is used, so calling this is rarely necessary.
 */
var setUseProxies = immer.setUseProxies.bind(immer);

/**
 * Apply an array of Immer patches to the first argument.
 *
 * This function is a producer, which means copy-on-write is in effect.
 */
var applyPatches$1 = immer.applyPatches.bind(immer);

exports.produce = produce;
exports['default'] = produce;
exports.setAutoFreeze = setAutoFreeze;
exports.setUseProxies = setUseProxies;
exports.applyPatches = applyPatches$1;
exports.Immer = Immer;
exports.original = original;
exports.isDraft = isDraft;
exports.isDraftable = isDraftable;
exports.nothing = NOTHING;
exports.immerable = DRAFTABLE;

});

var globals = createCommonjsModule(function (module, exports) {
// 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.
Object.defineProperty(exports, "__esModule", { value: true });
exports.globals = void 0;




/**
 * Global accessors for state/dispatch in the controller.
 */
class Globals {
    constructor() {
        this._runningControllers = false;
        this._queuedActions = new Array();
    }
    initialize(rootController, frontendProxy) {
        this._rootController = rootController;
        this._frontend = frontendProxy;
        this._state = state.createEmptyState();
    }
    dispatch(action) {
        this.dispatchMultiple([action]);
    }
    dispatchMultiple(actions) {
        this._queuedActions = this._queuedActions.concat(actions);
        // If we are in the middle of running the controllers, queue the actions
        // and run them at the end of the run, so the state is atomically updated
        // only at the end and all controllers see the same state.
        if (this._runningControllers)
            return;
        this.runControllers();
    }
    runControllers() {
        if (this._runningControllers)
            throw new Error('Re-entrant call detected');
        // Run controllers locally until all state machines reach quiescence.
        let runAgain = false;
        const patches = [];
        for (let iter = 0; runAgain || this._queuedActions.length > 0; iter++) {
            if (iter > 100)
                throw new Error('Controllers are stuck in a livelock');
            const actions = this._queuedActions;
            this._queuedActions = new Array();
            for (const action of actions) {
                const originalLength = patches.length;
                const morePatches = this.applyAction(action);
                patches.length += morePatches.length;
                for (let i = 0; i < morePatches.length; ++i) {
                    patches[i + originalLength] = morePatches[i];
                }
            }
            this._runningControllers = true;
            try {
                runAgain = logging.assertExists(this._rootController).invoke();
            }
            finally {
                this._runningControllers = false;
            }
        }
        logging.assertExists(this._frontend).send('patchState', [patches]);
    }
    // TODO: this needs to be cleaned up.
    publish(what, data, transferList) {
        logging.assertExists(this._frontend)
            .send(`publish${what}`, [data], transferList);
    }
    get state() {
        return logging.assertExists(this._state);
    }
    applyAction(action) {
        logging.assertExists(this._state);
        const patches = [];
        // 'produce' creates a immer proxy which wraps the current state turning
        // all imperative mutations of the state done in the callback into
        // immutable changes to the returned state.
        this._state = immer_1.produce(this.state, draft => {
            // tslint:disable-next-line no-any
            actions.StateActions[action.type](draft, action.args);
        }, (morePatches, _) => {
            const originalLength = patches.length;
            patches.length += morePatches.length;
            for (let i = 0; i < morePatches.length; ++i) {
                patches[i + originalLength] = morePatches[i];
            }
        });
        return patches;
    }
    resetForTesting() {
        this._state = undefined;
        this._rootController = undefined;
    }
}
exports.globals = new Globals();

});

var trace_converter = createCommonjsModule(function (module, exports) {
// 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.
Object.defineProperty(exports, "__esModule", { value: true });
exports.ConvertTraceToPprof = exports.ConvertTraceAndDownload = exports.ConvertTrace = void 0;







function ConvertTrace(trace, format, truncate) {
    const jobName = 'open_in_legacy';
    globals.globals.publish('ConversionJobStatusUpdate', {
        jobName,
        jobStatus: conversion_jobs.ConversionJobStatus.InProgress,
    });
    const outPath = '/trace.json';
    const args = [format];
    if (truncate !== undefined) {
        args.push('--truncate', truncate);
    }
    args.push('/fs/trace.proto', outPath);
    runTraceconv(trace, args)
        .then(module => {
        const fsNode = module.FS.lookupPath(outPath).node;
        const data = fsNode.contents.buffer;
        const size = fsNode.usedBytes;
        globals.globals.publish('LegacyTrace', { data, size }, /*transfer=*/ [data]);
        module.FS.unlink(outPath);
    })
        .finally(() => {
        globals.globals.publish('ConversionJobStatusUpdate', {
            jobName,
            jobStatus: conversion_jobs.ConversionJobStatus.NotRunning,
        });
    });
}
exports.ConvertTrace = ConvertTrace;
function ConvertTraceAndDownload(trace, format, truncate) {
    const jobName = `convert_${format}`;
    globals.globals.publish('ConversionJobStatusUpdate', {
        jobName,
        jobStatus: conversion_jobs.ConversionJobStatus.InProgress,
    });
    const outPath = '/trace.json';
    const args = [format];
    if (truncate !== undefined) {
        args.push('--truncate', truncate);
    }
    args.push('/fs/trace.proto', outPath);
    runTraceconv(trace, args)
        .then(module => {
        const fsNode = module.FS.lookupPath(outPath).node;
        downloadFile(fsNodeToBlob(fsNode), `trace.${format}`);
        module.FS.unlink(outPath);
    })
        .finally(() => {
        globals.globals.publish('ConversionJobStatusUpdate', {
            jobName,
            jobStatus: conversion_jobs.ConversionJobStatus.NotRunning,
        });
    });
}
exports.ConvertTraceAndDownload = ConvertTraceAndDownload;
function ConvertTraceToPprof(pid, src, ts1, ts2) {
    const jobName = 'convert_pprof';
    globals.globals.publish('ConversionJobStatusUpdate', {
        jobName,
        jobStatus: conversion_jobs.ConversionJobStatus.InProgress,
    });
    const timestamps = `${ts1}${ts2 === undefined ? '' : `,${ts2}`}`;
    const args = [
        'profile',
        `--pid`,
        `${pid}`,
        `--timestamps`,
        timestamps,
        '/fs/trace.proto'
    ];
    generateBlob(src)
        .then(traceBlob => {
        runTraceconv(traceBlob, args).then(module => {
            const heapDirName = Object.keys(module.FS.lookupPath('/tmp/').node.contents)[0];
            const heapDirContents = module.FS.lookupPath(`/tmp/${heapDirName}`).node.contents;
            const heapDumpFiles = Object.keys(heapDirContents);
            let fileNum = 0;
            heapDumpFiles.forEach(heapDump => {
                const fileNode = module.FS.lookupPath(`/tmp/${heapDirName}/${heapDump}`).node;
                fileNum++;
                const fileName = `/heap_dump.${fileNum}.${pid}.pb`;
                downloadFile(fsNodeToBlob(fileNode), fileName);
            });
        });
    })
        .finally(() => {
        globals.globals.publish('ConversionJobStatusUpdate', {
            jobName,
            jobStatus: conversion_jobs.ConversionJobStatus.NotRunning,
        });
    });
}
exports.ConvertTraceToPprof = ConvertTraceToPprof;
function runTraceconv(trace, args) {
    return tslib.__awaiter(this, void 0, void 0, function* () {
        const deferredRuntimeInitialized = deferred.defer();
        const module = trace_to_text({
            noInitialRun: true,
            locateFile: (s) => s,
            print: updateStatus,
            printErr: updateStatus,
            onRuntimeInitialized: () => deferredRuntimeInitialized.resolve()
        });
        yield deferredRuntimeInitialized;
        module.FS.mkdir('/fs');
        module.FS.mount(logging.assertExists(module.FS.filesystems.WORKERFS), { blobs: [{ name: 'trace.proto', data: trace }] }, '/fs');
        updateStatus('Converting trace');
        module.callMain(args);
        updateStatus('Trace conversion completed');
        return module;
    });
}
function generateBlob(src) {
    return tslib.__awaiter(this, void 0, void 0, function* () {
        let blob = new Blob();
        if (src.type === 'URL') {
            const resp = yield fetch(src.url);
            if (resp.status !== 200) {
                throw new Error(`fetch() failed with HTTP error ${resp.status}`);
            }
            blob = yield resp.blob();
        }
        else if (src.type === 'ARRAY_BUFFER') {
            blob = new Blob([new Uint8Array(src.buffer, 0, src.buffer.byteLength)]);
        }
        else if (src.type === 'FILE') {
            blob = src.file;
        }
        else {
            throw new Error(`Conversion not supported for ${JSON.stringify(src)}`);
        }
        return blob;
    });
}
function fsNodeToBlob(fsNode) {
    const fileSize = logging.assertExists(fsNode.usedBytes);
    const bufView = new Uint8Array(fsNode.contents.buffer, 0, fileSize);
    return new Blob([bufView]);
}
function downloadFile(file, name) {
    globals.globals.publish('FileDownload', { file, name });
}
function updateStatus(msg) {
    console.log(msg);
    globals.globals.dispatch(actions.Actions.updateStatus({
        msg: msg.toString(),
        timestamp: Date.now() / 1000,
    }));
}

});

var common = createCommonjsModule(function (module, exports) {
Object.defineProperty(exports, "__esModule", { value: true });
exports.ACTUAL_FRAMES_SLICE_TRACK_KIND = void 0;
exports.ACTUAL_FRAMES_SLICE_TRACK_KIND = 'ActualFramesSliceTrack';

});

var common$1 = createCommonjsModule(function (module, exports) {
Object.defineProperty(exports, "__esModule", { value: true });
exports.ASYNC_SLICE_TRACK_KIND = void 0;
exports.ASYNC_SLICE_TRACK_KIND = 'AsyncSliceTrack';

});

var common$2 = createCommonjsModule(function (module, exports) {
// 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.
Object.defineProperty(exports, "__esModule", { value: true });
exports.COUNTER_TRACK_KIND = void 0;
exports.COUNTER_TRACK_KIND = 'CounterTrack';

});

var common$3 = createCommonjsModule(function (module, exports) {
// Copyright (C) 2020 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 {Data as ChromeSlicesData} from '../chrome_slices/common';
Object.defineProperty(exports, "__esModule", { value: true });
exports.DEBUG_SLICE_TRACK_KIND = void 0;
exports.DEBUG_SLICE_TRACK_KIND = 'DebugSliceTrack';

});

var common$4 = createCommonjsModule(function (module, exports) {
Object.defineProperty(exports, "__esModule", { value: true });
exports.EXPECTED_FRAMES_SLICE_TRACK_KIND = void 0;
exports.EXPECTED_FRAMES_SLICE_TRACK_KIND = 'ExpectedFramesSliceTrack';

});

var common$5 = createCommonjsModule(function (module, exports) {
Object.defineProperty(exports, "__esModule", { value: true });
exports.HEAP_PROFILE_TRACK_KIND = void 0;
exports.HEAP_PROFILE_TRACK_KIND = 'HeapProfileTrack';

});

var common$6 = createCommonjsModule(function (module, exports) {
// Copyright (C) 2019 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.
Object.defineProperty(exports, "__esModule", { value: true });
exports.PROCESS_SCHEDULING_TRACK_KIND = void 0;
exports.PROCESS_SCHEDULING_TRACK_KIND = 'ProcessSchedulingTrack';

});

var common$7 = createCommonjsModule(function (module, exports) {
// 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.
Object.defineProperty(exports, "__esModule", { value: true });
exports.PROCESS_SUMMARY_TRACK = void 0;
exports.PROCESS_SUMMARY_TRACK = 'ProcessSummaryTrack';

});

var flamegraph_util = createCommonjsModule(function (module, exports) {
// Copyright (C) 2019 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.
Object.defineProperty(exports, "__esModule", { value: true });
exports.findRootSize = exports.mergeCallsites = exports.expandCallsites = exports.DEFAULT_VIEWING_OPTION = exports.OBJECTS_ALLOCATED_KEY = exports.OBJECTS_ALLOCATED_NOT_FREED_KEY = exports.ALLOC_SPACE_MEMORY_ALLOCATED_KEY = exports.SPACE_MEMORY_ALLOCATED_NOT_FREED_KEY = void 0;
exports.SPACE_MEMORY_ALLOCATED_NOT_FREED_KEY = 'SPACE';
exports.ALLOC_SPACE_MEMORY_ALLOCATED_KEY = 'ALLOC_SPACE';
exports.OBJECTS_ALLOCATED_NOT_FREED_KEY = 'OBJECTS';
exports.OBJECTS_ALLOCATED_KEY = 'ALLOC_OBJECTS';
exports.DEFAULT_VIEWING_OPTION = exports.SPACE_MEMORY_ALLOCATED_NOT_FREED_KEY;
function expandCallsites(data, clickedCallsiteIndex) {
    if (clickedCallsiteIndex === -1)
        return data;
    const expandedCallsites = [];
    if (clickedCallsiteIndex >= data.length || clickedCallsiteIndex < -1) {
        return expandedCallsites;
    }
    const clickedCallsite = data[clickedCallsiteIndex];
    expandedCallsites.unshift(clickedCallsite);
    // Adding parents
    let parentId = clickedCallsite.parentId;
    while (parentId > -1) {
        expandedCallsites.unshift(data[parentId]);
        parentId = data[parentId].parentId;
    }
    // Adding children
    const parents = [];
    parents.push(clickedCallsiteIndex);
    for (let i = clickedCallsiteIndex + 1; i < data.length; i++) {
        const element = data[i];
        if (parents.includes(element.parentId)) {
            expandedCallsites.push(element);
            parents.push(element.id);
        }
    }
    return expandedCallsites;
}
exports.expandCallsites = expandCallsites;
// Merge callsites that have approximately width less than
// MIN_PIXEL_DISPLAYED. All small callsites in the same depth and with same
// parent will be merged to one with total size of all merged callsites.
function mergeCallsites(data, minSizeDisplayed) {
    const mergedData = [];
    const mergedCallsites = new Map();
    for (let i = 0; i < data.length; i++) {
        // When a small callsite is found, it will be merged with other small
        // callsites of the same depth. So if the current callsite has already been
        // merged we can skip it.
        if (mergedCallsites.has(data[i].id)) {
            continue;
        }
        const copiedCallsite = copyCallsite(data[i]);
        copiedCallsite.parentId =
            getCallsitesParentHash(copiedCallsite, mergedCallsites);
        let mergedAny = false;
        // If current callsite is small, find other small callsites with same depth
        // and parent and merge them into the current one, marking them as merged.
        if (copiedCallsite.totalSize <= minSizeDisplayed && i + 1 < data.length) {
            let j = i + 1;
            let nextCallsite = data[j];
            while (j < data.length && copiedCallsite.depth === nextCallsite.depth) {
                if (copiedCallsite.parentId ===
                    getCallsitesParentHash(nextCallsite, mergedCallsites) &&
                    nextCallsite.totalSize <= minSizeDisplayed) {
                    copiedCallsite.totalSize += nextCallsite.totalSize;
                    mergedCallsites.set(nextCallsite.id, copiedCallsite.id);
                    mergedAny = true;
                }
                j++;
                nextCallsite = data[j];
            }
            if (mergedAny) {
                copiedCallsite.name = '[merged]';
                copiedCallsite.merged = true;
            }
        }
        mergedData.push(copiedCallsite);
    }
    return mergedData;
}
exports.mergeCallsites = mergeCallsites;
function copyCallsite(callsite) {
    return {
        id: callsite.id,
        parentId: callsite.parentId,
        depth: callsite.depth,
        name: callsite.name,
        totalSize: callsite.totalSize,
        mapping: callsite.mapping,
        selfSize: callsite.selfSize,
        merged: callsite.merged,
        highlighted: callsite.highlighted,
        location: callsite.location
    };
}
function getCallsitesParentHash(callsite, map) {
    return map.has(callsite.parentId) ? +map.get(callsite.parentId) :
        callsite.parentId;
}
function findRootSize(data) {
    let totalSize = 0;
    let i = 0;
    while (i < data.length && data[i].depth === 0) {
        totalSize += data[i].totalSize;
        i++;
    }
    return totalSize;
}
exports.findRootSize = findRootSize;

});

var actions = createCommonjsModule(function (module, exports) {
// 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.
Object.defineProperty(exports, "__esModule", { value: true });
exports.Actions = exports.StateActions = void 0;













const highPriorityTrackOrder = [
    common$6.PROCESS_SCHEDULING_TRACK_KIND,
    common$7.PROCESS_SUMMARY_TRACK,
    common$4.EXPECTED_FRAMES_SLICE_TRACK_KIND,
    common.ACTUAL_FRAMES_SLICE_TRACK_KIND
];
const lowPriorityTrackOrder = [common$5.HEAP_PROFILE_TRACK_KIND, common$2.COUNTER_TRACK_KIND, common$1.ASYNC_SLICE_TRACK_KIND];
function clearTraceState(state$1) {
    const nextId = state$1.nextId;
    const recordConfig = state$1.recordConfig;
    const route = state$1.route;
    const recordingTarget = state$1.recordingTarget;
    const updateChromeCategories = state$1.updateChromeCategories;
    const extensionInstalled = state$1.extensionInstalled;
    const availableAdbDevices = state$1.availableAdbDevices;
    const chromeCategories = state$1.chromeCategories;
    const newEngineMode = state$1.newEngineMode;
    Object.assign(state$1, state.createEmptyState());
    state$1.nextId = nextId;
    state$1.recordConfig = recordConfig;
    state$1.route = route;
    state$1.recordingTarget = recordingTarget;
    state$1.updateChromeCategories = updateChromeCategories;
    state$1.extensionInstalled = extensionInstalled;
    state$1.availableAdbDevices = availableAdbDevices;
    state$1.chromeCategories = chromeCategories;
    state$1.newEngineMode = newEngineMode;
}
function rank(ts) {
    const hpRank = rankIndex(ts.kind, highPriorityTrackOrder);
    const lpRank = rankIndex(ts.kind, lowPriorityTrackOrder);
    // TODO(hjd): Create sortBy object on TrackState to avoid this cast.
    const tid = ts.config.tid || 0;
    return [hpRank, ts.trackKindPriority.valueOf(), lpRank, tid];
}
function rankIndex(element, array) {
    const index = array.indexOf(element);
    if (index === -1)
        return array.length;
    return index;
}
exports.StateActions = {
    navigate(state, args) {
        state.route = args.route;
    },
    openTraceFromFile(state, args) {
        clearTraceState(state);
        const id = `${state.nextId++}`;
        state.engines[id] = {
            id,
            ready: false,
            source: { type: 'FILE', file: args.file },
        };
        state.route = `/viewer`;
    },
    openTraceFromBuffer(state, args) {
        clearTraceState(state);
        const id = `${state.nextId++}`;
        state.engines[id] = {
            id,
            ready: false,
            source: Object.assign({ type: 'ARRAY_BUFFER' }, args),
        };
        state.route = `/viewer`;
    },
    openTraceFromUrl(state, args) {
        clearTraceState(state);
        const id = `${state.nextId++}`;
        state.engines[id] = {
            id,
            ready: false,
            source: { type: 'URL', url: args.url },
        };
        state.route = `/viewer`;
    },
    openTraceFromHttpRpc(state, _args) {
        clearTraceState(state);
        const id = `${state.nextId++}`;
        state.engines[id] = {
            id,
            ready: false,
            source: { type: 'HTTP_RPC' },
        };
        state.route = `/viewer`;
    },
    openVideoFromFile(state, args) {
        state.video = URL.createObjectURL(args.file);
        state.videoEnabled = true;
    },
    // TODO(b/141359485): Actions should only modify state.
    convertTraceToJson(_, args) {
        trace_converter.ConvertTrace(args.file, 'json', args.truncate);
    },
    convertTraceToSystraceAndDownload(_, args) {
        trace_converter.ConvertTraceAndDownload(args.file, 'systrace');
    },
    convertTraceToJsonAndDownload(_, args) {
        trace_converter.ConvertTraceAndDownload(args.file, 'json');
    },
    convertTraceToPprof(_, args) {
        trace_converter.ConvertTraceToPprof(args.pid, args.src, args.ts1, args.ts2);
    },
    addTracks(state$1, args) {
        args.tracks.forEach(track => {
            const id = track.id === undefined ? `${state$1.nextId++}` : track.id;
            track.id = id;
            state$1.tracks[id] = track;
            if (track.trackGroup === state.SCROLLING_TRACK_GROUP) {
                state$1.scrollingTracks.push(id);
            }
            else if (track.trackGroup !== undefined) {
                logging.assertExists(state$1.trackGroups[track.trackGroup]).tracks.push(id);
            }
        });
    },
    addTrack(state$1, args) {
        const id = args.id !== undefined ? args.id : `${state$1.nextId++}`;
        state$1.tracks[id] = {
            id,
            engineId: args.engineId,
            kind: args.kind,
            name: args.name,
            trackKindPriority: args.trackKindPriority,
            trackGroup: args.trackGroup,
            config: args.config,
        };
        if (args.trackGroup === state.SCROLLING_TRACK_GROUP) {
            state$1.scrollingTracks.push(id);
        }
        else if (args.trackGroup !== undefined) {
            logging.assertExists(state$1.trackGroups[args.trackGroup]).tracks.push(id);
        }
    },
    addTrackGroup(state, 
    // Define ID in action so a track group can be referred to without running
    // the reducer.
    args) {
        state.trackGroups[args.id] = {
            engineId: args.engineId,
            name: args.name,
            id: args.id,
            collapsed: args.collapsed,
            tracks: [args.summaryTrackId],
        };
    },
    addDebugTrack(state$1, args) {
        if (state$1.debugTrackId !== undefined)
            return;
        const trackId = `${state$1.nextId++}`;
        state$1.debugTrackId = trackId;
        this.addTrack(state$1, {
            id: trackId,
            engineId: args.engineId,
            kind: common$3.DEBUG_SLICE_TRACK_KIND,
            name: args.name,
            trackKindPriority: state.TrackKindPriority.ORDINARY,
            trackGroup: state.SCROLLING_TRACK_GROUP,
            config: {
                maxDepth: 1,
            }
        });
        this.toggleTrackPinned(state$1, { trackId });
    },
    removeDebugTrack(state, _) {
        const { debugTrackId } = state;
        if (debugTrackId === undefined)
            return;
        delete state.tracks[debugTrackId];
        state.scrollingTracks =
            state.scrollingTracks.filter(id => id !== debugTrackId);
        state.pinnedTracks = state.pinnedTracks.filter(id => id !== debugTrackId);
        state.debugTrackId = undefined;
    },
    sortThreadTracks(state, _) {
        // Use a numeric collator so threads are sorted as T1, T2, ..., T10, T11,
        // rather than T1, T10, T11, ..., T2, T20, T21 .
        const coll = new Intl.Collator([], { sensitivity: 'base', numeric: true });
        for (const group of Object.values(state.trackGroups)) {
            group.tracks.sort((a, b) => {
                const aRank = rank(state.tracks[a]);
                const bRank = rank(state.tracks[b]);
                for (let i = 0; i < aRank.length; i++) {
                    if (aRank[i] !== bRank[i])
                        return aRank[i] - bRank[i];
                }
                const aName = state.tracks[a].name.toLocaleLowerCase();
                const bName = state.tracks[b].name.toLocaleLowerCase();
                return coll.compare(aName, bName);
            });
        }
    },
    updateAggregateSorting(state, args) {
        let prefs = state.aggregatePreferences[args.id];
        if (!prefs) {
            prefs = { id: args.id };
            state.aggregatePreferences[args.id] = prefs;
        }
        if (!prefs.sorting || prefs.sorting.column !== args.column) {
            // No sorting set for current column.
            state.aggregatePreferences[args.id].sorting = {
                column: args.column,
                direction: 'DESC'
            };
        }
        else if (prefs.sorting.direction === 'DESC') {
            // Toggle the direction if the column is currently sorted.
            state.aggregatePreferences[args.id].sorting = {
                column: args.column,
                direction: 'ASC'
            };
        }
        else {
            // If direction is currently 'ASC' toggle to no sorting.
            state.aggregatePreferences[args.id].sorting = undefined;
        }
    },
    setVisibleTracks(state, args) {
        state.visibleTracks = args.tracks;
    },
    updateTrackConfig(state, args) {
        if (state.tracks[args.id] === undefined)
            return;
        state.tracks[args.id].config = args.config;
    },
    executeQuery(state, args) {
        state.queries[args.queryId] = {
            id: args.queryId,
            engineId: args.engineId,
            query: args.query,
        };
    },
    deleteQuery(state, args) {
        delete state.queries[args.queryId];
    },
    moveTrack(state, args) {
        const moveWithinTrackList = (trackList) => {
            const newList = [];
            for (let i = 0; i < trackList.length; i++) {
                const curTrackId = trackList[i];
                if (curTrackId === args.dstId && args.op === 'before') {
                    newList.push(args.srcId);
                }
                if (curTrackId !== args.srcId) {
                    newList.push(curTrackId);
                }
                if (curTrackId === args.dstId && args.op === 'after') {
                    newList.push(args.srcId);
                }
            }
            trackList.splice(0);
            newList.forEach(x => {
                trackList.push(x);
            });
        };
        moveWithinTrackList(state.pinnedTracks);
        moveWithinTrackList(state.scrollingTracks);
    },
    toggleTrackPinned(state$1, args) {
        const id = args.trackId;
        const isPinned = state$1.pinnedTracks.includes(id);
        const trackGroup = logging.assertExists(state$1.tracks[id]).trackGroup;
        if (isPinned) {
            state$1.pinnedTracks.splice(state$1.pinnedTracks.indexOf(id), 1);
            if (trackGroup === state.SCROLLING_TRACK_GROUP) {
                state$1.scrollingTracks.unshift(id);
            }
        }
        else {
            if (trackGroup === state.SCROLLING_TRACK_GROUP) {
                state$1.scrollingTracks.splice(state$1.scrollingTracks.indexOf(id), 1);
            }
            state$1.pinnedTracks.push(id);
        }
    },
    toggleTrackGroupCollapsed(state, args) {
        const id = args.trackGroupId;
        const trackGroup = logging.assertExists(state.trackGroups[id]);
        trackGroup.collapsed = !trackGroup.collapsed;
    },
    requestTrackReload(state, _) {
        if (state.lastTrackReloadRequest) {
            state.lastTrackReloadRequest++;
        }
        else {
            state.lastTrackReloadRequest = 1;
        }
    },
    setEngineReady(state, args) {
        const engine = state.engines[args.engineId];
        if (engine === undefined) {
            return;
        }
        engine.ready = args.ready;
        engine.mode = args.mode;
    },
    setNewEngineMode(state, args) {
        state.newEngineMode = args.mode;
    },
    // Marks all engines matching the given |mode| as failed.
    setEngineFailed(state, args) {
        for (const engine of Object.values(state.engines)) {
            if (engine.mode === args.mode)
                engine.failed = args.failure;
        }
    },
    createPermalink(state, args) {
        state.permalink = {
            requestId: `${state.nextId++}`,
            hash: undefined,
            isRecordingConfig: args.isRecordingConfig
        };
    },
    setPermalink(state, args) {
        // Drop any links for old requests.
        if (state.permalink.requestId !== args.requestId)
            return;
        state.permalink = args;
    },
    loadPermalink(state, args) {
        state.permalink = { requestId: `${state.nextId++}`, hash: args.hash };
    },
    clearPermalink(state, _) {
        state.permalink = {};
    },
    setTraceTime(state, args) {
        state.traceTime = args;
    },
    updateStatus(state, args) {
        state.status = args;
    },
    // TODO(hjd): Remove setState - it causes problems due to reuse of ids.
    setState(state, args) {
        for (const key of Object.keys(state)) {
            // tslint:disable-next-line no-any
            delete state[key];
        }
        for (const key of Object.keys(args.newState)) {
            // tslint:disable-next-line no-any
            state[key] = args.newState[key];
        }
    },
    setRecordConfig(state, args) {
        state.recordConfig = args.config;
    },
    selectNote(state, args) {
        if (args.id) {
            state.currentSelection = {
                kind: 'NOTE',
                id: args.id
            };
        }
    },
    addNote(state, args) {
        const id = `${state.nextNoteId++}`;
        state.notes[id] = {
            noteType: 'DEFAULT',
            id,
            timestamp: args.timestamp,
            color: args.color,
            text: '',
        };
        if (args.isMovie) {
            state.videoNoteIds.push(id);
        }
        this.selectNote(state, { id });
    },
    markCurrentArea(state, args) {
        if (state.currentSelection === null ||
            state.currentSelection.kind !== 'AREA') {
            return;
        }
        const id = args.persistent ? `${state.nextNoteId++}` : '0';
        const color = args.persistent ? args.color : '#344596';
        state.notes[id] = {
            noteType: 'AREA',
            id,
            areaId: state.currentSelection.areaId,
            color,
            text: '',
        };
        state.currentSelection.noteId = id;
    },
    toggleMarkCurrentArea(state, args) {
        const selection = state.currentSelection;
        if (selection != null && selection.kind === 'AREA' &&
            selection.noteId !== undefined) {
            this.removeNote(state, { id: selection.noteId });
        }
        else {
            const color = colorizer.randomColor();
            this.markCurrentArea(state, { color, persistent: args.persistent });
        }
    },
    markArea(state, args) {
        const areaId = `${state.nextAreaId++}`;
        logging.assertTrue(args.area.endSec >= args.area.startSec);
        state.areas[areaId] = {
            id: areaId,
            startSec: args.area.startSec,
            endSec: args.area.endSec,
            tracks: args.area.tracks
        };
        const id = args.persistent ? `${state.nextNoteId++}` : '0';
        const color = args.persistent ? colorizer.randomColor() : '#344596';
        state.notes[id] = {
            noteType: 'AREA',
            id,
            areaId,
            color,
            text: '',
        };
    },
    toggleVideo(state, _) {
        state.videoEnabled = !state.videoEnabled;
        if (!state.videoEnabled) {
            state.video = null;
            state.flagPauseEnabled = false;
            state.scrubbingEnabled = false;
            state.videoNoteIds.forEach(id => {
                this.removeNote(state, { id });
            });
        }
    },
    toggleFlagPause(state, _) {
        if (state.video != null) {
            state.flagPauseEnabled = !state.flagPauseEnabled;
        }
    },
    toggleScrubbing(state, _) {
        if (state.video != null) {
            state.scrubbingEnabled = !state.scrubbingEnabled;
        }
    },
    setVideoOffset(state, args) {
        state.videoOffset = args.offset;
    },
    changeNoteColor(state, args) {
        const note = state.notes[args.id];
        if (note === undefined)
            return;
        note.color = args.newColor;
    },
    changeNoteText(state, args) {
        const note = state.notes[args.id];
        if (note === undefined)
            return;
        note.text = args.newText;
    },
    removeNote(state, args) {
        if (state.notes[args.id] === undefined)
            return;
        if (state.notes[args.id].noteType === 'MOVIE') {
            state.videoNoteIds = state.videoNoteIds.filter(id => {
                return id !== args.id;
            });
        }
        delete state.notes[args.id];
        // For regular notes, we clear the current selection but for an area note
        // we only want to clear the note/marking and leave the area selected.
        if (state.currentSelection === null)
            return;
        if (state.currentSelection.kind === 'NOTE' &&
            state.currentSelection.id === args.id) {
            state.currentSelection = null;
        }
        else if (state.currentSelection.kind === 'AREA' &&
            state.currentSelection.noteId === args.id) {
            state.currentSelection.noteId = undefined;
        }
    },
    selectSlice(state, args) {
        state.currentSelection = {
            kind: 'SLICE',
            id: args.id,
            trackId: args.trackId,
        };
    },
    selectCounter(state, args) {
        state.currentSelection = {
            kind: 'COUNTER',
            leftTs: args.leftTs,
            rightTs: args.rightTs,
            id: args.id,
            trackId: args.trackId,
        };
    },
    selectHeapProfile(state, args) {
        state.currentSelection = {
            kind: 'HEAP_PROFILE',
            id: args.id,
            upid: args.upid,
            ts: args.ts,
            type: args.type,
        };
        state.currentHeapProfileFlamegraph = {
            kind: 'HEAP_PROFILE_FLAMEGRAPH',
            id: args.id,
            upid: args.upid,
            ts: args.ts,
            type: args.type,
            viewingOption: flamegraph_util.DEFAULT_VIEWING_OPTION,
            focusRegex: '',
        };
    },
    selectCpuProfileSample(state, args) {
        state.currentSelection = {
            kind: 'CPU_PROFILE_SAMPLE',
            id: args.id,
            utid: args.utid,
            ts: args.ts,
        };
    },
    expandHeapProfileFlamegraph(state, args) {
        if (state.currentHeapProfileFlamegraph === null)
            return;
        state.currentHeapProfileFlamegraph.expandedCallsite = args.expandedCallsite;
    },
    changeViewHeapProfileFlamegraph(state, args) {
        if (state.currentHeapProfileFlamegraph === null)
            return;
        state.currentHeapProfileFlamegraph.viewingOption = args.viewingOption;
    },
    changeFocusHeapProfileFlamegraph(state, args) {
        if (state.currentHeapProfileFlamegraph === null)
            return;
        state.currentHeapProfileFlamegraph.focusRegex = args.focusRegex;
    },
    selectChromeSlice(state, args) {
        state.currentSelection = {
            kind: 'CHROME_SLICE',
            id: args.id,
            trackId: args.trackId,
            table: args.table
        };
    },
    selectThreadState(state, args) {
        state.currentSelection = {
            kind: 'THREAD_STATE',
            id: args.id,
            trackId: args.trackId,
        };
    },
    deselect(state, _) {
        state.currentSelection = null;
    },
    updateLogsPagination(state, args) {
        state.logsPagination = args;
    },
    startRecording(state, _) {
        state.recordingInProgress = true;
        state.lastRecordingError = undefined;
        state.recordingCancelled = false;
    },
    stopRecording(state, _) {
        state.recordingInProgress = false;
    },
    cancelRecording(state, _) {
        state.recordingInProgress = false;
        state.recordingCancelled = true;
    },
    setExtensionAvailable(state, args) {
        state.extensionInstalled = args.available;
    },
    updateBufferUsage(state, args) {
        state.bufferUsage = args.percentage;
    },
    setRecordingTarget(state, args) {
        state.recordingTarget = args.target;
    },
    setUpdateChromeCategories(state, args) {
        state.updateChromeCategories = args.update;
    },
    setAvailableAdbDevices(state, args) {
        state.availableAdbDevices = args.devices;
    },
    setOmnibox(state, args) {
        state.frontendLocalState.omniboxState = args;
    },
    selectArea(state, args) {
        const areaId = `${state.nextAreaId++}`;
        logging.assertTrue(args.area.endSec >= args.area.startSec);
        state.areas[areaId] = {
            id: areaId,
            startSec: args.area.startSec,
            endSec: args.area.endSec,
            tracks: args.area.tracks
        };
        state.currentSelection = { kind: 'AREA', areaId };
    },
    editArea(state, args) {
        logging.assertTrue(args.area.endSec >= args.area.startSec);
        state.areas[args.areaId] = {
            id: args.areaId,
            startSec: args.area.startSec,
            endSec: args.area.endSec,
            tracks: args.area.tracks
        };
    },
    reSelectArea(state, args) {
        state.currentSelection = {
            kind: 'AREA',
            areaId: args.areaId,
            noteId: args.noteId
        };
    },
    toggleTrackSelection(state, args) {
        const selection = state.currentSelection;
        if (selection === null || selection.kind !== 'AREA')
            return;
        const areaId = selection.areaId;
        const index = state.areas[areaId].tracks.indexOf(args.id);
        if (index > -1) {
            state.areas[areaId].tracks.splice(index, 1);
            if (args.isTrackGroup) { // Also remove all child tracks.
                for (const childTrack of state.trackGroups[args.id].tracks) {
                    const childIndex = state.areas[areaId].tracks.indexOf(childTrack);
                    if (childIndex > -1) {
                        state.areas[areaId].tracks.splice(childIndex, 1);
                    }
                }
            }
        }
        else {
            state.areas[areaId].tracks.push(args.id);
            if (args.isTrackGroup) { // Also add all child tracks.
                for (const childTrack of state.trackGroups[args.id].tracks) {
                    if (!state.areas[areaId].tracks.includes(childTrack)) {
                        state.areas[areaId].tracks.push(childTrack);
                    }
                }
            }
        }
    },
    setVisibleTraceTime(state, args) {
        state.frontendLocalState.visibleState = args;
    },
    setChromeCategories(state, args) {
        state.chromeCategories = args.categories;
    },
    setLastRecordingError(state, args) {
        state.lastRecordingError = args.error;
        state.recordingStatus = undefined;
    },
    setRecordingStatus(state, args) {
        state.recordingStatus = args.status;
        state.lastRecordingError = undefined;
    },
    setAnalyzePageQuery(state, args) {
        state.analyzePageQuery = args.query;
    },
    requestSelectedMetric(state, _) {
        if (!state.metrics.availableMetrics)
            throw Error('No metrics available');
        if (state.metrics.selectedIndex === undefined) {
            throw Error('No metric selected');
        }
        state.metrics.requestedMetric =
            state.metrics.availableMetrics[state.metrics.selectedIndex];
    },
    resetMetricRequest(state, args) {
        if (state.metrics.requestedMetric !== args.name)
            return;
        state.metrics.requestedMetric = undefined;
    },
    setAvailableMetrics(state, args) {
        state.metrics.availableMetrics = args.metrics;
        if (args.metrics.length > 0)
            state.metrics.selectedIndex = 0;
    },
    setMetricSelectedIndex(state, args) {
        if (!state.metrics.availableMetrics ||
            args.index >= state.metrics.availableMetrics.length) {
            throw Error('metric selection out of bounds');
        }
        state.metrics.selectedIndex = args.index;
    },
};
// Actions is an implementation of DeferredActions<typeof StateActions>.
// (since StateActions is a variable not a type we have to do
// 'typeof StateActions' to access the (unnamed) type of StateActions).
// It's a Proxy such that any attribute access returns a function:
// (args) => {return {type: ATTRIBUTE_NAME, args};}
exports.Actions = 
// tslint:disable-next-line no-any
new Proxy({}, {
    // tslint:disable-next-line no-any
    get(_, prop, _2) {
        return (args) => {
            return {
                type: prop,
                args,
            };
        };
    },
});

});

var rate_limiters = createCommonjsModule(function (module, exports) {
// Copyright (C) 2020 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.
Object.defineProperty(exports, "__esModule", { value: true });
exports.debounce = exports.ratelimit = void 0;
// Returns a wrapper around |f| which calls f at most once every |ms|ms.
function ratelimit(f, ms) {
    let inProgess = false;
    return () => {
        if (inProgess) {
            return;
        }
        inProgess = true;
        window.setTimeout(() => {
            f();
            inProgess = false;
        }, ms);
    };
}
exports.ratelimit = ratelimit;
// Returns a wrapper around |f| which waits for a |ms|ms pause in calls
// before calling |f|.
function debounce(f, ms) {
    let timerId;
    return () => {
        if (timerId) {
            window.clearTimeout(timerId);
        }
        timerId = window.setTimeout(() => {
            f();
            timerId = undefined;
        }, ms);
    };
}
exports.debounce = debounce;

});

var time_scale = createCommonjsModule(function (module, exports) {
// 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.
Object.defineProperty(exports, "__esModule", { value: true });
exports.computeZoom = exports.TimeScale = void 0;


const MAX_ZOOM_SPAN_SEC = 1e-6; // 1us.
/**
 * Defines a mapping between number and seconds for the entire application.
 * Linearly scales time values from boundsMs to pixel values in boundsPx and
 * back.
 */
class TimeScale {
    constructor(timeBounds, boundsPx) {
        this.secPerPx = 0;
        this.timeBounds = timeBounds;
        this._startPx = boundsPx[0];
        this._endPx = boundsPx[1];
        this.updateSlope();
    }
    updateSlope() {
        this.secPerPx = this.timeBounds.duration / (this._endPx - this._startPx);
    }
    deltaTimeToPx(time) {
        return Math.round(time / this.secPerPx);
    }
    timeToPx(time) {
        return this._startPx + (time - this.timeBounds.start) / this.secPerPx;
    }
    pxToTime(px) {
        return this.timeBounds.start + (px - this._startPx) * this.secPerPx;
    }
    deltaPxToDuration(px) {
        return px * this.secPerPx;
    }
    setTimeBounds(timeBounds) {
        this.timeBounds = timeBounds;
        this.updateSlope();
    }
    setLimitsPx(pxStart, pxEnd) {
        logging.assertFalse(pxStart === pxEnd);
        logging.assertTrue(pxStart >= 0 && pxEnd >= 0);
        this._startPx = pxStart;
        this._endPx = pxEnd;
        this.updateSlope();
    }
    timeInBounds(time) {
        return this.timeBounds.isInBounds(time);
    }
    get startPx() {
        return this._startPx;
    }
    get endPx() {
        return this._endPx;
    }
}
exports.TimeScale = TimeScale;
function computeZoom(scale, span, zoomFactor, zoomPx) {
    const startPx = scale.startPx;
    const endPx = scale.endPx;
    const deltaPx = endPx - startPx;
    const deltaTime = span.end - span.start;
    const newDeltaTime = Math.max(deltaTime * zoomFactor, MAX_ZOOM_SPAN_SEC);
    const clampedZoomPx = Math.max(startPx, Math.min(endPx, zoomPx));
    const zoomTime = scale.pxToTime(clampedZoomPx);
    const r = (clampedZoomPx - startPx) / deltaPx;
    const newStartTime = zoomTime - newDeltaTime * r;
    const newEndTime = newStartTime + newDeltaTime;
    return new time.TimeSpan(newStartTime, newEndTime);
}
exports.computeZoom = computeZoom;

});

var frontend_local_state = createCommonjsModule(function (module, exports) {
// 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.
Object.defineProperty(exports, "__esModule", { value: true });
exports.FrontendLocalState = void 0;






function chooseLatest(current, next) {
    if (next !== current && next.lastUpdate > current.lastUpdate) {
        return next;
    }
    return current;
}
function capBetween(t, start, end) {
    return Math.min(Math.max(t, start), end);
}
// Calculate the space a scrollbar takes up so that we can subtract it from
// the canvas width.
function calculateScrollbarWidth() {
    const outer = document.createElement('div');
    outer.style.overflowY = 'scroll';
    const inner = document.createElement('div');
    outer.appendChild(inner);
    document.body.appendChild(outer);
    const width = outer.getBoundingClientRect().width - inner.getBoundingClientRect().width;
    document.body.removeChild(outer);
    return width;
}
/**
 * State that is shared between several frontend components, but not the
 * controller. This state is updated at 60fps.
 */
class FrontendLocalState {
    constructor() {
        this.visibleWindowTime = new time.TimeSpan(0, 10);
        this.timeScale = new time_scale.TimeScale(this.visibleWindowTime, [0, 0]);
        this.perfDebug = false;
        this.hoveredUtid = -1;
        this.hoveredPid = -1;
        this.hoveredLogsTimestamp = -1;
        this.hoveredNoteTimestamp = -1;
        this.highlightedSliceId = -1;
        this.focusedFlowIdLeft = -1;
        this.focusedFlowIdRight = -1;
        this.vidTimestamp = -1;
        this.localOnlyMode = false;
        this.sidebarVisible = false;
        this.showPanningHint = false;
        this.showCookieConsent = false;
        this.visibleTracks = new Set();
        this.prevVisibleTracks = new Set();
        this.searchIndex = -1;
        this.httpRpcState = { connected: false };
        this.newVersionAvailable = false;
        // This is used to calculate the tracks within a Y range for area selection.
        this.areaY = {};
        this._omniboxState = {
            lastUpdate: 0,
            omnibox: '',
            mode: 'SEARCH',
        };
        this._visibleState = {
            lastUpdate: 0,
            startSec: 0,
            endSec: 10,
            resolution: 1,
        };
        this.setOmniboxDebounced = rate_limiters.debounce(() => {
            globals$1.globals.dispatch(actions.Actions.setOmnibox(this._omniboxState));
        }, 20);
        this.ratelimitedUpdateVisible = rate_limiters.ratelimit(() => {
            globals$1.globals.dispatch(actions.Actions.setVisibleTraceTime(this._visibleState));
        }, 50);
    }
    // TODO: there is some redundancy in the fact that both |visibleWindowTime|
    // and a |timeScale| have a notion of time range. That should live in one
    // place only.
    getScrollbarWidth() {
        if (this.scrollBarWidth === undefined) {
            this.scrollBarWidth = calculateScrollbarWidth();
        }
        return this.scrollBarWidth;
    }
    togglePerfDebug() {
        this.perfDebug = !this.perfDebug;
        globals$1.globals.rafScheduler.scheduleFullRedraw();
    }
    setHoveredUtidAndPid(utid, pid) {
        this.hoveredUtid = utid;
        this.hoveredPid = pid;
        globals$1.globals.rafScheduler.scheduleRedraw();
    }
    setHighlightedSliceId(sliceId) {
        this.highlightedSliceId = sliceId;
        globals$1.globals.rafScheduler.scheduleRedraw();
    }
    setHighlightedFlowLeftId(flowId) {
        this.focusedFlowIdLeft = flowId;
        globals$1.globals.rafScheduler.scheduleFullRedraw();
    }
    setHighlightedFlowRightId(flowId) {
        this.focusedFlowIdRight = flowId;
        globals$1.globals.rafScheduler.scheduleFullRedraw();
    }
    // Sets the timestamp at which a vertical line will be drawn.
    setHoveredLogsTimestamp(ts) {
        if (this.hoveredLogsTimestamp === ts)
            return;
        this.hoveredLogsTimestamp = ts;
        globals$1.globals.rafScheduler.scheduleRedraw();
    }
    setHoveredNoteTimestamp(ts) {
        if (this.hoveredNoteTimestamp === ts)
            return;
        this.hoveredNoteTimestamp = ts;
        globals$1.globals.rafScheduler.scheduleRedraw();
    }
    setVidTimestamp(ts) {
        if (this.vidTimestamp === ts)
            return;
        this.vidTimestamp = ts;
        globals$1.globals.rafScheduler.scheduleRedraw();
    }
    addVisibleTrack(trackId) {
        this.visibleTracks.add(trackId);
    }
    setSearchIndex(index) {
        this.searchIndex = index;
        globals$1.globals.rafScheduler.scheduleRedraw();
    }
    toggleSidebar() {
        this.sidebarVisible = !this.sidebarVisible;
        globals$1.globals.rafScheduler.scheduleFullRedraw();
    }
    setHttpRpcState(httpRpcState) {
        this.httpRpcState = httpRpcState;
        globals$1.globals.rafScheduler.scheduleFullRedraw();
    }
    // Called when beginning a canvas redraw.
    clearVisibleTracks() {
        this.visibleTracks.clear();
    }
    // Called when the canvas redraw is complete.
    sendVisibleTracks() {
        if (this.prevVisibleTracks.size !== this.visibleTracks.size ||
            ![...this.prevVisibleTracks].every(value => this.visibleTracks.has(value))) {
            globals$1.globals.dispatch(actions.Actions.setVisibleTracks({ tracks: Array.from(this.visibleTracks) }));
            this.prevVisibleTracks = new Set(this.visibleTracks);
        }
    }
    mergeState(state) {
        this._omniboxState = chooseLatest(this._omniboxState, state.omniboxState);
        this._visibleState = chooseLatest(this._visibleState, state.visibleState);
        if (this._visibleState === state.visibleState) {
            this.updateLocalTime(new time.TimeSpan(this._visibleState.startSec, this._visibleState.endSec));
        }
    }
    selectArea(startSec, endSec, tracks = this._selectedArea ? this._selectedArea.tracks : []) {
        logging.assertTrue(endSec >= startSec);
        this.showPanningHint = true;
        this._selectedArea = { startSec, endSec, tracks },
            globals$1.globals.rafScheduler.scheduleFullRedraw();
    }
    deselectArea() {
        this._selectedArea = undefined;
        globals$1.globals.rafScheduler.scheduleRedraw();
    }
    get selectedArea() {
        return this._selectedArea;
    }
    setOmnibox(value, mode) {
        this._omniboxState.omnibox = value;
        this._omniboxState.mode = mode;
        this._omniboxState.lastUpdate = Date.now() / 1000;
        this.setOmniboxDebounced();
    }
    get omnibox() {
        return this._omniboxState.omnibox;
    }
    updateLocalTime(ts) {
        const traceTime = globals$1.globals.state.traceTime;
        const startSec = capBetween(ts.start, traceTime.startSec, traceTime.endSec);
        const endSec = capBetween(ts.end, traceTime.startSec, traceTime.endSec);
        this.visibleWindowTime = new time.TimeSpan(startSec, endSec);
        this.timeScale.setTimeBounds(this.visibleWindowTime);
        this.updateResolution();
    }
    updateResolution() {
        this._visibleState.lastUpdate = Date.now() / 1000;
        this._visibleState.resolution = globals$1.globals.getCurResolution();
        this.ratelimitedUpdateVisible();
    }
    updateVisibleTime(ts) {
        this.updateLocalTime(ts);
        this._visibleState.lastUpdate = Date.now() / 1000;
        this._visibleState.startSec = this.visibleWindowTime.start;
        this._visibleState.endSec = this.visibleWindowTime.end;
        this._visibleState.resolution = globals$1.globals.getCurResolution();
        this.ratelimitedUpdateVisible();
    }
    getVisibleStateBounds() {
        return [this.visibleWindowTime.start, this.visibleWindowTime.end];
    }
    // Whenever start/end px of the timeScale is changed, update
    // the resolution.
    updateLocalLimits(pxStart, pxEnd) {
        // Numbers received here can be negative or equal, but we should fix that
        // before updating the timescale.
        pxStart = Math.max(0, pxStart);
        pxEnd = Math.max(0, pxEnd);
        if (pxStart === pxEnd)
            pxEnd = pxStart + 1;
        this.timeScale.setLimitsPx(pxStart, pxEnd);
        this.updateResolution();
    }
}
exports.FrontendLocalState = FrontendLocalState;

});

function Vnode(tag, key, attrs, children, text, dom) {
	return {tag: tag, key: key, attrs: attrs, children: children, text: text, dom: dom, domSize: undefined, state: undefined, events: undefined, instance: undefined}
}
Vnode.normalize = function(node) {
	if (Array.isArray(node)) return Vnode("[", undefined, undefined, Vnode.normalizeChildren(node), undefined, undefined)
	if (node == null || typeof node === "boolean") return null
	if (typeof node === "object") return node
	return Vnode("#", undefined, undefined, String(node), undefined, undefined)
};
Vnode.normalizeChildren = function(input) {
	var children = [];
	if (input.length) {
		var isKeyed = input[0] != null && input[0].key != null;
		// Note: this is a *very* perf-sensitive check.
		// Fun fact: merging the loop like this is somehow faster than splitting
		// it, noticeably so.
		for (var i = 1; i < input.length; i++) {
			if ((input[i] != null && input[i].key != null) !== isKeyed) {
				throw new TypeError("Vnodes must either always have keys or never have keys!")
			}
		}
		for (var i = 0; i < input.length; i++) {
			children[i] = Vnode.normalize(input[i]);
		}
	}
	return children
};

var vnode = Vnode;

// Call via `hyperscriptVnode.apply(startOffset, arguments)`
//
// The reason I do it this way, forwarding the arguments and passing the start
// offset in `this`, is so I don't have to create a temporary array in a
// performance-critical path.
//
// In native ES6, I'd instead add a final `...args` parameter to the
// `hyperscript` and `fragment` factories and define this as
// `hyperscriptVnode(...args)`, since modern engines do optimize that away. But
// ES5 (what Mithril requires thanks to IE support) doesn't give me that luxury,
// and engines aren't nearly intelligent enough to do either of these:
//
// 1. Elide the allocation for `[].slice.call(arguments, 1)` when it's passed to
//    another function only to be indexed.
// 2. Elide an `arguments` allocation when it's passed to any function other
//    than `Function.prototype.apply` or `Reflect.apply`.
//
// In ES6, it'd probably look closer to this (I'd need to profile it, though):
// module.exports = function(attrs, ...children) {
//     if (attrs == null || typeof attrs === "object" && attrs.tag == null && !Array.isArray(attrs)) {
//         if (children.length === 1 && Array.isArray(children[0])) children = children[0]
//     } else {
//         children = children.length === 0 && Array.isArray(attrs) ? attrs : [attrs, ...children]
//         attrs = undefined
//     }
//
//     if (attrs == null) attrs = {}
//     return Vnode("", attrs.key, attrs, children)
// }
var hyperscriptVnode = function() {
	var attrs = arguments[this], start = this + 1, children;

	if (attrs == null) {
		attrs = {};
	} else if (typeof attrs !== "object" || attrs.tag != null || Array.isArray(attrs)) {
		attrs = {};
		start = this;
	}

	if (arguments.length === start + 1) {
		children = arguments[start];
		if (!Array.isArray(children)) children = [children];
	} else {
		children = [];
		while (start < arguments.length) children.push(arguments[start++]);
	}

	return vnode("", attrs.key, attrs, children)
};

var selectorParser = /(?:(^|#|\.)([^#\.\[\]]+))|(\[(.+?)(?:\s*=\s*("|'|)((?:\\["'\]]|.)*?)\5)?\])/g;
var selectorCache = {};
var hasOwn = {}.hasOwnProperty;

function isEmpty(object) {
	for (var key in object) if (hasOwn.call(object, key)) return false
	return true
}

function compileSelector(selector) {
	var match, tag = "div", classes = [], attrs = {};
	while (match = selectorParser.exec(selector)) {
		var type = match[1], value = match[2];
		if (type === "" && value !== "") tag = value;
		else if (type === "#") attrs.id = value;
		else if (type === ".") classes.push(value);
		else if (match[3][0] === "[") {
			var attrValue = match[6];
			if (attrValue) attrValue = attrValue.replace(/\\(["'])/g, "$1").replace(/\\\\/g, "\\");
			if (match[4] === "class") classes.push(attrValue);
			else attrs[match[4]] = attrValue === "" ? attrValue : attrValue || true;
		}
	}
	if (classes.length > 0) attrs.className = classes.join(" ");
	return selectorCache[selector] = {tag: tag, attrs: attrs}
}

function execSelector(state, vnode$1) {
	var attrs = vnode$1.attrs;
	var children = vnode.normalizeChildren(vnode$1.children);
	var hasClass = hasOwn.call(attrs, "class");
	var className = hasClass ? attrs.class : attrs.className;

	vnode$1.tag = state.tag;
	vnode$1.attrs = null;
	vnode$1.children = undefined;

	if (!isEmpty(state.attrs) && !isEmpty(attrs)) {
		var newAttrs = {};

		for (var key in attrs) {
			if (hasOwn.call(attrs, key)) newAttrs[key] = attrs[key];
		}

		attrs = newAttrs;
	}

	for (var key in state.attrs) {
		if (hasOwn.call(state.attrs, key) && key !== "className" && !hasOwn.call(attrs, key)){
			attrs[key] = state.attrs[key];
		}
	}
	if (className != null || state.attrs.className != null) attrs.className =
		className != null
			? state.attrs.className != null
				? String(state.attrs.className) + " " + String(className)
				: className
			: state.attrs.className != null
				? state.attrs.className
				: null;

	if (hasClass) attrs.class = null;

	for (var key in attrs) {
		if (hasOwn.call(attrs, key) && key !== "key") {
			vnode$1.attrs = attrs;
			break
		}
	}

	if (Array.isArray(children) && children.length === 1 && children[0] != null && children[0].tag === "#") {
		vnode$1.text = children[0].children;
	} else {
		vnode$1.children = children;
	}

	return vnode$1
}

function hyperscript(selector) {
	if (selector == null || typeof selector !== "string" && typeof selector !== "function" && typeof selector.view !== "function") {
		throw Error("The selector must be either a string or a component.");
	}

	var vnode$1 = hyperscriptVnode.apply(1, arguments);

	if (typeof selector === "string") {
		vnode$1.children = vnode.normalizeChildren(vnode$1.children);
		if (selector !== "[") return execSelector(selectorCache[selector] || compileSelector(selector), vnode$1)
	}

	vnode$1.tag = selector;
	return vnode$1
}

var hyperscript_1 = hyperscript;

var trust = function(html) {
	if (html == null) html = "";
	return vnode("<", undefined, undefined, html, undefined, undefined)
};

var fragment = function() {
	var vnode$1 = hyperscriptVnode.apply(0, arguments);

	vnode$1.tag = "[";
	vnode$1.children = vnode.normalizeChildren(vnode$1.children);
	return vnode$1
};

hyperscript_1.trust = trust;
hyperscript_1.fragment = fragment;

var hyperscript_1$1 = hyperscript_1;

/** @constructor */
var PromisePolyfill = function(executor) {
	if (!(this instanceof PromisePolyfill)) throw new Error("Promise must be called with `new`")
	if (typeof executor !== "function") throw new TypeError("executor must be a function")

	var self = this, resolvers = [], rejectors = [], resolveCurrent = handler(resolvers, true), rejectCurrent = handler(rejectors, false);
	var instance = self._instance = {resolvers: resolvers, rejectors: rejectors};
	var callAsync = typeof setImmediate === "function" ? setImmediate : setTimeout;
	function handler(list, shouldAbsorb) {
		return function execute(value) {
			var then;
			try {
				if (shouldAbsorb && value != null && (typeof value === "object" || typeof value === "function") && typeof (then = value.then) === "function") {
					if (value === self) throw new TypeError("Promise can't be resolved w/ itself")
					executeOnce(then.bind(value));
				}
				else {
					callAsync(function() {
						if (!shouldAbsorb && list.length === 0) console.error("Possible unhandled promise rejection:", value);
						for (var i = 0; i < list.length; i++) list[i](value);
						resolvers.length = 0, rejectors.length = 0;
						instance.state = shouldAbsorb;
						instance.retry = function() {execute(value);};
					});
				}
			}
			catch (e) {
				rejectCurrent(e);
			}
		}
	}
	function executeOnce(then) {
		var runs = 0;
		function run(fn) {
			return function(value) {
				if (runs++ > 0) return
				fn(value);
			}
		}
		var onerror = run(rejectCurrent);
		try {then(run(resolveCurrent), onerror);} catch (e) {onerror(e);}
	}

	executeOnce(executor);
};
PromisePolyfill.prototype.then = function(onFulfilled, onRejection) {
	var self = this, instance = self._instance;
	function handle(callback, list, next, state) {
		list.push(function(value) {
			if (typeof callback !== "function") next(value);
			else try {resolveNext(callback(value));} catch (e) {if (rejectNext) rejectNext(e);}
		});
		if (typeof instance.retry === "function" && state === instance.state) instance.retry();
	}
	var resolveNext, rejectNext;
	var promise = new PromisePolyfill(function(resolve, reject) {resolveNext = resolve, rejectNext = reject;});
	handle(onFulfilled, instance.resolvers, resolveNext, true), handle(onRejection, instance.rejectors, rejectNext, false);
	return promise
};
PromisePolyfill.prototype.catch = function(onRejection) {
	return this.then(null, onRejection)
};
PromisePolyfill.prototype.finally = function(callback) {
	return this.then(
		function(value) {
			return PromisePolyfill.resolve(callback()).then(function() {
				return value
			})
		},
		function(reason) {
			return PromisePolyfill.resolve(callback()).then(function() {
				return PromisePolyfill.reject(reason);
			})
		}
	)
};
PromisePolyfill.resolve = function(value) {
	if (value instanceof PromisePolyfill) return value
	return new PromisePolyfill(function(resolve) {resolve(value);})
};
PromisePolyfill.reject = function(value) {
	return new PromisePolyfill(function(resolve, reject) {reject(value);})
};
PromisePolyfill.all = function(list) {
	return new PromisePolyfill(function(resolve, reject) {
		var total = list.length, count = 0, values = [];
		if (list.length === 0) resolve([]);
		else for (var i = 0; i < list.length; i++) {
			(function(i) {
				function consume(value) {
					count++;
					values[i] = value;
					if (count === total) resolve(values);
				}
				if (list[i] != null && (typeof list[i] === "object" || typeof list[i] === "function") && typeof list[i].then === "function") {
					list[i].then(consume, reject);
				}
				else consume(list[i]);
			})(i);
		}
	})
};
PromisePolyfill.race = function(list) {
	return new PromisePolyfill(function(resolve, reject) {
		for (var i = 0; i < list.length; i++) {
			list[i].then(resolve, reject);
		}
	})
};

var polyfill = PromisePolyfill;

var promise = createCommonjsModule(function (module) {



if (typeof window !== "undefined") {
	if (typeof window.Promise === "undefined") {
		window.Promise = polyfill;
	} else if (!window.Promise.prototype.finally) {
		window.Promise.prototype.finally = polyfill.prototype.finally;
	}
	module.exports = window.Promise;
} else if (typeof commonjsGlobal !== "undefined") {
	if (typeof commonjsGlobal.Promise === "undefined") {
		commonjsGlobal.Promise = polyfill;
	} else if (!commonjsGlobal.Promise.prototype.finally) {
		commonjsGlobal.Promise.prototype.finally = polyfill.prototype.finally;
	}
	module.exports = commonjsGlobal.Promise;
} else {
	module.exports = polyfill;
}
});

var render = function($window) {
	var $doc = $window && $window.document;
	var currentRedraw;

	var nameSpace = {
		svg: "http://www.w3.org/2000/svg",
		math: "http://www.w3.org/1998/Math/MathML"
	};

	function getNameSpace(vnode) {
		return vnode.attrs && vnode.attrs.xmlns || nameSpace[vnode.tag]
	}

	//sanity check to discourage people from doing `vnode.state = ...`
	function checkState(vnode, original) {
		if (vnode.state !== original) throw new Error("`vnode.state` must not be modified")
	}

	//Note: the hook is passed as the `this` argument to allow proxying the
	//arguments without requiring a full array allocation to do so. It also
	//takes advantage of the fact the current `vnode` is the first argument in
	//all lifecycle methods.
	function callHook(vnode) {
		var original = vnode.state;
		try {
			return this.apply(original, arguments)
		} finally {
			checkState(vnode, original);
		}
	}

	// IE11 (at least) throws an UnspecifiedError when accessing document.activeElement when
	// inside an iframe. Catch and swallow this error, and heavy-handidly return null.
	function activeElement() {
		try {
			return $doc.activeElement
		} catch (e) {
			return null
		}
	}
	//create
	function createNodes(parent, vnodes, start, end, hooks, nextSibling, ns) {
		for (var i = start; i < end; i++) {
			var vnode = vnodes[i];
			if (vnode != null) {
				createNode(parent, vnode, hooks, ns, nextSibling);
			}
		}
	}
	function createNode(parent, vnode, hooks, ns, nextSibling) {
		var tag = vnode.tag;
		if (typeof tag === "string") {
			vnode.state = {};
			if (vnode.attrs != null) initLifecycle(vnode.attrs, vnode, hooks);
			switch (tag) {
				case "#": createText(parent, vnode, nextSibling); break
				case "<": createHTML(parent, vnode, ns, nextSibling); break
				case "[": createFragment(parent, vnode, hooks, ns, nextSibling); break
				default: createElement(parent, vnode, hooks, ns, nextSibling);
			}
		}
		else createComponent(parent, vnode, hooks, ns, nextSibling);
	}
	function createText(parent, vnode, nextSibling) {
		vnode.dom = $doc.createTextNode(vnode.children);
		insertNode(parent, vnode.dom, nextSibling);
	}
	var possibleParents = {caption: "table", thead: "table", tbody: "table", tfoot: "table", tr: "tbody", th: "tr", td: "tr", colgroup: "table", col: "colgroup"};
	function createHTML(parent, vnode, ns, nextSibling) {
		var match = vnode.children.match(/^\s*?<(\w+)/im) || [];
		// not using the proper parent makes the child element(s) vanish.
		//     var div = document.createElement("div")
		//     div.innerHTML = "<td>i</td><td>j</td>"
		//     console.log(div.innerHTML)
		// --> "ij", no <td> in sight.
		var temp = $doc.createElement(possibleParents[match[1]] || "div");
		if (ns === "http://www.w3.org/2000/svg") {
			temp.innerHTML = "<svg xmlns=\"http://www.w3.org/2000/svg\">" + vnode.children + "</svg>";
			temp = temp.firstChild;
		} else {
			temp.innerHTML = vnode.children;
		}
		vnode.dom = temp.firstChild;
		vnode.domSize = temp.childNodes.length;
		// Capture nodes to remove, so we don't confuse them.
		vnode.instance = [];
		var fragment = $doc.createDocumentFragment();
		var child;
		while (child = temp.firstChild) {
			vnode.instance.push(child);
			fragment.appendChild(child);
		}
		insertNode(parent, fragment, nextSibling);
	}
	function createFragment(parent, vnode, hooks, ns, nextSibling) {
		var fragment = $doc.createDocumentFragment();
		if (vnode.children != null) {
			var children = vnode.children;
			createNodes(fragment, children, 0, children.length, hooks, null, ns);
		}
		vnode.dom = fragment.firstChild;
		vnode.domSize = fragment.childNodes.length;
		insertNode(parent, fragment, nextSibling);
	}
	function createElement(parent, vnode$1, hooks, ns, nextSibling) {
		var tag = vnode$1.tag;
		var attrs = vnode$1.attrs;
		var is = attrs && attrs.is;

		ns = getNameSpace(vnode$1) || ns;

		var element = ns ?
			is ? $doc.createElementNS(ns, tag, {is: is}) : $doc.createElementNS(ns, tag) :
			is ? $doc.createElement(tag, {is: is}) : $doc.createElement(tag);
		vnode$1.dom = element;

		if (attrs != null) {
			setAttrs(vnode$1, attrs, ns);
		}

		insertNode(parent, element, nextSibling);

		if (!maybeSetContentEditable(vnode$1)) {
			if (vnode$1.text != null) {
				if (vnode$1.text !== "") element.textContent = vnode$1.text;
				else vnode$1.children = [vnode("#", undefined, undefined, vnode$1.text, undefined, undefined)];
			}
			if (vnode$1.children != null) {
				var children = vnode$1.children;
				createNodes(element, children, 0, children.length, hooks, null, ns);
				if (vnode$1.tag === "select" && attrs != null) setLateSelectAttrs(vnode$1, attrs);
			}
		}
	}
	function initComponent(vnode$1, hooks) {
		var sentinel;
		if (typeof vnode$1.tag.view === "function") {
			vnode$1.state = Object.create(vnode$1.tag);
			sentinel = vnode$1.state.view;
			if (sentinel.$$reentrantLock$$ != null) return
			sentinel.$$reentrantLock$$ = true;
		} else {
			vnode$1.state = void 0;
			sentinel = vnode$1.tag;
			if (sentinel.$$reentrantLock$$ != null) return
			sentinel.$$reentrantLock$$ = true;
			vnode$1.state = (vnode$1.tag.prototype != null && typeof vnode$1.tag.prototype.view === "function") ? new vnode$1.tag(vnode$1) : vnode$1.tag(vnode$1);
		}
		initLifecycle(vnode$1.state, vnode$1, hooks);
		if (vnode$1.attrs != null) initLifecycle(vnode$1.attrs, vnode$1, hooks);
		vnode$1.instance = vnode.normalize(callHook.call(vnode$1.state.view, vnode$1));
		if (vnode$1.instance === vnode$1) throw Error("A view cannot return the vnode it received as argument")
		sentinel.$$reentrantLock$$ = null;
	}
	function createComponent(parent, vnode, hooks, ns, nextSibling) {
		initComponent(vnode, hooks);
		if (vnode.instance != null) {
			createNode(parent, vnode.instance, hooks, ns, nextSibling);
			vnode.dom = vnode.instance.dom;
			vnode.domSize = vnode.dom != null ? vnode.instance.domSize : 0;
		}
		else {
			vnode.domSize = 0;
		}
	}

	//update
	/**
	 * @param {Element|Fragment} parent - the parent element
	 * @param {Vnode[] | null} old - the list of vnodes of the last `render()` call for
	 *                               this part of the tree
	 * @param {Vnode[] | null} vnodes - as above, but for the current `render()` call.
	 * @param {Function[]} hooks - an accumulator of post-render hooks (oncreate/onupdate)
	 * @param {Element | null} nextSibling - the next DOM node if we're dealing with a
	 *                                       fragment that is not the last item in its
	 *                                       parent
	 * @param {'svg' | 'math' | String | null} ns) - the current XML namespace, if any
	 * @returns void
	 */
	// This function diffs and patches lists of vnodes, both keyed and unkeyed.
	//
	// We will:
	//
	// 1. describe its general structure
	// 2. focus on the diff algorithm optimizations
	// 3. discuss DOM node operations.

	// ## Overview:
	//
	// The updateNodes() function:
	// - deals with trivial cases
	// - determines whether the lists are keyed or unkeyed based on the first non-null node
	//   of each list.
	// - diffs them and patches the DOM if needed (that's the brunt of the code)
	// - manages the leftovers: after diffing, are there:
	//   - old nodes left to remove?
	// 	 - new nodes to insert?
	// 	 deal with them!
	//
	// The lists are only iterated over once, with an exception for the nodes in `old` that
	// are visited in the fourth part of the diff and in the `removeNodes` loop.

	// ## Diffing
	//
	// Reading https://github.com/localvoid/ivi/blob/ddc09d06abaef45248e6133f7040d00d3c6be853/packages/ivi/src/vdom/implementation.ts#L617-L837
	// may be good for context on longest increasing subsequence-based logic for moving nodes.
	//
	// In order to diff keyed lists, one has to
	//
	// 1) match nodes in both lists, per key, and update them accordingly
	// 2) create the nodes present in the new list, but absent in the old one
	// 3) remove the nodes present in the old list, but absent in the new one
	// 4) figure out what nodes in 1) to move in order to minimize the DOM operations.
	//
	// To achieve 1) one can create a dictionary of keys => index (for the old list), then iterate
	// over the new list and for each new vnode, find the corresponding vnode in the old list using
	// the map.
	// 2) is achieved in the same step: if a new node has no corresponding entry in the map, it is new
	// and must be created.
	// For the removals, we actually remove the nodes that have been updated from the old list.
	// The nodes that remain in that list after 1) and 2) have been performed can be safely removed.
	// The fourth step is a bit more complex and relies on the longest increasing subsequence (LIS)
	// algorithm.
	//
	// the longest increasing subsequence is the list of nodes that can remain in place. Imagine going
	// from `1,2,3,4,5` to `4,5,1,2,3` where the numbers are not necessarily the keys, but the indices
	// corresponding to the keyed nodes in the old list (keyed nodes `e,d,c,b,a` => `b,a,e,d,c` would
	//  match the above lists, for example).
	//
	// In there are two increasing subsequences: `4,5` and `1,2,3`, the latter being the longest. We
	// can update those nodes without moving them, and only call `insertNode` on `4` and `5`.
	//
	// @localvoid adapted the algo to also support node deletions and insertions (the `lis` is actually
	// the longest increasing subsequence *of old nodes still present in the new list*).
	//
	// It is a general algorithm that is fireproof in all circumstances, but it requires the allocation
	// and the construction of a `key => oldIndex` map, and three arrays (one with `newIndex => oldIndex`,
	// the `LIS` and a temporary one to create the LIS).
	//
	// So we cheat where we can: if the tails of the lists are identical, they are guaranteed to be part of
	// the LIS and can be updated without moving them.
	//
	// If two nodes are swapped, they are guaranteed not to be part of the LIS, and must be moved (with
	// the exception of the last node if the list is fully reversed).
	//
	// ## Finding the next sibling.
	//
	// `updateNode()` and `createNode()` expect a nextSibling parameter to perform DOM operations.
	// When the list is being traversed top-down, at any index, the DOM nodes up to the previous
	// vnode reflect the content of the new list, whereas the rest of the DOM nodes reflect the old
	// list. The next sibling must be looked for in the old list using `getNextSibling(... oldStart + 1 ...)`.
	//
	// In the other scenarios (swaps, upwards traversal, map-based diff),
	// the new vnodes list is traversed upwards. The DOM nodes at the bottom of the list reflect the
	// bottom part of the new vnodes list, and we can use the `v.dom`  value of the previous node
	// as the next sibling (cached in the `nextSibling` variable).


	// ## DOM node moves
	//
	// In most scenarios `updateNode()` and `createNode()` perform the DOM operations. However,
	// this is not the case if the node moved (second and fourth part of the diff algo). We move
	// the old DOM nodes before updateNode runs because it enables us to use the cached `nextSibling`
	// variable rather than fetching it using `getNextSibling()`.
	//
	// The fourth part of the diff currently inserts nodes unconditionally, leading to issues
	// like #1791 and #1999. We need to be smarter about those situations where adjascent old
	// nodes remain together in the new list in a way that isn't covered by parts one and
	// three of the diff algo.

	function updateNodes(parent, old, vnodes, hooks, nextSibling, ns) {
		if (old === vnodes || old == null && vnodes == null) return
		else if (old == null || old.length === 0) createNodes(parent, vnodes, 0, vnodes.length, hooks, nextSibling, ns);
		else if (vnodes == null || vnodes.length === 0) removeNodes(parent, old, 0, old.length);
		else {
			var isOldKeyed = old[0] != null && old[0].key != null;
			var isKeyed = vnodes[0] != null && vnodes[0].key != null;
			var start = 0, oldStart = 0;
			if (!isOldKeyed) while (oldStart < old.length && old[oldStart] == null) oldStart++;
			if (!isKeyed) while (start < vnodes.length && vnodes[start] == null) start++;
			if (isKeyed === null && isOldKeyed == null) return // both lists are full of nulls
			if (isOldKeyed !== isKeyed) {
				removeNodes(parent, old, oldStart, old.length);
				createNodes(parent, vnodes, start, vnodes.length, hooks, nextSibling, ns);
			} else if (!isKeyed) {
				// Don't index past the end of either list (causes deopts).
				var commonLength = old.length < vnodes.length ? old.length : vnodes.length;
				// Rewind if necessary to the first non-null index on either side.
				// We could alternatively either explicitly create or remove nodes when `start !== oldStart`
				// but that would be optimizing for sparse lists which are more rare than dense ones.
				start = start < oldStart ? start : oldStart;
				for (; start < commonLength; start++) {
					o = old[start];
					v = vnodes[start];
					if (o === v || o == null && v == null) continue
					else if (o == null) createNode(parent, v, hooks, ns, getNextSibling(old, start + 1, nextSibling));
					else if (v == null) removeNode(parent, o);
					else updateNode(parent, o, v, hooks, getNextSibling(old, start + 1, nextSibling), ns);
				}
				if (old.length > commonLength) removeNodes(parent, old, start, old.length);
				if (vnodes.length > commonLength) createNodes(parent, vnodes, start, vnodes.length, hooks, nextSibling, ns);
			} else {
				// keyed diff
				var oldEnd = old.length - 1, end = vnodes.length - 1, map, o, v, oe, ve, topSibling;

				// bottom-up
				while (oldEnd >= oldStart && end >= start) {
					oe = old[oldEnd];
					ve = vnodes[end];
					if (oe.key !== ve.key) break
					if (oe !== ve) updateNode(parent, oe, ve, hooks, nextSibling, ns);
					if (ve.dom != null) nextSibling = ve.dom;
					oldEnd--, end--;
				}
				// top-down
				while (oldEnd >= oldStart && end >= start) {
					o = old[oldStart];
					v = vnodes[start];
					if (o.key !== v.key) break
					oldStart++, start++;
					if (o !== v) updateNode(parent, o, v, hooks, getNextSibling(old, oldStart, nextSibling), ns);
				}
				// swaps and list reversals
				while (oldEnd >= oldStart && end >= start) {
					if (start === end) break
					if (o.key !== ve.key || oe.key !== v.key) break
					topSibling = getNextSibling(old, oldStart, nextSibling);
					moveNodes(parent, oe, topSibling);
					if (oe !== v) updateNode(parent, oe, v, hooks, topSibling, ns);
					if (++start <= --end) moveNodes(parent, o, nextSibling);
					if (o !== ve) updateNode(parent, o, ve, hooks, nextSibling, ns);
					if (ve.dom != null) nextSibling = ve.dom;
					oldStart++; oldEnd--;
					oe = old[oldEnd];
					ve = vnodes[end];
					o = old[oldStart];
					v = vnodes[start];
				}
				// bottom up once again
				while (oldEnd >= oldStart && end >= start) {
					if (oe.key !== ve.key) break
					if (oe !== ve) updateNode(parent, oe, ve, hooks, nextSibling, ns);
					if (ve.dom != null) nextSibling = ve.dom;
					oldEnd--, end--;
					oe = old[oldEnd];
					ve = vnodes[end];
				}
				if (start > end) removeNodes(parent, old, oldStart, oldEnd + 1);
				else if (oldStart > oldEnd) createNodes(parent, vnodes, start, end + 1, hooks, nextSibling, ns);
				else {
					// inspired by ivi https://github.com/ivijs/ivi/ by Boris Kaul
					var originalNextSibling = nextSibling, vnodesLength = end - start + 1, oldIndices = new Array(vnodesLength), li=0, i=0, pos = 2147483647, matched = 0, map, lisIndices;
					for (i = 0; i < vnodesLength; i++) oldIndices[i] = -1;
					for (i = end; i >= start; i--) {
						if (map == null) map = getKeyMap(old, oldStart, oldEnd + 1);
						ve = vnodes[i];
						var oldIndex = map[ve.key];
						if (oldIndex != null) {
							pos = (oldIndex < pos) ? oldIndex : -1; // becomes -1 if nodes were re-ordered
							oldIndices[i-start] = oldIndex;
							oe = old[oldIndex];
							old[oldIndex] = null;
							if (oe !== ve) updateNode(parent, oe, ve, hooks, nextSibling, ns);
							if (ve.dom != null) nextSibling = ve.dom;
							matched++;
						}
					}
					nextSibling = originalNextSibling;
					if (matched !== oldEnd - oldStart + 1) removeNodes(parent, old, oldStart, oldEnd + 1);
					if (matched === 0) createNodes(parent, vnodes, start, end + 1, hooks, nextSibling, ns);
					else {
						if (pos === -1) {
							// the indices of the indices of the items that are part of the
							// longest increasing subsequence in the oldIndices list
							lisIndices = makeLisIndices(oldIndices);
							li = lisIndices.length - 1;
							for (i = end; i >= start; i--) {
								v = vnodes[i];
								if (oldIndices[i-start] === -1) createNode(parent, v, hooks, ns, nextSibling);
								else {
									if (lisIndices[li] === i - start) li--;
									else moveNodes(parent, v, nextSibling);
								}
								if (v.dom != null) nextSibling = vnodes[i].dom;
							}
						} else {
							for (i = end; i >= start; i--) {
								v = vnodes[i];
								if (oldIndices[i-start] === -1) createNode(parent, v, hooks, ns, nextSibling);
								if (v.dom != null) nextSibling = vnodes[i].dom;
							}
						}
					}
				}
			}
		}
	}
	function updateNode(parent, old, vnode, hooks, nextSibling, ns) {
		var oldTag = old.tag, tag = vnode.tag;
		if (oldTag === tag) {
			vnode.state = old.state;
			vnode.events = old.events;
			if (shouldNotUpdate(vnode, old)) return
			if (typeof oldTag === "string") {
				if (vnode.attrs != null) {
					updateLifecycle(vnode.attrs, vnode, hooks);
				}
				switch (oldTag) {
					case "#": updateText(old, vnode); break
					case "<": updateHTML(parent, old, vnode, ns, nextSibling); break
					case "[": updateFragment(parent, old, vnode, hooks, nextSibling, ns); break
					default: updateElement(old, vnode, hooks, ns);
				}
			}
			else updateComponent(parent, old, vnode, hooks, nextSibling, ns);
		}
		else {
			removeNode(parent, old);
			createNode(parent, vnode, hooks, ns, nextSibling);
		}
	}
	function updateText(old, vnode) {
		if (old.children.toString() !== vnode.children.toString()) {
			old.dom.nodeValue = vnode.children;
		}
		vnode.dom = old.dom;
	}
	function updateHTML(parent, old, vnode, ns, nextSibling) {
		if (old.children !== vnode.children) {
			removeHTML(parent, old);
			createHTML(parent, vnode, ns, nextSibling);
		}
		else {
			vnode.dom = old.dom;
			vnode.domSize = old.domSize;
			vnode.instance = old.instance;
		}
	}
	function updateFragment(parent, old, vnode, hooks, nextSibling, ns) {
		updateNodes(parent, old.children, vnode.children, hooks, nextSibling, ns);
		var domSize = 0, children = vnode.children;
		vnode.dom = null;
		if (children != null) {
			for (var i = 0; i < children.length; i++) {
				var child = children[i];
				if (child != null && child.dom != null) {
					if (vnode.dom == null) vnode.dom = child.dom;
					domSize += child.domSize || 1;
				}
			}
			if (domSize !== 1) vnode.domSize = domSize;
		}
	}
	function updateElement(old, vnode$1, hooks, ns) {
		var element = vnode$1.dom = old.dom;
		ns = getNameSpace(vnode$1) || ns;

		if (vnode$1.tag === "textarea") {
			if (vnode$1.attrs == null) vnode$1.attrs = {};
			if (vnode$1.text != null) {
				vnode$1.attrs.value = vnode$1.text; //FIXME handle multiple children
				vnode$1.text = undefined;
			}
		}
		updateAttrs(vnode$1, old.attrs, vnode$1.attrs, ns);
		if (!maybeSetContentEditable(vnode$1)) {
			if (old.text != null && vnode$1.text != null && vnode$1.text !== "") {
				if (old.text.toString() !== vnode$1.text.toString()) old.dom.firstChild.nodeValue = vnode$1.text;
			}
			else {
				if (old.text != null) old.children = [vnode("#", undefined, undefined, old.text, undefined, old.dom.firstChild)];
				if (vnode$1.text != null) vnode$1.children = [vnode("#", undefined, undefined, vnode$1.text, undefined, undefined)];
				updateNodes(element, old.children, vnode$1.children, hooks, null, ns);
			}
		}
	}
	function updateComponent(parent, old, vnode$1, hooks, nextSibling, ns) {
		vnode$1.instance = vnode.normalize(callHook.call(vnode$1.state.view, vnode$1));
		if (vnode$1.instance === vnode$1) throw Error("A view cannot return the vnode it received as argument")
		updateLifecycle(vnode$1.state, vnode$1, hooks);
		if (vnode$1.attrs != null) updateLifecycle(vnode$1.attrs, vnode$1, hooks);
		if (vnode$1.instance != null) {
			if (old.instance == null) createNode(parent, vnode$1.instance, hooks, ns, nextSibling);
			else updateNode(parent, old.instance, vnode$1.instance, hooks, nextSibling, ns);
			vnode$1.dom = vnode$1.instance.dom;
			vnode$1.domSize = vnode$1.instance.domSize;
		}
		else if (old.instance != null) {
			removeNode(parent, old.instance);
			vnode$1.dom = undefined;
			vnode$1.domSize = 0;
		}
		else {
			vnode$1.dom = old.dom;
			vnode$1.domSize = old.domSize;
		}
	}
	function getKeyMap(vnodes, start, end) {
		var map = Object.create(null);
		for (; start < end; start++) {
			var vnode = vnodes[start];
			if (vnode != null) {
				var key = vnode.key;
				if (key != null) map[key] = start;
			}
		}
		return map
	}
	// Lifted from ivi https://github.com/ivijs/ivi/
	// takes a list of unique numbers (-1 is special and can
	// occur multiple times) and returns an array with the indices
	// of the items that are part of the longest increasing
	// subsequece
	var lisTemp = [];
	function makeLisIndices(a) {
		var result = [0];
		var u = 0, v = 0, i = 0;
		var il = lisTemp.length = a.length;
		for (var i = 0; i < il; i++) lisTemp[i] = a[i];
		for (var i = 0; i < il; ++i) {
			if (a[i] === -1) continue
			var j = result[result.length - 1];
			if (a[j] < a[i]) {
				lisTemp[i] = j;
				result.push(i);
				continue
			}
			u = 0;
			v = result.length - 1;
			while (u < v) {
				// Fast integer average without overflow.
				// eslint-disable-next-line no-bitwise
				var c = (u >>> 1) + (v >>> 1) + (u & v & 1);
				if (a[result[c]] < a[i]) {
					u = c + 1;
				}
				else {
					v = c;
				}
			}
			if (a[i] < a[result[u]]) {
				if (u > 0) lisTemp[i] = result[u - 1];
				result[u] = i;
			}
		}
		u = result.length;
		v = result[u - 1];
		while (u-- > 0) {
			result[u] = v;
			v = lisTemp[v];
		}
		lisTemp.length = 0;
		return result
	}

	function getNextSibling(vnodes, i, nextSibling) {
		for (; i < vnodes.length; i++) {
			if (vnodes[i] != null && vnodes[i].dom != null) return vnodes[i].dom
		}
		return nextSibling
	}

	// This covers a really specific edge case:
	// - Parent node is keyed and contains child
	// - Child is removed, returns unresolved promise in `onbeforeremove`
	// - Parent node is moved in keyed diff
	// - Remaining children still need moved appropriately
	//
	// Ideally, I'd track removed nodes as well, but that introduces a lot more
	// complexity and I'm not exactly interested in doing that.
	function moveNodes(parent, vnode, nextSibling) {
		var frag = $doc.createDocumentFragment();
		moveChildToFrag(parent, frag, vnode);
		insertNode(parent, frag, nextSibling);
	}
	function moveChildToFrag(parent, frag, vnode) {
		// Dodge the recursion overhead in a few of the most common cases.
		while (vnode.dom != null && vnode.dom.parentNode === parent) {
			if (typeof vnode.tag !== "string") {
				vnode = vnode.instance;
				if (vnode != null) continue
			} else if (vnode.tag === "<") {
				for (var i = 0; i < vnode.instance.length; i++) {
					frag.appendChild(vnode.instance[i]);
				}
			} else if (vnode.tag !== "[") {
				// Don't recurse for text nodes *or* elements, just fragments
				frag.appendChild(vnode.dom);
			} else if (vnode.children.length === 1) {
				vnode = vnode.children[0];
				if (vnode != null) continue
			} else {
				for (var i = 0; i < vnode.children.length; i++) {
					var child = vnode.children[i];
					if (child != null) moveChildToFrag(parent, frag, child);
				}
			}
			break
		}
	}

	function insertNode(parent, dom, nextSibling) {
		if (nextSibling != null) parent.insertBefore(dom, nextSibling);
		else parent.appendChild(dom);
	}

	function maybeSetContentEditable(vnode) {
		if (vnode.attrs == null || (
			vnode.attrs.contenteditable == null && // attribute
			vnode.attrs.contentEditable == null // property
		)) return false
		var children = vnode.children;
		if (children != null && children.length === 1 && children[0].tag === "<") {
			var content = children[0].children;
			if (vnode.dom.innerHTML !== content) vnode.dom.innerHTML = content;
		}
		else if (vnode.text != null || children != null && children.length !== 0) throw new Error("Child node of a contenteditable must be trusted")
		return true
	}

	//remove
	function removeNodes(parent, vnodes, start, end) {
		for (var i = start; i < end; i++) {
			var vnode = vnodes[i];
			if (vnode != null) removeNode(parent, vnode);
		}
	}
	function removeNode(parent, vnode) {
		var mask = 0;
		var original = vnode.state;
		var stateResult, attrsResult;
		if (typeof vnode.tag !== "string" && typeof vnode.state.onbeforeremove === "function") {
			var result = callHook.call(vnode.state.onbeforeremove, vnode);
			if (result != null && typeof result.then === "function") {
				mask = 1;
				stateResult = result;
			}
		}
		if (vnode.attrs && typeof vnode.attrs.onbeforeremove === "function") {
			var result = callHook.call(vnode.attrs.onbeforeremove, vnode);
			if (result != null && typeof result.then === "function") {
				// eslint-disable-next-line no-bitwise
				mask |= 2;
				attrsResult = result;
			}
		}
		checkState(vnode, original);

		// If we can, try to fast-path it and avoid all the overhead of awaiting
		if (!mask) {
			onremove(vnode);
			removeChild(parent, vnode);
		} else {
			if (stateResult != null) {
				var next = function () {
					// eslint-disable-next-line no-bitwise
					if (mask & 1) { mask &= 2; if (!mask) reallyRemove(); }
				};
				stateResult.then(next, next);
			}
			if (attrsResult != null) {
				var next = function () {
					// eslint-disable-next-line no-bitwise
					if (mask & 2) { mask &= 1; if (!mask) reallyRemove(); }
				};
				attrsResult.then(next, next);
			}
		}

		function reallyRemove() {
			checkState(vnode, original);
			onremove(vnode);
			removeChild(parent, vnode);
		}
	}
	function removeHTML(parent, vnode) {
		for (var i = 0; i < vnode.instance.length; i++) {
			parent.removeChild(vnode.instance[i]);
		}
	}
	function removeChild(parent, vnode) {
		// Dodge the recursion overhead in a few of the most common cases.
		while (vnode.dom != null && vnode.dom.parentNode === parent) {
			if (typeof vnode.tag !== "string") {
				vnode = vnode.instance;
				if (vnode != null) continue
			} else if (vnode.tag === "<") {
				removeHTML(parent, vnode);
			} else {
				if (vnode.tag !== "[") {
					parent.removeChild(vnode.dom);
					if (!Array.isArray(vnode.children)) break
				}
				if (vnode.children.length === 1) {
					vnode = vnode.children[0];
					if (vnode != null) continue
				} else {
					for (var i = 0; i < vnode.children.length; i++) {
						var child = vnode.children[i];
						if (child != null) removeChild(parent, child);
					}
				}
			}
			break
		}
	}
	function onremove(vnode) {
		if (typeof vnode.tag !== "string" && typeof vnode.state.onremove === "function") callHook.call(vnode.state.onremove, vnode);
		if (vnode.attrs && typeof vnode.attrs.onremove === "function") callHook.call(vnode.attrs.onremove, vnode);
		if (typeof vnode.tag !== "string") {
			if (vnode.instance != null) onremove(vnode.instance);
		} else {
			var children = vnode.children;
			if (Array.isArray(children)) {
				for (var i = 0; i < children.length; i++) {
					var child = children[i];
					if (child != null) onremove(child);
				}
			}
		}
	}

	//attrs
	function setAttrs(vnode, attrs, ns) {
		for (var key in attrs) {
			setAttr(vnode, key, null, attrs[key], ns);
		}
	}
	function setAttr(vnode, key, old, value, ns) {
		if (key === "key" || key === "is" || value == null || isLifecycleMethod(key) || (old === value && !isFormAttribute(vnode, key)) && typeof value !== "object") return
		if (key[0] === "o" && key[1] === "n") return updateEvent(vnode, key, value)
		if (key.slice(0, 6) === "xlink:") vnode.dom.setAttributeNS("http://www.w3.org/1999/xlink", key.slice(6), value);
		else if (key === "style") updateStyle(vnode.dom, old, value);
		else if (hasPropertyKey(vnode, key, ns)) {
			if (key === "value") {
				// Only do the coercion if we're actually going to check the value.
				/* eslint-disable no-implicit-coercion */
				//setting input[value] to same value by typing on focused element moves cursor to end in Chrome
				if ((vnode.tag === "input" || vnode.tag === "textarea") && vnode.dom.value === "" + value && vnode.dom === activeElement()) return
				//setting select[value] to same value while having select open blinks select dropdown in Chrome
				if (vnode.tag === "select" && old !== null && vnode.dom.value === "" + value) return
				//setting option[value] to same value while having select open blinks select dropdown in Chrome
				if (vnode.tag === "option" && old !== null && vnode.dom.value === "" + value) return
				/* eslint-enable no-implicit-coercion */
			}
			// If you assign an input type that is not supported by IE 11 with an assignment expression, an error will occur.
			if (vnode.tag === "input" && key === "type") vnode.dom.setAttribute(key, value);
			else vnode.dom[key] = value;
		} else {
			if (typeof value === "boolean") {
				if (value) vnode.dom.setAttribute(key, "");
				else vnode.dom.removeAttribute(key);
			}
			else vnode.dom.setAttribute(key === "className" ? "class" : key, value);
		}
	}
	function removeAttr(vnode, key, old, ns) {
		if (key === "key" || key === "is" || old == null || isLifecycleMethod(key)) return
		if (key[0] === "o" && key[1] === "n" && !isLifecycleMethod(key)) updateEvent(vnode, key, undefined);
		else if (key === "style") updateStyle(vnode.dom, old, null);
		else if (
			hasPropertyKey(vnode, key, ns)
			&& key !== "className"
			&& !(key === "value" && (
				vnode.tag === "option"
				|| vnode.tag === "select" && vnode.dom.selectedIndex === -1 && vnode.dom === activeElement()
			))
			&& !(vnode.tag === "input" && key === "type")
		) {
			vnode.dom[key] = null;
		} else {
			var nsLastIndex = key.indexOf(":");
			if (nsLastIndex !== -1) key = key.slice(nsLastIndex + 1);
			if (old !== false) vnode.dom.removeAttribute(key === "className" ? "class" : key);
		}
	}
	function setLateSelectAttrs(vnode, attrs) {
		if ("value" in attrs) {
			if(attrs.value === null) {
				if (vnode.dom.selectedIndex !== -1) vnode.dom.value = null;
			} else {
				var normalized = "" + attrs.value; // eslint-disable-line no-implicit-coercion
				if (vnode.dom.value !== normalized || vnode.dom.selectedIndex === -1) {
					vnode.dom.value = normalized;
				}
			}
		}
		if ("selectedIndex" in attrs) setAttr(vnode, "selectedIndex", null, attrs.selectedIndex, undefined);
	}
	function updateAttrs(vnode, old, attrs, ns) {
		if (attrs != null) {
			for (var key in attrs) {
				setAttr(vnode, key, old && old[key], attrs[key], ns);
			}
		}
		var val;
		if (old != null) {
			for (var key in old) {
				if (((val = old[key]) != null) && (attrs == null || attrs[key] == null)) {
					removeAttr(vnode, key, val, ns);
				}
			}
		}
	}
	function isFormAttribute(vnode, attr) {
		return attr === "value" || attr === "checked" || attr === "selectedIndex" || attr === "selected" && vnode.dom === activeElement() || vnode.tag === "option" && vnode.dom.parentNode === $doc.activeElement
	}
	function isLifecycleMethod(attr) {
		return attr === "oninit" || attr === "oncreate" || attr === "onupdate" || attr === "onremove" || attr === "onbeforeremove" || attr === "onbeforeupdate"
	}
	function hasPropertyKey(vnode, key, ns) {
		// Filter out namespaced keys
		return ns === undefined && (
			// If it's a custom element, just keep it.
			vnode.tag.indexOf("-") > -1 || vnode.attrs != null && vnode.attrs.is ||
			// If it's a normal element, let's try to avoid a few browser bugs.
			key !== "href" && key !== "list" && key !== "form" && key !== "width" && key !== "height"// && key !== "type"
			// Defer the property check until *after* we check everything.
		) && key in vnode.dom
	}

	//style
	var uppercaseRegex = /[A-Z]/g;
	function toLowerCase(capital) { return "-" + capital.toLowerCase() }
	function normalizeKey(key) {
		return key[0] === "-" && key[1] === "-" ? key :
			key === "cssFloat" ? "float" :
				key.replace(uppercaseRegex, toLowerCase)
	}
	function updateStyle(element, old, style) {
		if (old === style) ; else if (style == null) {
			// New style is missing, just clear it.
			element.style.cssText = "";
		} else if (typeof style !== "object") {
			// New style is a string, let engine deal with patching.
			element.style.cssText = style;
		} else if (old == null || typeof old !== "object") {
			// `old` is missing or a string, `style` is an object.
			element.style.cssText = "";
			// Add new style properties
			for (var key in style) {
				var value = style[key];
				if (value != null) element.style.setProperty(normalizeKey(key), String(value));
			}
		} else {
			// Both old & new are (different) objects.
			// Update style properties that have changed
			for (var key in style) {
				var value = style[key];
				if (value != null && (value = String(value)) !== String(old[key])) {
					element.style.setProperty(normalizeKey(key), value);
				}
			}
			// Remove style properties that no longer exist
			for (var key in old) {
				if (old[key] != null && style[key] == null) {
					element.style.removeProperty(normalizeKey(key));
				}
			}
		}
	}

	// Here's an explanation of how this works:
	// 1. The event names are always (by design) prefixed by `on`.
	// 2. The EventListener interface accepts either a function or an object
	//    with a `handleEvent` method.
	// 3. The object does not inherit from `Object.prototype`, to avoid
	//    any potential interference with that (e.g. setters).
	// 4. The event name is remapped to the handler before calling it.
	// 5. In function-based event handlers, `ev.target === this`. We replicate
	//    that below.
	// 6. In function-based event handlers, `return false` prevents the default
	//    action and stops event propagation. We replicate that below.
	function EventDict() {
		// Save this, so the current redraw is correctly tracked.
		this._ = currentRedraw;
	}
	EventDict.prototype = Object.create(null);
	EventDict.prototype.handleEvent = function (ev) {
		var handler = this["on" + ev.type];
		var result;
		if (typeof handler === "function") result = handler.call(ev.currentTarget, ev);
		else if (typeof handler.handleEvent === "function") handler.handleEvent(ev);
		if (this._ && ev.redraw !== false) (0, this._)();
		if (result === false) {
			ev.preventDefault();
			ev.stopPropagation();
		}
	};

	//event
	function updateEvent(vnode, key, value) {
		if (vnode.events != null) {
			if (vnode.events[key] === value) return
			if (value != null && (typeof value === "function" || typeof value === "object")) {
				if (vnode.events[key] == null) vnode.dom.addEventListener(key.slice(2), vnode.events, false);
				vnode.events[key] = value;
			} else {
				if (vnode.events[key] != null) vnode.dom.removeEventListener(key.slice(2), vnode.events, false);
				vnode.events[key] = undefined;
			}
		} else if (value != null && (typeof value === "function" || typeof value === "object")) {
			vnode.events = new EventDict();
			vnode.dom.addEventListener(key.slice(2), vnode.events, false);
			vnode.events[key] = value;
		}
	}

	//lifecycle
	function initLifecycle(source, vnode, hooks) {
		if (typeof source.oninit === "function") callHook.call(source.oninit, vnode);
		if (typeof source.oncreate === "function") hooks.push(callHook.bind(source.oncreate, vnode));
	}
	function updateLifecycle(source, vnode, hooks) {
		if (typeof source.onupdate === "function") hooks.push(callHook.bind(source.onupdate, vnode));
	}
	function shouldNotUpdate(vnode, old) {
		do {
			if (vnode.attrs != null && typeof vnode.attrs.onbeforeupdate === "function") {
				var force = callHook.call(vnode.attrs.onbeforeupdate, vnode, old);
				if (force !== undefined && !force) break
			}
			if (typeof vnode.tag !== "string" && typeof vnode.state.onbeforeupdate === "function") {
				var force = callHook.call(vnode.state.onbeforeupdate, vnode, old);
				if (force !== undefined && !force) break
			}
			return false
		} while (false); // eslint-disable-line no-constant-condition
		vnode.dom = old.dom;
		vnode.domSize = old.domSize;
		vnode.instance = old.instance;
		// One would think having the actual latest attributes would be ideal,
		// but it doesn't let us properly diff based on our current internal
		// representation. We have to save not only the old DOM info, but also
		// the attributes used to create it, as we diff *that*, not against the
		// DOM directly (with a few exceptions in `setAttr`). And, of course, we
		// need to save the children and text as they are conceptually not
		// unlike special "attributes" internally.
		vnode.attrs = old.attrs;
		vnode.children = old.children;
		vnode.text = old.text;
		return true
	}

	return function(dom, vnodes, redraw) {
		if (!dom) throw new TypeError("Ensure the DOM element being passed to m.route/m.mount/m.render is not undefined.")
		var hooks = [];
		var active = activeElement();
		var namespace = dom.namespaceURI;

		// First time rendering into a node clears it out
		if (dom.vnodes == null) dom.textContent = "";

		vnodes = vnode.normalizeChildren(Array.isArray(vnodes) ? vnodes : [vnodes]);
		var prevRedraw = currentRedraw;
		try {
			currentRedraw = typeof redraw === "function" ? redraw : undefined;
			updateNodes(dom, dom.vnodes, vnodes, hooks, null, namespace === "http://www.w3.org/1999/xhtml" ? undefined : namespace);
		} finally {
			currentRedraw = prevRedraw;
		}
		dom.vnodes = vnodes;
		// `document.activeElement` can return null: https://html.spec.whatwg.org/multipage/interaction.html#dom-document-activeelement
		if (active != null && activeElement() !== active && typeof active.focus === "function") active.focus();
		for (var i = 0; i < hooks.length; i++) hooks[i]();
	}
};

var render$1 = render(window);

var mountRedraw = function(render, schedule, console) {
	var subscriptions = [];
	var rendering = false;
	var pending = false;

	function sync() {
		if (rendering) throw new Error("Nested m.redraw.sync() call")
		rendering = true;
		for (var i = 0; i < subscriptions.length; i += 2) {
			try { render(subscriptions[i], vnode(subscriptions[i + 1]), redraw); }
			catch (e) { console.error(e); }
		}
		rendering = false;
	}

	function redraw() {
		if (!pending) {
			pending = true;
			schedule(function() {
				pending = false;
				sync();
			});
		}
	}

	redraw.sync = sync;

	function mount(root, component) {
		if (component != null && component.view == null && typeof component !== "function") {
			throw new TypeError("m.mount(element, component) expects a component, not a vnode")
		}

		var index = subscriptions.indexOf(root);
		if (index >= 0) {
			subscriptions.splice(index, 2);
			render(root, [], redraw);
		}

		if (component != null) {
			subscriptions.push(root, component);
			render(root, vnode(component), redraw);
		}
	}

	return {mount: mount, redraw: redraw}
};

var mountRedraw$1 = mountRedraw(render$1, requestAnimationFrame, console);

var build = function(object) {
	if (Object.prototype.toString.call(object) !== "[object Object]") return ""

	var args = [];
	for (var key in object) {
		destructure(key, object[key]);
	}

	return args.join("&")

	function destructure(key, value) {
		if (Array.isArray(value)) {
			for (var i = 0; i < value.length; i++) {
				destructure(key + "[" + i + "]", value[i]);
			}
		}
		else if (Object.prototype.toString.call(value) === "[object Object]") {
			for (var i in value) {
				destructure(key + "[" + i + "]", value[i]);
			}
		}
		else args.push(encodeURIComponent(key) + (value != null && value !== "" ? "=" + encodeURIComponent(value) : ""));
	}
};

var assign = Object.assign || function(target, source) {
	if(source) Object.keys(source).forEach(function(key) { target[key] = source[key]; });
};

// Returns `path` from `template` + `params`
var build$1 = function(template, params) {
	if ((/:([^\/\.-]+)(\.{3})?:/).test(template)) {
		throw new SyntaxError("Template parameter names *must* be separated")
	}
	if (params == null) return template
	var queryIndex = template.indexOf("?");
	var hashIndex = template.indexOf("#");
	var queryEnd = hashIndex < 0 ? template.length : hashIndex;
	var pathEnd = queryIndex < 0 ? queryEnd : queryIndex;
	var path = template.slice(0, pathEnd);
	var query = {};

	assign(query, params);

	var resolved = path.replace(/:([^\/\.-]+)(\.{3})?/g, function(m, key, variadic) {
		delete query[key];
		// If no such parameter exists, don't interpolate it.
		if (params[key] == null) return m
		// Escape normal parameters, but not variadic ones.
		return variadic ? params[key] : encodeURIComponent(String(params[key]))
	});

	// In case the template substitution adds new query/hash parameters.
	var newQueryIndex = resolved.indexOf("?");
	var newHashIndex = resolved.indexOf("#");
	var newQueryEnd = newHashIndex < 0 ? resolved.length : newHashIndex;
	var newPathEnd = newQueryIndex < 0 ? newQueryEnd : newQueryIndex;
	var result = resolved.slice(0, newPathEnd);

	if (queryIndex >= 0) result += template.slice(queryIndex, queryEnd);
	if (newQueryIndex >= 0) result += (queryIndex < 0 ? "?" : "&") + resolved.slice(newQueryIndex, newQueryEnd);
	var querystring = build(query);
	if (querystring) result += (queryIndex < 0 && newQueryIndex < 0 ? "?" : "&") + querystring;
	if (hashIndex >= 0) result += template.slice(hashIndex);
	if (newHashIndex >= 0) result += (hashIndex < 0 ? "" : "&") + resolved.slice(newHashIndex);
	return result
};

var request = function($window, Promise, oncompletion) {
	var callbackCount = 0;

	function PromiseProxy(executor) {
		return new Promise(executor)
	}

	// In case the global Promise is some userland library's where they rely on
	// `foo instanceof this.constructor`, `this.constructor.resolve(value)`, or
	// similar. Let's *not* break them.
	PromiseProxy.prototype = Promise.prototype;
	PromiseProxy.__proto__ = Promise; // eslint-disable-line no-proto

	function makeRequest(factory) {
		return function(url, args) {
			if (typeof url !== "string") { args = url; url = url.url; }
			else if (args == null) args = {};
			var promise = new Promise(function(resolve, reject) {
				factory(build$1(url, args.params), args, function (data) {
					if (typeof args.type === "function") {
						if (Array.isArray(data)) {
							for (var i = 0; i < data.length; i++) {
								data[i] = new args.type(data[i]);
							}
						}
						else data = new args.type(data);
					}
					resolve(data);
				}, reject);
			});
			if (args.background === true) return promise
			var count = 0;
			function complete() {
				if (--count === 0 && typeof oncompletion === "function") oncompletion();
			}

			return wrap(promise)

			function wrap(promise) {
				var then = promise.then;
				// Set the constructor, so engines know to not await or resolve
				// this as a native promise. At the time of writing, this is
				// only necessary for V8, but their behavior is the correct
				// behavior per spec. See this spec issue for more details:
				// https://github.com/tc39/ecma262/issues/1577. Also, see the
				// corresponding comment in `request/tests/test-request.js` for
				// a bit more background on the issue at hand.
				promise.constructor = PromiseProxy;
				promise.then = function() {
					count++;
					var next = then.apply(promise, arguments);
					next.then(complete, function(e) {
						complete();
						if (count === 0) throw e
					});
					return wrap(next)
				};
				return promise
			}
		}
	}

	function hasHeader(args, name) {
		for (var key in args.headers) {
			if ({}.hasOwnProperty.call(args.headers, key) && name.test(key)) return true
		}
		return false
	}

	return {
		request: makeRequest(function(url, args, resolve, reject) {
			var method = args.method != null ? args.method.toUpperCase() : "GET";
			var body = args.body;
			var assumeJSON = (args.serialize == null || args.serialize === JSON.serialize) && !(body instanceof $window.FormData);
			var responseType = args.responseType || (typeof args.extract === "function" ? "" : "json");

			var xhr = new $window.XMLHttpRequest(), aborted = false;
			var original = xhr, replacedAbort;
			var abort = xhr.abort;

			xhr.abort = function() {
				aborted = true;
				abort.call(this);
			};

			xhr.open(method, url, args.async !== false, typeof args.user === "string" ? args.user : undefined, typeof args.password === "string" ? args.password : undefined);

			if (assumeJSON && body != null && !hasHeader(args, /^content-type$/i)) {
				xhr.setRequestHeader("Content-Type", "application/json; charset=utf-8");
			}
			if (typeof args.deserialize !== "function" && !hasHeader(args, /^accept$/i)) {
				xhr.setRequestHeader("Accept", "application/json, text/*");
			}
			if (args.withCredentials) xhr.withCredentials = args.withCredentials;
			if (args.timeout) xhr.timeout = args.timeout;
			xhr.responseType = responseType;

			for (var key in args.headers) {
				if ({}.hasOwnProperty.call(args.headers, key)) {
					xhr.setRequestHeader(key, args.headers[key]);
				}
			}

			xhr.onreadystatechange = function(ev) {
				// Don't throw errors on xhr.abort().
				if (aborted) return

				if (ev.target.readyState === 4) {
					try {
						var success = (ev.target.status >= 200 && ev.target.status < 300) || ev.target.status === 304 || (/^file:\/\//i).test(url);
						// When the response type isn't "" or "text",
						// `xhr.responseText` is the wrong thing to use.
						// Browsers do the right thing and throw here, and we
						// should honor that and do the right thing by
						// preferring `xhr.response` where possible/practical.
						var response = ev.target.response, message;

						if (responseType === "json") {
							// For IE and Edge, which don't implement
							// `responseType: "json"`.
							if (!ev.target.responseType && typeof args.extract !== "function") response = JSON.parse(ev.target.responseText);
						} else if (!responseType || responseType === "text") {
							// Only use this default if it's text. If a parsed
							// document is needed on old IE and friends (all
							// unsupported), the user should use a custom
							// `config` instead. They're already using this at
							// their own risk.
							if (response == null) response = ev.target.responseText;
						}

						if (typeof args.extract === "function") {
							response = args.extract(ev.target, args);
							success = true;
						} else if (typeof args.deserialize === "function") {
							response = args.deserialize(response);
						}
						if (success) resolve(response);
						else {
							try { message = ev.target.responseText; }
							catch (e) { message = response; }
							var error = new Error(message);
							error.code = ev.target.status;
							error.response = response;
							reject(error);
						}
					}
					catch (e) {
						reject(e);
					}
				}
			};

			if (typeof args.config === "function") {
				xhr = args.config(xhr, args, url) || xhr;

				// Propagate the `abort` to any replacement XHR as well.
				if (xhr !== original) {
					replacedAbort = xhr.abort;
					xhr.abort = function() {
						aborted = true;
						replacedAbort.call(this);
					};
				}
			}

			if (body == null) xhr.send();
			else if (typeof args.serialize === "function") xhr.send(args.serialize(body));
			else if (body instanceof $window.FormData) xhr.send(body);
			else xhr.send(JSON.stringify(body));
		}),
		jsonp: makeRequest(function(url, args, resolve, reject) {
			var callbackName = args.callbackName || "_mithril_" + Math.round(Math.random() * 1e16) + "_" + callbackCount++;
			var script = $window.document.createElement("script");
			$window[callbackName] = function(data) {
				delete $window[callbackName];
				script.parentNode.removeChild(script);
				resolve(data);
			};
			script.onerror = function() {
				delete $window[callbackName];
				script.parentNode.removeChild(script);
				reject(new Error("JSONP request failed"));
			};
			script.src = url + (url.indexOf("?") < 0 ? "?" : "&") +
				encodeURIComponent(args.callbackKey || "callback") + "=" +
				encodeURIComponent(callbackName);
			$window.document.documentElement.appendChild(script);
		}),
	}
};

var request$1 = request(window, promise, mountRedraw$1.redraw);

var parse = function(string) {
	if (string === "" || string == null) return {}
	if (string.charAt(0) === "?") string = string.slice(1);

	var entries = string.split("&"), counters = {}, data = {};
	for (var i = 0; i < entries.length; i++) {
		var entry = entries[i].split("=");
		var key = decodeURIComponent(entry[0]);
		var value = entry.length === 2 ? decodeURIComponent(entry[1]) : "";

		if (value === "true") value = true;
		else if (value === "false") value = false;

		var levels = key.split(/\]\[?|\[/);
		var cursor = data;
		if (key.indexOf("[") > -1) levels.pop();
		for (var j = 0; j < levels.length; j++) {
			var level = levels[j], nextLevel = levels[j + 1];
			var isNumber = nextLevel == "" || !isNaN(parseInt(nextLevel, 10));
			if (level === "") {
				var key = levels.slice(0, j).join();
				if (counters[key] == null) {
					counters[key] = Array.isArray(cursor) ? cursor.length : 0;
				}
				level = counters[key]++;
			}
			// Disallow direct prototype pollution
			else if (level === "__proto__") break
			if (j === levels.length - 1) cursor[level] = value;
			else {
				// Read own properties exclusively to disallow indirect
				// prototype pollution
				var desc = Object.getOwnPropertyDescriptor(cursor, level);
				if (desc != null) desc = desc.value;
				if (desc == null) cursor[level] = desc = isNumber ? [] : {};
				cursor = desc;
			}
		}
	}
	return data
};

// Returns `{path, params}` from `url`
var parse$1 = function(url) {
	var queryIndex = url.indexOf("?");
	var hashIndex = url.indexOf("#");
	var queryEnd = hashIndex < 0 ? url.length : hashIndex;
	var pathEnd = queryIndex < 0 ? queryEnd : queryIndex;
	var path = url.slice(0, pathEnd).replace(/\/{2,}/g, "/");

	if (!path) path = "/";
	else {
		if (path[0] !== "/") path = "/" + path;
		if (path.length > 1 && path[path.length - 1] === "/") path = path.slice(0, -1);
	}
	return {
		path: path,
		params: queryIndex < 0
			? {}
			: parse(url.slice(queryIndex + 1, queryEnd)),
	}
};

// Compiles a template into a function that takes a resolved path (without query
// strings) and returns an object containing the template parameters with their
// parsed values. This expects the input of the compiled template to be the
// output of `parsePathname`. Note that it does *not* remove query parameters
// specified in the template.
var compileTemplate = function(template) {
	var templateData = parse$1(template);
	var templateKeys = Object.keys(templateData.params);
	var keys = [];
	var regexp = new RegExp("^" + templateData.path.replace(
		// I escape literal text so people can use things like `:file.:ext` or
		// `:lang-:locale` in routes. This is all merged into one pass so I
		// don't also accidentally escape `-` and make it harder to detect it to
		// ban it from template parameters.
		/:([^\/.-]+)(\.{3}|\.(?!\.)|-)?|[\\^$*+.()|\[\]{}]/g,
		function(m, key, extra) {
			if (key == null) return "\\" + m
			keys.push({k: key, r: extra === "..."});
			if (extra === "...") return "(.*)"
			if (extra === ".") return "([^/]+)\\."
			return "([^/]+)" + (extra || "")
		}
	) + "$");
	return function(data) {
		// First, check the params. Usually, there isn't any, and it's just
		// checking a static set.
		for (var i = 0; i < templateKeys.length; i++) {
			if (templateData.params[templateKeys[i]] !== data.params[templateKeys[i]]) return false
		}
		// If no interpolations exist, let's skip all the ceremony
		if (!keys.length) return regexp.test(data.path)
		var values = regexp.exec(data.path);
		if (values == null) return false
		for (var i = 0; i < keys.length; i++) {
			data.params[keys[i].k] = keys[i].r ? values[i + 1] : decodeURIComponent(values[i + 1]);
		}
		return true
	}
};

var sentinel = {};

var router = function($window, mountRedraw) {
	var fireAsync;

	function setPath(path, data, options) {
		path = build$1(path, data);
		if (fireAsync != null) {
			fireAsync();
			var state = options ? options.state : null;
			var title = options ? options.title : null;
			if (options && options.replace) $window.history.replaceState(state, title, route.prefix + path);
			else $window.history.pushState(state, title, route.prefix + path);
		}
		else {
			$window.location.href = route.prefix + path;
		}
	}

	var currentResolver = sentinel, component, attrs, currentPath, lastUpdate;

	var SKIP = route.SKIP = {};

	function route(root, defaultRoute, routes) {
		if (root == null) throw new Error("Ensure the DOM element that was passed to `m.route` is not undefined")
		// 0 = start
		// 1 = init
		// 2 = ready
		var state = 0;

		var compiled = Object.keys(routes).map(function(route) {
			if (route[0] !== "/") throw new SyntaxError("Routes must start with a `/`")
			if ((/:([^\/\.-]+)(\.{3})?:/).test(route)) {
				throw new SyntaxError("Route parameter names must be separated with either `/`, `.`, or `-`")
			}
			return {
				route: route,
				component: routes[route],
				check: compileTemplate(route),
			}
		});
		var callAsync = typeof setImmediate === "function" ? setImmediate : setTimeout;
		var p = promise.resolve();
		var scheduled = false;
		var onremove;

		fireAsync = null;

		if (defaultRoute != null) {
			var defaultData = parse$1(defaultRoute);

			if (!compiled.some(function (i) { return i.check(defaultData) })) {
				throw new ReferenceError("Default route doesn't match any known routes")
			}
		}

		function resolveRoute() {
			scheduled = false;
			// Consider the pathname holistically. The prefix might even be invalid,
			// but that's not our problem.
			var prefix = $window.location.hash;
			if (route.prefix[0] !== "#") {
				prefix = $window.location.search + prefix;
				if (route.prefix[0] !== "?") {
					prefix = $window.location.pathname + prefix;
					if (prefix[0] !== "/") prefix = "/" + prefix;
				}
			}
			// This seemingly useless `.concat()` speeds up the tests quite a bit,
			// since the representation is consistently a relatively poorly
			// optimized cons string.
			var path = prefix.concat()
				.replace(/(?:%[a-f89][a-f0-9])+/gim, decodeURIComponent)
				.slice(route.prefix.length);
			var data = parse$1(path);

			assign(data.params, $window.history.state);

			function fail() {
				if (path === defaultRoute) throw new Error("Could not resolve default route " + defaultRoute)
				setPath(defaultRoute, null, {replace: true});
			}

			loop(0);
			function loop(i) {
				// 0 = init
				// 1 = scheduled
				// 2 = done
				for (; i < compiled.length; i++) {
					if (compiled[i].check(data)) {
						var payload = compiled[i].component;
						var matchedRoute = compiled[i].route;
						var localComp = payload;
						var update = lastUpdate = function(comp) {
							if (update !== lastUpdate) return
							if (comp === SKIP) return loop(i + 1)
							component = comp != null && (typeof comp.view === "function" || typeof comp === "function")? comp : "div";
							attrs = data.params, currentPath = path, lastUpdate = null;
							currentResolver = payload.render ? payload : null;
							if (state === 2) mountRedraw.redraw();
							else {
								state = 2;
								mountRedraw.redraw.sync();
							}
						};
						// There's no understating how much I *wish* I could
						// use `async`/`await` here...
						if (payload.view || typeof payload === "function") {
							payload = {};
							update(localComp);
						}
						else if (payload.onmatch) {
							p.then(function () {
								return payload.onmatch(data.params, path, matchedRoute)
							}).then(update, fail);
						}
						else update("div");
						return
					}
				}
				fail();
			}
		}

		// Set it unconditionally so `m.route.set` and `m.route.Link` both work,
		// even if neither `pushState` nor `hashchange` are supported. It's
		// cleared if `hashchange` is used, since that makes it automatically
		// async.
		fireAsync = function() {
			if (!scheduled) {
				scheduled = true;
				callAsync(resolveRoute);
			}
		};

		if (typeof $window.history.pushState === "function") {
			onremove = function() {
				$window.removeEventListener("popstate", fireAsync, false);
			};
			$window.addEventListener("popstate", fireAsync, false);
		} else if (route.prefix[0] === "#") {
			fireAsync = null;
			onremove = function() {
				$window.removeEventListener("hashchange", resolveRoute, false);
			};
			$window.addEventListener("hashchange", resolveRoute, false);
		}

		return mountRedraw.mount(root, {
			onbeforeupdate: function() {
				state = state ? 2 : 1;
				return !(!state || sentinel === currentResolver)
			},
			oncreate: resolveRoute,
			onremove: onremove,
			view: function() {
				if (!state || sentinel === currentResolver) return
				// Wrap in a fragment to preserve existing key semantics
				var vnode$1 = [vnode(component, attrs.key, attrs)];
				if (currentResolver) vnode$1 = currentResolver.render(vnode$1[0]);
				return vnode$1
			},
		})
	}
	route.set = function(path, data, options) {
		if (lastUpdate != null) {
			options = options || {};
			options.replace = true;
		}
		lastUpdate = null;
		setPath(path, data, options);
	};
	route.get = function() {return currentPath};
	route.prefix = "#!";
	route.Link = {
		view: function(vnode) {
			var options = vnode.attrs.options;
			// Remove these so they don't get overwritten
			var attrs = {}, onclick, href;
			assign(attrs, vnode.attrs);
			// The first two are internal, but the rest are magic attributes
			// that need censored to not screw up rendering.
			attrs.selector = attrs.options = attrs.key = attrs.oninit =
			attrs.oncreate = attrs.onbeforeupdate = attrs.onupdate =
			attrs.onbeforeremove = attrs.onremove = null;

			// Do this now so we can get the most current `href` and `disabled`.
			// Those attributes may also be specified in the selector, and we
			// should honor that.
			var child = hyperscript_1(vnode.attrs.selector || "a", attrs, vnode.children);

			// Let's provide a *right* way to disable a route link, rather than
			// letting people screw up accessibility on accident.
			//
			// The attribute is coerced so users don't get surprised over
			// `disabled: 0` resulting in a button that's somehow routable
			// despite being visibly disabled.
			if (child.attrs.disabled = Boolean(child.attrs.disabled)) {
				child.attrs.href = null;
				child.attrs["aria-disabled"] = "true";
				// If you *really* do want to do this on a disabled link, use
				// an `oncreate` hook to add it.
				child.attrs.onclick = null;
			} else {
				onclick = child.attrs.onclick;
				href = child.attrs.href;
				child.attrs.href = route.prefix + href;
				child.attrs.onclick = function(e) {
					var result;
					if (typeof onclick === "function") {
						result = onclick.call(e.currentTarget, e);
					} else if (onclick == null || typeof onclick !== "object") ; else if (typeof onclick.handleEvent === "function") {
						onclick.handleEvent(e);
					}

					// Adapted from React Router's implementation:
					// https://github.com/ReactTraining/react-router/blob/520a0acd48ae1b066eb0b07d6d4d1790a1d02482/packages/react-router-dom/modules/Link.js
					//
					// Try to be flexible and intuitive in how we handle links.
					// Fun fact: links aren't as obvious to get right as you
					// would expect. There's a lot more valid ways to click a
					// link than this, and one might want to not simply click a
					// link, but right click or command-click it to copy the
					// link target, etc. Nope, this isn't just for blind people.
					if (
						// Skip if `onclick` prevented default
						result !== false && !e.defaultPrevented &&
						// Ignore everything but left clicks
						(e.button === 0 || e.which === 0 || e.which === 1) &&
						// Let the browser handle `target=_blank`, etc.
						(!e.currentTarget.target || e.currentTarget.target === "_self") &&
						// No modifier keys
						!e.ctrlKey && !e.metaKey && !e.shiftKey && !e.altKey
					) {
						e.preventDefault();
						e.redraw = false;
						route.set(href, null, options);
					}
				};
			}
			return child
		},
	};
	route.param = function(key) {
		return attrs && key != null ? attrs[key] : attrs
	};

	return route
};

var route$1 = router(window, mountRedraw$1);

var m = function m() { return hyperscript_1$1.apply(this, arguments) };
m.m = hyperscript_1$1;
m.trust = hyperscript_1$1.trust;
m.fragment = hyperscript_1$1.fragment;
m.mount = mountRedraw$1.mount;
m.route = route$1;
m.render = render$1;
m.redraw = mountRedraw$1.redraw;
m.request = request$1.request;
m.jsonp = request$1.jsonp;
m.parseQueryString = parse;
m.buildQueryString = build;
m.parsePathname = parse$1;
m.buildPathname = build$1;
m.vnode = vnode;
m.PromisePolyfill = polyfill;

var mithril = m;

var perf = createCommonjsModule(function (module, exports) {
// 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.
Object.defineProperty(exports, "__esModule", { value: true });
exports.perfDisplay = exports.runningStatStr = exports.RunningStatistics = exports.measure = exports.debugNow = exports.perfDebug = void 0;


/**
 * Shorthand for if globals perf debug mode is on.
 */
exports.perfDebug = () => globals$1.globals.frontendLocalState.perfDebug;
/**
 * Returns performance.now() if perfDebug is enabled, otherwise 0.
 * This is needed because calling performance.now is generally expensive
 * and should not be done for every frame.
 */
exports.debugNow = () => exports.perfDebug() ? performance.now() : 0;
/**
 * Returns execution time of |fn| if perf debug mode is on. Returns 0 otherwise.
 */
function measure(fn) {
    const start = exports.debugNow();
    fn();
    return exports.debugNow() - start;
}
exports.measure = measure;
/**
 * Stores statistics about samples, and keeps a fixed size buffer of most recent
 * samples.
 */
class RunningStatistics {
    constructor(_maxBufferSize = 10) {
        this._maxBufferSize = _maxBufferSize;
        this._count = 0;
        this._mean = 0;
        this._lastValue = 0;
        this.buffer = [];
    }
    addValue(value) {
        this._lastValue = value;
        this.buffer.push(value);
        if (this.buffer.length > this._maxBufferSize) {
            this.buffer.shift();
        }
        this._mean = (this._mean * this._count + value) / (this._count + 1);
        this._count++;
    }
    get mean() {
        return this._mean;
    }
    get count() {
        return this._count;
    }
    get bufferMean() {
        return this.buffer.reduce((sum, v) => sum + v, 0) / this.buffer.length;
    }
    get bufferSize() {
        return this.buffer.length;
    }
    get maxBufferSize() {
        return this._maxBufferSize;
    }
    get last() {
        return this._lastValue;
    }
}
exports.RunningStatistics = RunningStatistics;
/**
 * Returns a summary string representation of a RunningStatistics object.
 */
function runningStatStr(stat) {
    return `Last: ${stat.last.toFixed(2)}ms | ` +
        `Avg: ${stat.mean.toFixed(2)}ms | ` +
        `Avg${stat.maxBufferSize}: ${stat.bufferMean.toFixed(2)}ms`;
}
exports.runningStatStr = runningStatStr;
/**
 * Globals singleton class that renders performance stats for the whole app.
 */
class PerfDisplay {
    constructor() {
        this.containers = [];
    }
    addContainer(container) {
        this.containers.push(container);
    }
    removeContainer(container) {
        const i = this.containers.indexOf(container);
        this.containers.splice(i, 1);
    }
    renderPerfStats() {
        if (!exports.perfDebug())
            return;
        const perfDisplayEl = document.querySelector('.perf-stats');
        if (!perfDisplayEl)
            return;
        mithril.render(perfDisplayEl, [
            mithril('section', globals$1.globals.rafScheduler.renderPerfStats()),
            mithril('button.close-button', {
                onclick: () => globals$1.globals.frontendLocalState.togglePerfDebug(),
            }, mithril('i.material-icons', 'close')),
            this.containers.map((c, i) => mithril('section', c.renderPerfStats(i)))
        ]);
    }
}
exports.perfDisplay = new PerfDisplay();

});

var raf_scheduler = createCommonjsModule(function (module, exports) {
// 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.
Object.defineProperty(exports, "__esModule", { value: true });
exports.RafScheduler = void 0;




function statTableHeader() {
    return mithril('tr', mithril('th', ''), mithril('th', 'Last (ms)'), mithril('th', 'Avg (ms)'), mithril('th', 'Avg-10 (ms)'));
}
function statTableRow(title, stat) {
    return mithril('tr', mithril('td', title), mithril('td', stat.last.toFixed(2)), mithril('td', stat.mean.toFixed(2)), mithril('td', stat.bufferMean.toFixed(2)));
}
// This class orchestrates all RAFs in the UI. It ensures that there is only
// one animation frame handler overall and that callbacks are called in
// predictable order. There are two types of callbacks here:
// - actions (e.g. pan/zoon animations), which will alter the "fast"
//  (main-thread-only) state (e.g. update visible time bounds @ 60 fps).
// - redraw callbacks that will repaint canvases.
// This class guarantees that, on each frame, redraw callbacks are called after
// all action callbacks.
class RafScheduler {
    constructor() {
        this.actionCallbacks = new Set();
        this.canvasRedrawCallbacks = new Set();
        this._syncDomRedraw = _ => { };
        this.hasScheduledNextFrame = false;
        this.requestedFullRedraw = false;
        this.isRedrawing = false;
        this._shutdown = false;
        this.perfStats = {
            rafActions: new perf.RunningStatistics(),
            rafCanvas: new perf.RunningStatistics(),
            rafDom: new perf.RunningStatistics(),
            rafTotal: new perf.RunningStatistics(),
            domRedraw: new perf.RunningStatistics(),
        };
    }
    start(cb) {
        this.actionCallbacks.add(cb);
        this.maybeScheduleAnimationFrame();
    }
    stop(cb) {
        this.actionCallbacks.delete(cb);
    }
    addRedrawCallback(cb) {
        this.canvasRedrawCallbacks.add(cb);
    }
    removeRedrawCallback(cb) {
        this.canvasRedrawCallbacks.delete(cb);
    }
    scheduleRedraw() {
        this.maybeScheduleAnimationFrame(true);
    }
    shutdown() {
        this._shutdown = true;
    }
    set domRedraw(cb) {
        this._syncDomRedraw = cb || (_ => { });
    }
    scheduleFullRedraw() {
        this.requestedFullRedraw = true;
        this.maybeScheduleAnimationFrame(true);
    }
    syncDomRedraw(nowMs) {
        const redrawStart = perf.debugNow();
        this._syncDomRedraw(nowMs);
        if (perf.perfDebug()) {
            this.perfStats.domRedraw.addValue(perf.debugNow() - redrawStart);
        }
    }
    syncCanvasRedraw(nowMs) {
        const redrawStart = perf.debugNow();
        if (this.isRedrawing)
            return;
        globals$1.globals.frontendLocalState.clearVisibleTracks();
        this.isRedrawing = true;
        for (const redraw of this.canvasRedrawCallbacks)
            redraw(nowMs);
        this.isRedrawing = false;
        globals$1.globals.frontendLocalState.sendVisibleTracks();
        if (perf.perfDebug()) {
            this.perfStats.rafCanvas.addValue(perf.debugNow() - redrawStart);
        }
    }
    maybeScheduleAnimationFrame(force = false) {
        if (this.hasScheduledNextFrame)
            return;
        if (this.actionCallbacks.size !== 0 || force) {
            this.hasScheduledNextFrame = true;
            window.requestAnimationFrame(this.onAnimationFrame.bind(this));
        }
    }
    onAnimationFrame(nowMs) {
        if (this._shutdown)
            return;
        const rafStart = perf.debugNow();
        this.hasScheduledNextFrame = false;
        const doFullRedraw = this.requestedFullRedraw;
        this.requestedFullRedraw = false;
        const actionTime = perf.measure(() => {
            for (const action of this.actionCallbacks)
                action(nowMs);
        });
        const domTime = perf.measure(() => {
            if (doFullRedraw)
                this.syncDomRedraw(nowMs);
        });
        const canvasTime = perf.measure(() => this.syncCanvasRedraw(nowMs));
        const totalRafTime = perf.debugNow() - rafStart;
        this.updatePerfStats(actionTime, domTime, canvasTime, totalRafTime);
        perf.perfDisplay.renderPerfStats();
        this.maybeScheduleAnimationFrame();
    }
    updatePerfStats(actionsTime, domTime, canvasTime, totalRafTime) {
        if (!perf.perfDebug())
            return;
        this.perfStats.rafActions.addValue(actionsTime);
        this.perfStats.rafDom.addValue(domTime);
        this.perfStats.rafCanvas.addValue(canvasTime);
        this.perfStats.rafTotal.addValue(totalRafTime);
    }
    renderPerfStats() {
        logging.assertTrue(perf.perfDebug());
        return mithril('div', mithril('div', [
            mithril('button', { onclick: () => this.scheduleRedraw() }, 'Do Canvas Redraw'),
            '   |   ',
            mithril('button', { onclick: () => this.scheduleFullRedraw() }, 'Do Full Redraw'),
        ]), mithril('div', 'Raf Timing ' +
            '(Total may not add up due to imprecision)'), mithril('table', statTableHeader(), statTableRow('Actions', this.perfStats.rafActions), statTableRow('Dom', this.perfStats.rafDom), statTableRow('Canvas', this.perfStats.rafCanvas), statTableRow('Total', this.perfStats.rafTotal)), mithril('div', 'Dom redraw: ' +
            `Count: ${this.perfStats.domRedraw.count} | ` +
            perf.runningStatStr(this.perfStats.domRedraw)));
    }
}
exports.RafScheduler = RafScheduler;

});

var service_worker_controller = createCommonjsModule(function (module, exports) {
// Copyright (C) 2020 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.
Object.defineProperty(exports, "__esModule", { value: true });
exports.ServiceWorkerController = void 0;

// Handles registration, unregistration and lifecycle of the service worker.
// This class contains only the controlling logic, all the code in here runs in
// the main thread, not in the service worker thread.
// The actual service worker code is in src/service_worker.
// Design doc: http://go/perfetto-offline.


// We use a dedicated |caches| object to share a global boolean beween the main
// thread and the SW. SW cannot use local-storage or anything else other than
// IndexedDB (which would be overkill).
const BYPASS_ID = 'BYPASS_SERVICE_WORKER';
class ServiceWorkerController {
    constructor() {
        this._initialWorker = null;
        this._bypassed = false;
        this._installing = false;
    }
    // Caller should reload().
    setBypass(bypass) {
        return tslib.__awaiter(this, void 0, void 0, function* () {
            if (!('serviceWorker' in navigator))
                return; // Not supported.
            this._bypassed = bypass;
            if (bypass) {
                yield caches.open(BYPASS_ID); // Create the entry.
                for (const reg of yield navigator.serviceWorker.getRegistrations()) {
                    yield reg.unregister();
                }
            }
            else {
                yield caches.delete(BYPASS_ID);
                this.install();
            }
            globals$1.globals.rafScheduler.scheduleFullRedraw();
        });
    }
    onStateChange(sw) {
        globals$1.globals.rafScheduler.scheduleFullRedraw();
        if (sw.state === 'installing') {
            this._installing = true;
        }
        else if (sw.state === 'activated') {
            this._installing = false;
            // Don't show the notification if the site was served straight
            // from the network (e.g., on the very first visit or after
            // Ctrl+Shift+R). In these cases, we are already at the last
            // version.
            if (sw !== this._initialWorker && this._initialWorker) {
                globals$1.globals.frontendLocalState.newVersionAvailable = true;
            }
        }
    }
    monitorWorker(sw) {
        if (!sw)
            return;
        sw.addEventListener('error', (e) => logging.reportError(e));
        sw.addEventListener('statechange', () => this.onStateChange(sw));
        this.onStateChange(sw); // Trigger updates for the current state.
    }
    install() {
        return tslib.__awaiter(this, void 0, void 0, function* () {
            if (!('serviceWorker' in navigator))
                return; // Not supported.
            if (location.pathname !== '/') {
                // Disable the service worker when the UI is loaded from a non-root URL
                // (e.g. from the CI artifacts GCS bucket). Supporting the case of a
                // nested index.html is too cumbersome and has no benefits.
                return;
            }
            if (yield caches.has(BYPASS_ID)) {
                this._bypassed = true;
                console.log('Skipping service worker registration, disabled by the user');
                return;
            }
            // In production cases versionDir == VERSION. We use this here for ease of
            // testing (so we can have /v1.0.0a/ /v1.0.0b/ even if they have the same
            // version code).
            const versionDir = globals$1.globals.root.split('/').slice(-2)[0];
            const swUri = `/service_worker.js?v=${versionDir}`;
            navigator.serviceWorker.register(swUri).then(registration => {
                this._initialWorker = registration.active;
                // At this point there are two options:
                // 1. This is the first time we visit the site (or cache was cleared) and
                //    no SW is installed yet. In this case |installing| will be set.
                // 2. A SW is already installed (though it might be obsolete). In this
                //    case |active| will be set.
                this.monitorWorker(registration.installing);
                this.monitorWorker(registration.active);
                // Setup the event that shows the "Updated to v1.2.3" notification.
                registration.addEventListener('updatefound', () => {
                    this.monitorWorker(registration.installing);
                });
            });
        });
    }
    get bypassed() {
        return this._bypassed;
    }
    get installing() {
        return this._installing;
    }
}
exports.ServiceWorkerController = ServiceWorkerController;

});

var globals$1 = createCommonjsModule(function (module, exports) {
// 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.
Object.defineProperty(exports, "__esModule", { value: true });
exports.globals = void 0;








function getRoot() {
    // Works out the root directory where the content should be served from
    // e.g. `http://origin/v1.2.3/`.
    let root = document.currentScript.src;
    root = root.substr(0, root.lastIndexOf('/') + 1);
    return root;
}
/**
 * Global accessors for state/dispatch in the frontend.
 */
class Globals {
    constructor() {
        this.root = getRoot();
        this._dispatch = undefined;
        this._controllerWorker = undefined;
        this._state = undefined;
        this._frontendLocalState = undefined;
        this._rafScheduler = undefined;
        this._serviceWorkerController = undefined;
        this._logging = undefined;
        this._isInternalUser = undefined;
        this._channel = undefined;
        // TODO(hjd): Unify trackDataStore, queryResults, overviewStore, threads.
        this._trackDataStore = undefined;
        this._queryResults = undefined;
        this._overviewStore = undefined;
        this._aggregateDataStore = undefined;
        this._threadMap = undefined;
        this._sliceDetails = undefined;
        this._threadStateDetails = undefined;
        this._connectedFlows = undefined;
        this._selectedFlows = undefined;
        this._visibleFlowCategories = undefined;
        this._counterDetails = undefined;
        this._heapProfileDetails = undefined;
        this._functionProfileDetails = undefined;
        this._cpuProfileDetails = undefined;
        this._numQueriesQueued = 0;
        this._bufferUsage = undefined;
        this._recordingLog = undefined;
        this._traceErrors = undefined;
        this._metricError = undefined;
        this._metricResult = undefined;
        this._hasFtrace = undefined;
        this._jobStatus = undefined;
        this._sourceFileStorage = undefined;
        this._currentSearchResults = {
            sliceIds: [],
            tsStarts: [],
            utids: [],
            trackIds: [],
            sources: [],
            totalResults: 0,
        };
        this.searchSummary = {
            tsStarts: new Float64Array(0),
            tsEnds: new Float64Array(0),
            count: new Uint8Array(0),
        };
    }
    initialize(dispatch, controllerWorker) {
        this._dispatch = dispatch;
        this._controllerWorker = controllerWorker;
        this._state = state.createEmptyState();
        this._frontendLocalState = new frontend_local_state.FrontendLocalState();
        this._rafScheduler = new raf_scheduler.RafScheduler();
        this._serviceWorkerController = new service_worker_controller.ServiceWorkerController();
        this._logging = analytics.initAnalytics();
        // TODO(hjd): Unify trackDataStore, queryResults, overviewStore, threads.
        this._trackDataStore = new Map();
        this._queryResults = new Map();
        this._overviewStore = new Map();
        this._aggregateDataStore = new Map();
        this._threadMap = new Map();
        this._sliceDetails = {};
        this._connectedFlows = [];
        this._selectedFlows = [];
        this._visibleFlowCategories = new Map();
        this._counterDetails = {};
        this._threadStateDetails = {};
        this._heapProfileDetails = {};
        this._functionProfileDetails = [];
        this._cpuProfileDetails = {};
        this._sourceFileStorage = {};
    }
    get state() {
        return logging.assertExists(this._state);
    }
    set state(state) {
        this._state = logging.assertExists(state);
    }
    get dispatch() {
        return logging.assertExists(this._dispatch);
    }
    get frontendLocalState() {
        return logging.assertExists(this._frontendLocalState);
    }
    get rafScheduler() {
        return logging.assertExists(this._rafScheduler);
    }
    get logging() {
        return logging.assertExists(this._logging);
    }
    get serviceWorkerController() {
        return logging.assertExists(this._serviceWorkerController);
    }
    // TODO(hjd): Unify trackDataStore, queryResults, overviewStore, threads.
    get overviewStore() {
        return logging.assertExists(this._overviewStore);
    }
    get trackDataStore() {
        return logging.assertExists(this._trackDataStore);
    }
    get queryResults() {
        return logging.assertExists(this._queryResults);
    }
    get threads() {
        return logging.assertExists(this._threadMap);
    }
    get sliceDetails() {
        return logging.assertExists(this._sliceDetails);
    }
    set sliceDetails(click) {
        this._sliceDetails = logging.assertExists(click);
    }
    get threadStateDetails() {
        return logging.assertExists(this._threadStateDetails);
    }
    set threadStateDetails(click) {
        this._threadStateDetails = logging.assertExists(click);
    }
    get connectedFlows() {
        return logging.assertExists(this._connectedFlows);
    }
    set connectedFlows(connectedFlows) {
        this._connectedFlows = logging.assertExists(connectedFlows);
    }
    get selectedFlows() {
        return logging.assertExists(this._selectedFlows);
    }
    set selectedFlows(selectedFlows) {
        this._selectedFlows = logging.assertExists(selectedFlows);
    }
    get visibleFlowCategories() {
        return logging.assertExists(this._visibleFlowCategories);
    }
    set visibleFlowCategories(visibleFlowCategories) {
        this._visibleFlowCategories = logging.assertExists(visibleFlowCategories);
    }
    get counterDetails() {
        return logging.assertExists(this._counterDetails);
    }
    set counterDetails(click) {
        this._counterDetails = logging.assertExists(click);
    }
    get aggregateDataStore() {
        return logging.assertExists(this._aggregateDataStore);
    }
    get heapProfileDetails() {
        return logging.assertExists(this._heapProfileDetails);
    }
    set heapProfileDetails(click) {
        this._heapProfileDetails = logging.assertExists(click);
    }
    get functionProfileDetails() {
        return logging.assertExists(this._functionProfileDetails);
    }
    set functionProfileDetails(click) {
        this._functionProfileDetails = logging.assertExists(click);
    }
    get traceErrors() {
        return this._traceErrors;
    }
    setTraceErrors(arg) {
        this._traceErrors = arg;
    }
    get metricError() {
        return this._metricError;
    }
    setMetricError(arg) {
        this._metricError = arg;
    }
    get metricResult() {
        return this._metricResult;
    }
    setMetricResult(result) {
        this._metricResult = result;
    }
    get cpuProfileDetails() {
        return logging.assertExists(this._cpuProfileDetails);
    }
    set cpuProfileDetails(click) {
        this._cpuProfileDetails = logging.assertExists(click);
    }
    get sourceFileStorage() {
        return logging.assertExists(this._sourceFileStorage);
    }
    set sourceFileStorage(value) {
        this._sourceFileStorage = value;
    }
    set numQueuedQueries(value) {
        this._numQueriesQueued = value;
    }
    get numQueuedQueries() {
        return this._numQueriesQueued;
    }
    get bufferUsage() {
        return this._bufferUsage;
    }
    get recordingLog() {
        return this._recordingLog;
    }
    get currentSearchResults() {
        return this._currentSearchResults;
    }
    set currentSearchResults(results) {
        this._currentSearchResults = results;
    }
    get hasFtrace() {
        return !!this._hasFtrace;
    }
    set hasFtrace(value) {
        this._hasFtrace = value;
    }
    getConversionJobStatus(name) {
        return this.getJobStatusMap().get(name) || conversion_jobs.ConversionJobStatus.NotRunning;
    }
    setConversionJobStatus(name, status) {
        const map = this.getJobStatusMap();
        if (status === conversion_jobs.ConversionJobStatus.NotRunning) {
            map.delete(name);
        }
        else {
            map.set(name, status);
        }
    }
    getJobStatusMap() {
        if (!this._jobStatus) {
            this._jobStatus = new Map();
        }
        return this._jobStatus;
    }
    setBufferUsage(bufferUsage) {
        this._bufferUsage = bufferUsage;
    }
    setTrackData(id, data) {
        this.trackDataStore.set(id, data);
    }
    setRecordingLog(recordingLog) {
        this._recordingLog = recordingLog;
    }
    setAggregateData(kind, data) {
        this.aggregateDataStore.set(kind, data);
    }
    getCurResolution() {
        // Truncate the resolution to the closest power of 2 (in nanosecond space).
        // We choose to work in ns space because resolution is consumed be track
        // controllers for quantization and they rely on resolution to be a power
        // of 2 in nanosecond form. This is property does not hold if we work in
        // second space.
        //
        // This effectively means the resolution changes approximately every 6 zoom
        // levels. Logic: each zoom level represents a delta of 0.1 * (visible
        // window span). Therefore, zooming out by six levels is 1.1^6 ~= 2.
        // Similarily, zooming in six levels is 0.9^6 ~= 0.5.
        const pxToSec = this.frontendLocalState.timeScale.deltaPxToDuration(1);
        // TODO(b/186265930): Remove once fixed:
        if (!isFinite(pxToSec)) {
            // Resolution is in pixels per second so 1000 means 1px = 1ms.
            console.error(`b/186265930: Bad pxToSec suppressed ${pxToSec}`);
            return time.fromNs(Math.pow(2, Math.floor(Math.log2(time.toNs(1000)))));
        }
        const pxToNs = Math.max(time.toNs(pxToSec), 1);
        const resolution = time.fromNs(Math.pow(2, Math.floor(Math.log2(pxToNs))));
        const log2 = Math.log2(time.toNs(resolution));
        if (log2 % 1 !== 0) {
            throw new Error(`Resolution should be a power of two.
        pxToSec: ${pxToSec},
        pxToNs: ${pxToNs},
        resolution: ${resolution},
        log2: ${Math.log2(time.toNs(resolution))}`);
        }
        return resolution;
    }
    makeSelection(action, tabToOpen = 'current_selection') {
        // A new selection should cancel the current search selection.
        exports.globals.frontendLocalState.searchIndex = -1;
        exports.globals.frontendLocalState.currentTab =
            action.type === 'deselect' ? undefined : tabToOpen;
        exports.globals.dispatch(action);
    }
    resetForTesting() {
        this._dispatch = undefined;
        this._state = undefined;
        this._frontendLocalState = undefined;
        this._rafScheduler = undefined;
        this._serviceWorkerController = undefined;
        // TODO(hjd): Unify trackDataStore, queryResults, overviewStore, threads.
        this._trackDataStore = undefined;
        this._queryResults = undefined;
        this._overviewStore = undefined;
        this._threadMap = undefined;
        this._sliceDetails = undefined;
        this._threadStateDetails = undefined;
        this._aggregateDataStore = undefined;
        this._numQueriesQueued = 0;
        this._metricResult = undefined;
        this._currentSearchResults = {
            sliceIds: [],
            tsStarts: [],
            utids: [],
            trackIds: [],
            sources: [],
            totalResults: 0,
        };
    }
    // This variable is set by the is_internal_user.js script if the user is a
    // googler. This is used to avoid exposing features that are not ready yet
    // for public consumption. The gated features themselves are not secret.
    // If a user has been detected as a Googler once, make that sticky in
    // localStorage, so that we keep treating them as such when they connect over
    // public networks.
    get isInternalUser() {
        if (this._isInternalUser === undefined) {
            this._isInternalUser = localStorage.getItem('isInternalUser') === '1';
        }
        return this._isInternalUser;
    }
    set isInternalUser(value) {
        localStorage.setItem('isInternalUser', value ? '1' : '0');
        this._isInternalUser = value;
    }
    get channel() {
        if (this._channel === undefined) {
            this._channel = localStorage.getItem('perfettoUiChannel') || 'stable';
        }
        return this._channel;
    }
    // Used when switching to the legacy TraceViewer UI.
    // Most resources are cleaned up by replacing the current |window| object,
    // however pending RAFs and workers seem to outlive the |window| and need to
    // be cleaned up explicitly.
    shutdown() {
        this._controllerWorker.terminate();
        this._rafScheduler.shutdown();
    }
}
exports.globals = new Globals();

});

var track = createCommonjsModule(function (module, exports) {
// 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.
Object.defineProperty(exports, "__esModule", { value: true });
exports.Track = void 0;


/**
 * The abstract class that needs to be implemented by all tracks.
 */
class Track {
    constructor(trackState) {
        this.trackId = trackState.id;
    }
    get trackState() {
        return globals$1.globals.state.tracks[this.trackId];
    }
    get config() {
        return globals$1.globals.state.tracks[this.trackId].config;
    }
    data() {
        return globals$1.globals.trackDataStore.get(this.trackId);
    }
    getHeight() {
        return 40;
    }
    getTrackShellButtons() {
        return [];
    }
    onMouseMove(_position) { }
    /**
     * Returns whether the mouse click has selected something.
     * Used to prevent further propagation if necessary.
     */
    onMouseClick(_position) {
        return false;
    }
    onMouseOut() { }
    render(ctx) {
        globals$1.globals.frontendLocalState.addVisibleTrack(this.trackState.id);
        if (this.data() === undefined) {
            const { visibleWindowTime, timeScale } = globals$1.globals.frontendLocalState;
            const startPx = Math.floor(timeScale.timeToPx(visibleWindowTime.start));
            const endPx = Math.ceil(timeScale.timeToPx(visibleWindowTime.end));
            checkerboard_1.checkerboard(ctx, this.getHeight(), startPx, endPx);
        }
        else {
            this.renderCanvas(ctx);
        }
    }
    drawTrackHoverTooltip(ctx, xPos, text, text2) {
        ctx.font = '10px Roboto Condensed';
        const textWidth = ctx.measureText(text).width;
        let width = textWidth;
        let textYPos = this.getHeight() / 2;
        if (text2 !== undefined) {
            const text2Width = ctx.measureText(text2).width;
            width = Math.max(textWidth, text2Width);
            textYPos = this.getHeight() / 2 - 6;
        }
        // Move tooltip over if it would go off the right edge of the viewport.
        const rectWidth = width + 16;
        const endPx = globals$1.globals.frontendLocalState.timeScale.endPx;
        if (xPos + rectWidth > endPx) {
            xPos -= (xPos + rectWidth - endPx);
        }
        ctx.fillStyle = 'rgba(255, 255, 255, 0.9)';
        const rectMargin = this.getHeight() / 12;
        ctx.fillRect(xPos, rectMargin, rectWidth, this.getHeight() - rectMargin * 2);
        ctx.fillStyle = 'hsl(200, 50%, 40%)';
        ctx.textAlign = 'left';
        ctx.textBaseline = 'middle';
        ctx.fillText(text, xPos + 8, textYPos);
        if (text2 !== undefined) {
            ctx.fillText(text2, xPos + 8, this.getHeight() / 2 + 6);
        }
    }
    /**
     * Returns a place where a given slice should be drawn. Should be implemented
     * only for track types that support slices e.g. chrome_slice, async_slices
     * tStart - slice start time in seconds, tEnd - slice end time in seconds,
     * depth - slice depth
     */
    getSliceRect(_tStart, _tEnd, _depth) {
        return undefined;
    }
}
exports.Track = Track;

});

var registry = createCommonjsModule(function (module, exports) {
// 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.
Object.defineProperty(exports, "__esModule", { value: true });
exports.Registry = void 0;
class Registry {
    constructor() {
        this.registry = new Map();
    }
    register(registrant) {
        const kind = registrant.kind;
        if (this.registry.has(kind)) {
            throw new Error(`Registrant ${kind} already exists in the registry`);
        }
        this.registry.set(kind, registrant);
    }
    has(kind) {
        return this.registry.has(kind);
    }
    get(kind) {
        const registrant = this.registry.get(kind);
        if (registrant === undefined) {
            throw new Error(`${kind} has not been registered.`);
        }
        return registrant;
    }
    unregisterAllForTesting() {
        this.registry.clear();
    }
}
exports.Registry = Registry;

});

var track_registry = createCommonjsModule(function (module, exports) {
// 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.
Object.defineProperty(exports, "__esModule", { value: true });
exports.trackRegistry = void 0;

/**
 * Global registry that maps types to TrackCreator.
 */
exports.trackRegistry = new registry.Registry();

});

var common$8 = createCommonjsModule(function (module, exports) {
// 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.
Object.defineProperty(exports, "__esModule", { value: true });
exports.ANDROID_LOGS_TRACK_KIND = void 0;
exports.ANDROID_LOGS_TRACK_KIND = 'AndroidLogTrack';

});

createCommonjsModule(function (module, exports) {
// Copyright (C) 2019 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.
Object.defineProperty(exports, "__esModule", { value: true });





const LEVELS = [
    { color: 'hsl(122, 39%, 49%)', prios: [0, 1, 2, 3] },
    { color: 'hsl(0, 0%, 70%)', prios: [4] },
    { color: 'hsl(45, 100%, 51%)', prios: [5] },
    { color: 'hsl(4, 90%, 58%)', prios: [6] },
    { color: 'hsl(291, 64%, 42%)', prios: [7] },
];
const MARGIN_TOP = 2;
const RECT_HEIGHT = 35;
const EVT_PX = 2; // Width of an event tick in pixels.
class AndroidLogTrack extends track.Track {
    constructor(trackState) {
        super(trackState);
    }
    static create(trackState) {
        return new AndroidLogTrack(trackState);
    }
    renderCanvas(ctx) {
        const { timeScale, visibleWindowTime } = globals$1.globals.frontendLocalState;
        const data = this.data();
        if (data === undefined)
            return; // Can't possibly draw anything.
        const dataStartPx = timeScale.timeToPx(data.start);
        const dataEndPx = timeScale.timeToPx(data.end);
        const visibleStartPx = timeScale.timeToPx(visibleWindowTime.start);
        const visibleEndPx = timeScale.timeToPx(visibleWindowTime.end);
        checkerboard_1.checkerboardExcept(ctx, this.getHeight(), visibleStartPx, visibleEndPx, dataStartPx, dataEndPx);
        const quantWidth = Math.max(EVT_PX, timeScale.deltaTimeToPx(data.resolution));
        const blockH = RECT_HEIGHT / LEVELS.length;
        for (let i = 0; i < data.timestamps.length; i++) {
            for (let lev = 0; lev < LEVELS.length; lev++) {
                let hasEventsForCurColor = false;
                for (const prio of LEVELS[lev].prios) {
                    if (data.priorities[i] & (1 << prio))
                        hasEventsForCurColor = true;
                }
                if (!hasEventsForCurColor)
                    continue;
                ctx.fillStyle = LEVELS[lev].color;
                const px = Math.floor(timeScale.timeToPx(data.timestamps[i]));
                ctx.fillRect(px, MARGIN_TOP + blockH * lev, quantWidth, blockH);
            } // for(lev)
        } // for (timestamps)
    }
}
AndroidLogTrack.kind = common$8.ANDROID_LOGS_TRACK_KIND;
track_registry.trackRegistry.register(AndroidLogTrack);

});

// Generated by Haxe 3.4.4
var hsluv = hsluv || {};
hsluv.Geometry = function() { };
hsluv.Geometry.intersectLineLine = function(a,b) {
	var x = (a.intercept - b.intercept) / (b.slope - a.slope);
	var y = a.slope * x + a.intercept;
	return { x : x, y : y};
};
hsluv.Geometry.distanceFromOrigin = function(point) {
	return Math.sqrt(Math.pow(point.x,2) + Math.pow(point.y,2));
};
hsluv.Geometry.distanceLineFromOrigin = function(line) {
	return Math.abs(line.intercept) / Math.sqrt(Math.pow(line.slope,2) + 1);
};
hsluv.Geometry.perpendicularThroughPoint = function(line,point) {
	var slope = -1 / line.slope;
	var intercept = point.y - slope * point.x;
	return { slope : slope, intercept : intercept};
};
hsluv.Geometry.angleFromOrigin = function(point) {
	return Math.atan2(point.y,point.x);
};
hsluv.Geometry.normalizeAngle = function(angle) {
	var m = 2 * Math.PI;
	return (angle % m + m) % m;
};
hsluv.Geometry.lengthOfRayUntilIntersect = function(theta,line) {
	return line.intercept / (Math.sin(theta) - line.slope * Math.cos(theta));
};
hsluv.Hsluv = function() { };
hsluv.Hsluv.getBounds = function(L) {
	var result = [];
	var sub1 = Math.pow(L + 16,3) / 1560896;
	var sub2 = sub1 > hsluv.Hsluv.epsilon ? sub1 : L / hsluv.Hsluv.kappa;
	var _g = 0;
	while(_g < 3) {
		var c = _g++;
		var m1 = hsluv.Hsluv.m[c][0];
		var m2 = hsluv.Hsluv.m[c][1];
		var m3 = hsluv.Hsluv.m[c][2];
		var _g1 = 0;
		while(_g1 < 2) {
			var t = _g1++;
			var top1 = (284517 * m1 - 94839 * m3) * sub2;
			var top2 = (838422 * m3 + 769860 * m2 + 731718 * m1) * L * sub2 - 769860 * t * L;
			var bottom = (632260 * m3 - 126452 * m2) * sub2 + 126452 * t;
			result.push({ slope : top1 / bottom, intercept : top2 / bottom});
		}
	}
	return result;
};
hsluv.Hsluv.maxSafeChromaForL = function(L) {
	var bounds = hsluv.Hsluv.getBounds(L);
	var min = Infinity;
	var _g = 0;
	while(_g < bounds.length) {
		var bound = bounds[_g];
		++_g;
		var length = hsluv.Geometry.distanceLineFromOrigin(bound);
		min = Math.min(min,length);
	}
	return min;
};
hsluv.Hsluv.maxChromaForLH = function(L,H) {
	var hrad = H / 360 * Math.PI * 2;
	var bounds = hsluv.Hsluv.getBounds(L);
	var min = Infinity;
	var _g = 0;
	while(_g < bounds.length) {
		var bound = bounds[_g];
		++_g;
		var length = hsluv.Geometry.lengthOfRayUntilIntersect(hrad,bound);
		if(length >= 0) {
			min = Math.min(min,length);
		}
	}
	return min;
};
hsluv.Hsluv.dotProduct = function(a,b) {
	var sum = 0;
	var _g1 = 0;
	var _g = a.length;
	while(_g1 < _g) {
		var i = _g1++;
		sum += a[i] * b[i];
	}
	return sum;
};
hsluv.Hsluv.fromLinear = function(c) {
	if(c <= 0.0031308) {
		return 12.92 * c;
	} else {
		return 1.055 * Math.pow(c,0.416666666666666685) - 0.055;
	}
};
hsluv.Hsluv.toLinear = function(c) {
	if(c > 0.04045) {
		return Math.pow((c + 0.055) / 1.055,2.4);
	} else {
		return c / 12.92;
	}
};
hsluv.Hsluv.xyzToRgb = function(tuple) {
	return [hsluv.Hsluv.fromLinear(hsluv.Hsluv.dotProduct(hsluv.Hsluv.m[0],tuple)),hsluv.Hsluv.fromLinear(hsluv.Hsluv.dotProduct(hsluv.Hsluv.m[1],tuple)),hsluv.Hsluv.fromLinear(hsluv.Hsluv.dotProduct(hsluv.Hsluv.m[2],tuple))];
};
hsluv.Hsluv.rgbToXyz = function(tuple) {
	var rgbl = [hsluv.Hsluv.toLinear(tuple[0]),hsluv.Hsluv.toLinear(tuple[1]),hsluv.Hsluv.toLinear(tuple[2])];
	return [hsluv.Hsluv.dotProduct(hsluv.Hsluv.minv[0],rgbl),hsluv.Hsluv.dotProduct(hsluv.Hsluv.minv[1],rgbl),hsluv.Hsluv.dotProduct(hsluv.Hsluv.minv[2],rgbl)];
};
hsluv.Hsluv.yToL = function(Y) {
	if(Y <= hsluv.Hsluv.epsilon) {
		return Y / hsluv.Hsluv.refY * hsluv.Hsluv.kappa;
	} else {
		return 116 * Math.pow(Y / hsluv.Hsluv.refY,0.333333333333333315) - 16;
	}
};
hsluv.Hsluv.lToY = function(L) {
	if(L <= 8) {
		return hsluv.Hsluv.refY * L / hsluv.Hsluv.kappa;
	} else {
		return hsluv.Hsluv.refY * Math.pow((L + 16) / 116,3);
	}
};
hsluv.Hsluv.xyzToLuv = function(tuple) {
	var X = tuple[0];
	var Y = tuple[1];
	var Z = tuple[2];
	var divider = X + 15 * Y + 3 * Z;
	var varU = 4 * X;
	var varV = 9 * Y;
	if(divider != 0) {
		varU /= divider;
		varV /= divider;
	} else {
		varU = NaN;
		varV = NaN;
	}
	var L = hsluv.Hsluv.yToL(Y);
	if(L == 0) {
		return [0,0,0];
	}
	var U = 13 * L * (varU - hsluv.Hsluv.refU);
	var V = 13 * L * (varV - hsluv.Hsluv.refV);
	return [L,U,V];
};
hsluv.Hsluv.luvToXyz = function(tuple) {
	var L = tuple[0];
	var U = tuple[1];
	var V = tuple[2];
	if(L == 0) {
		return [0,0,0];
	}
	var varU = U / (13 * L) + hsluv.Hsluv.refU;
	var varV = V / (13 * L) + hsluv.Hsluv.refV;
	var Y = hsluv.Hsluv.lToY(L);
	var X = 0 - 9 * Y * varU / ((varU - 4) * varV - varU * varV);
	var Z = (9 * Y - 15 * varV * Y - varV * X) / (3 * varV);
	return [X,Y,Z];
};
hsluv.Hsluv.luvToLch = function(tuple) {
	var L = tuple[0];
	var U = tuple[1];
	var V = tuple[2];
	var C = Math.sqrt(U * U + V * V);
	var H;
	if(C < 0.00000001) {
		H = 0;
	} else {
		var Hrad = Math.atan2(V,U);
		H = Hrad * 180.0 / Math.PI;
		if(H < 0) {
			H = 360 + H;
		}
	}
	return [L,C,H];
};
hsluv.Hsluv.lchToLuv = function(tuple) {
	var L = tuple[0];
	var C = tuple[1];
	var H = tuple[2];
	var Hrad = H / 360.0 * 2 * Math.PI;
	var U = Math.cos(Hrad) * C;
	var V = Math.sin(Hrad) * C;
	return [L,U,V];
};
hsluv.Hsluv.hsluvToLch = function(tuple) {
	var H = tuple[0];
	var S = tuple[1];
	var L = tuple[2];
	if(L > 99.9999999) {
		return [100,0,H];
	}
	if(L < 0.00000001) {
		return [0,0,H];
	}
	var max = hsluv.Hsluv.maxChromaForLH(L,H);
	var C = max / 100 * S;
	return [L,C,H];
};
hsluv.Hsluv.lchToHsluv = function(tuple) {
	var L = tuple[0];
	var C = tuple[1];
	var H = tuple[2];
	if(L > 99.9999999) {
		return [H,0,100];
	}
	if(L < 0.00000001) {
		return [H,0,0];
	}
	var max = hsluv.Hsluv.maxChromaForLH(L,H);
	var S = C / max * 100;
	return [H,S,L];
};
hsluv.Hsluv.hpluvToLch = function(tuple) {
	var H = tuple[0];
	var S = tuple[1];
	var L = tuple[2];
	if(L > 99.9999999) {
		return [100,0,H];
	}
	if(L < 0.00000001) {
		return [0,0,H];
	}
	var max = hsluv.Hsluv.maxSafeChromaForL(L);
	var C = max / 100 * S;
	return [L,C,H];
};
hsluv.Hsluv.lchToHpluv = function(tuple) {
	var L = tuple[0];
	var C = tuple[1];
	var H = tuple[2];
	if(L > 99.9999999) {
		return [H,0,100];
	}
	if(L < 0.00000001) {
		return [H,0,0];
	}
	var max = hsluv.Hsluv.maxSafeChromaForL(L);
	var S = C / max * 100;
	return [H,S,L];
};
hsluv.Hsluv.rgbToHex = function(tuple) {
	var h = "#";
	var _g = 0;
	while(_g < 3) {
		var i = _g++;
		var chan = tuple[i];
		var c = Math.round(chan * 255);
		var digit2 = c % 16;
		var digit1 = (c - digit2) / 16 | 0;
		h += hsluv.Hsluv.hexChars.charAt(digit1) + hsluv.Hsluv.hexChars.charAt(digit2);
	}
	return h;
};
hsluv.Hsluv.hexToRgb = function(hex) {
	hex = hex.toLowerCase();
	var ret = [];
	var _g = 0;
	while(_g < 3) {
		var i = _g++;
		var digit1 = hsluv.Hsluv.hexChars.indexOf(hex.charAt(i * 2 + 1));
		var digit2 = hsluv.Hsluv.hexChars.indexOf(hex.charAt(i * 2 + 2));
		var n = digit1 * 16 + digit2;
		ret.push(n / 255.0);
	}
	return ret;
};
hsluv.Hsluv.lchToRgb = function(tuple) {
	return hsluv.Hsluv.xyzToRgb(hsluv.Hsluv.luvToXyz(hsluv.Hsluv.lchToLuv(tuple)));
};
hsluv.Hsluv.rgbToLch = function(tuple) {
	return hsluv.Hsluv.luvToLch(hsluv.Hsluv.xyzToLuv(hsluv.Hsluv.rgbToXyz(tuple)));
};
hsluv.Hsluv.hsluvToRgb = function(tuple) {
	return hsluv.Hsluv.lchToRgb(hsluv.Hsluv.hsluvToLch(tuple));
};
hsluv.Hsluv.rgbToHsluv = function(tuple) {
	return hsluv.Hsluv.lchToHsluv(hsluv.Hsluv.rgbToLch(tuple));
};
hsluv.Hsluv.hpluvToRgb = function(tuple) {
	return hsluv.Hsluv.lchToRgb(hsluv.Hsluv.hpluvToLch(tuple));
};
hsluv.Hsluv.rgbToHpluv = function(tuple) {
	return hsluv.Hsluv.lchToHpluv(hsluv.Hsluv.rgbToLch(tuple));
};
hsluv.Hsluv.hsluvToHex = function(tuple) {
	return hsluv.Hsluv.rgbToHex(hsluv.Hsluv.hsluvToRgb(tuple));
};
hsluv.Hsluv.hpluvToHex = function(tuple) {
	return hsluv.Hsluv.rgbToHex(hsluv.Hsluv.hpluvToRgb(tuple));
};
hsluv.Hsluv.hexToHsluv = function(s) {
	return hsluv.Hsluv.rgbToHsluv(hsluv.Hsluv.hexToRgb(s));
};
hsluv.Hsluv.hexToHpluv = function(s) {
	return hsluv.Hsluv.rgbToHpluv(hsluv.Hsluv.hexToRgb(s));
};
hsluv.Hsluv.m = [[3.240969941904521,-1.537383177570093,-0.498610760293],[-0.96924363628087,1.87596750150772,0.041555057407175],[0.055630079696993,-0.20397695888897,1.056971514242878]];
hsluv.Hsluv.minv = [[0.41239079926595,0.35758433938387,0.18048078840183],[0.21263900587151,0.71516867876775,0.072192315360733],[0.019330818715591,0.11919477979462,0.95053215224966]];
hsluv.Hsluv.refY = 1.0;
hsluv.Hsluv.refU = 0.19783000664283;
hsluv.Hsluv.refV = 0.46831999493879;
hsluv.Hsluv.kappa = 903.2962962;
hsluv.Hsluv.epsilon = 0.0088564516;
hsluv.Hsluv.hexChars = "0123456789abcdef";
var root = {
    "hsluvToRgb": hsluv.Hsluv.hsluvToRgb,
    "rgbToHsluv": hsluv.Hsluv.rgbToHsluv,
    "hpluvToRgb": hsluv.Hsluv.hpluvToRgb,
    "rgbToHpluv": hsluv.Hsluv.rgbToHpluv,
    "hsluvToHex": hsluv.Hsluv.hsluvToHex,
    "hexToHsluv": hsluv.Hsluv.hexToHsluv,
    "hpluvToHex": hsluv.Hsluv.hpluvToHex,
    "hexToHpluv": hsluv.Hsluv.hexToHpluv,
    "lchToHpluv": hsluv.Hsluv.lchToHpluv,
    "hpluvToLch": hsluv.Hsluv.hpluvToLch,
    "lchToHsluv": hsluv.Hsluv.lchToHsluv,
    "hsluvToLch": hsluv.Hsluv.hsluvToLch,
    "lchToLuv": hsluv.Hsluv.lchToLuv,
    "luvToLch": hsluv.Hsluv.luvToLch,
    "xyzToLuv": hsluv.Hsluv.xyzToLuv,
    "luvToXyz": hsluv.Hsluv.luvToXyz,
    "xyzToRgb": hsluv.Hsluv.xyzToRgb,
    "rgbToXyz": hsluv.Hsluv.rgbToXyz,
    "lchToRgb": hsluv.Hsluv.lchToRgb,
    "rgbToLch": hsluv.Hsluv.rgbToLch
};

var hsluv_1 = root;

var canvas_utils = createCommonjsModule(function (module, exports) {
// Copyright (C) 2019 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.
Object.defineProperty(exports, "__esModule", { value: true });
exports.drawIncompleteSlice = exports.drawDoubleHeadedArrow = exports.cropText = void 0;
function cropText(str, charWidth, rectWidth) {
    let displayText = '';
    const maxLength = Math.floor(rectWidth / charWidth) - 1;
    if (str.length <= maxLength) {
        displayText = str;
    }
    else {
        let limit = maxLength;
        let maybeTripleDot = '';
        if (maxLength > 1) {
            limit = maxLength - 1;
            maybeTripleDot = '\u2026';
        }
        // Javascript strings are UTF-16. |limit| could point in the middle of a
        // 32-bit double-wchar codepoint (e.g., an emoji). Here we detect if the
        // |limit|-th wchar is a leading surrogate and attach the trailing one.
        const lastCharCode = str.charCodeAt(limit - 1);
        limit += (lastCharCode >= 0xD800 && lastCharCode < 0xDC00) ? 1 : 0;
        displayText = str.substring(0, limit) + maybeTripleDot;
    }
    return displayText;
}
exports.cropText = cropText;
function drawDoubleHeadedArrow(ctx, x, y, length, showArrowHeads, width = 2, color = 'black') {
    ctx.beginPath();
    ctx.lineWidth = width;
    ctx.lineCap = 'round';
    ctx.strokeStyle = color;
    ctx.moveTo(x, y);
    ctx.lineTo(x + length, y);
    ctx.stroke();
    ctx.closePath();
    // Arrowheads on the each end of the line.
    if (showArrowHeads) {
        ctx.beginPath();
        ctx.moveTo(x + length - 8, y - 4);
        ctx.lineTo(x + length, y);
        ctx.lineTo(x + length - 8, y + 4);
        ctx.stroke();
        ctx.closePath();
        ctx.beginPath();
        ctx.moveTo(x + 8, y - 4);
        ctx.lineTo(x, y);
        ctx.lineTo(x + 8, y + 4);
        ctx.stroke();
        ctx.closePath();
    }
}
exports.drawDoubleHeadedArrow = drawDoubleHeadedArrow;
function drawIncompleteSlice(ctx, x, y, length, width, color) {
    ctx.beginPath();
    ctx.fillStyle = color;
    const triangleSize = width / 4;
    ctx.moveTo(x, y);
    ctx.lineTo(x + length, y);
    ctx.lineTo(x + length - 3, y + triangleSize * 0.5);
    ctx.lineTo(x + length, y + triangleSize);
    ctx.lineTo(x + length - 3, y + (triangleSize * 1.5));
    ctx.lineTo(x + length, y + 2 * triangleSize);
    ctx.lineTo(x + length - 3, y + (triangleSize * 2.5));
    ctx.lineTo(x + length, y + 3 * triangleSize);
    ctx.lineTo(x + length - 3, y + (triangleSize * 3.5));
    ctx.lineTo(x + length, y + 4 * triangleSize);
    ctx.lineTo(x, y + width);
    ctx.fill();
}
exports.drawIncompleteSlice = drawIncompleteSlice;

});

var constants = createCommonjsModule(function (module, exports) {
// Copyright (C) 2021 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.
Object.defineProperty(exports, "__esModule", { value: true });
exports.TRACE_MARGIN_TIME_S = exports.TRACE_SUFFIX = void 0;
exports.TRACE_SUFFIX = '.perfetto-trace';
exports.TRACE_MARGIN_TIME_S = 1 / 1e7;

});

var common$9 = createCommonjsModule(function (module, exports) {
// 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.
Object.defineProperty(exports, "__esModule", { value: true });
exports.SLICE_TRACK_KIND = void 0;
exports.SLICE_TRACK_KIND = 'ChromeSliceTrack';

});

var frontend = createCommonjsModule(function (module, exports) {
// 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.
Object.defineProperty(exports, "__esModule", { value: true });
exports.ChromeSliceTrack = void 0;










const SLICE_HEIGHT = 18;
const TRACK_PADDING = 4;
const CHEVRON_WIDTH_PX = 10;
const HALF_CHEVRON_WIDTH_PX = CHEVRON_WIDTH_PX / 2;
const INNER_CHEVRON_OFFSET = -3;
const INNER_CHEVRON_SCALE = (SLICE_HEIGHT - 2 * INNER_CHEVRON_OFFSET) / SLICE_HEIGHT;
class ChromeSliceTrack extends track.Track {
    constructor(trackState) {
        super(trackState);
        this.hoveredTitleId = -1;
    }
    static create(trackState) {
        return new ChromeSliceTrack(trackState);
    }
    renderCanvas(ctx) {
        // TODO: fonts and colors should come from the CSS and not hardcoded here.
        const { timeScale, visibleWindowTime } = globals$1.globals.frontendLocalState;
        const data = this.data();
        if (data === undefined)
            return; // Can't possibly draw anything.
        // If the cached trace slices don't fully cover the visible time range,
        // show a gray rectangle with a "Loading..." label.
        checkerboard_1.checkerboardExcept(ctx, this.getHeight(), timeScale.timeToPx(visibleWindowTime.start), timeScale.timeToPx(visibleWindowTime.end), timeScale.timeToPx(data.start), timeScale.timeToPx(data.end));
        ctx.font = '12px Roboto Condensed';
        ctx.textAlign = 'center';
        // measuretext is expensive so we only use it once.
        const charWidth = ctx.measureText('ACBDLqsdfg').width / 10;
        // The draw of the rect on the selected slice must happen after the other
        // drawings, otherwise it would result under another rect.
        let drawRectOnSelected = () => { };
        for (let i = 0; i < data.starts.length; i++) {
            const tStart = data.starts[i];
            let tEnd = data.ends[i];
            const depth = data.depths[i];
            const titleId = data.titles[i];
            const sliceId = data.sliceIds[i];
            const isInstant = data.isInstant[i];
            const isIncomplete = data.isIncomplete[i];
            const title = data.strings[titleId];
            const colorOverride = data.colors && data.strings[data.colors[i]];
            if (isIncomplete) { // incomplete slice
                tEnd = visibleWindowTime.end;
            }
            const rect = this.getSliceRect(tStart, tEnd, depth);
            if (!rect || !rect.visible) {
                continue;
            }
            const currentSelection = globals$1.globals.state.currentSelection;
            const isSelected = currentSelection &&
                currentSelection.kind === 'CHROME_SLICE' &&
                currentSelection.id !== undefined && currentSelection.id === sliceId;
            const name = title.replace(/( )?\d+/g, '');
            const highlighted = titleId === this.hoveredTitleId ||
                globals$1.globals.frontendLocalState.highlightedSliceId === sliceId;
            const [hue, saturation, lightness] = colorizer.hslForSlice(name, highlighted || isSelected);
            let color;
            if (colorOverride === undefined) {
                color = hsluv_1.hsluvToHex([hue, saturation, lightness]);
            }
            else {
                color = colorOverride;
            }
            ctx.fillStyle = color;
            // We draw instant events as upward facing chevrons starting at A:
            //     A
            //    ###
            //   ##C##
            //  ##   ##
            // D       B
            // Then B, C, D and back to A:
            if (isInstant) {
                if (isSelected) {
                    drawRectOnSelected = () => {
                        ctx.save();
                        ctx.translate(rect.left, rect.top);
                        // Draw outer chevron as dark border
                        ctx.save();
                        ctx.translate(0, INNER_CHEVRON_OFFSET);
                        ctx.scale(INNER_CHEVRON_SCALE, INNER_CHEVRON_SCALE);
                        ctx.fillStyle = hsluv_1.hsluvToHex([hue, 100, 10]);
                        this.drawChevron(ctx);
                        ctx.restore();
                        // Draw inner chevron as interior
                        ctx.fillStyle = color;
                        this.drawChevron(ctx);
                        ctx.restore();
                    };
                }
                else {
                    ctx.save();
                    ctx.translate(rect.left, rect.top);
                    this.drawChevron(ctx);
                    ctx.restore();
                }
                continue;
            }
            if (isIncomplete && rect.width > SLICE_HEIGHT / 4) {
                canvas_utils.drawIncompleteSlice(ctx, rect.left, rect.top, rect.width, SLICE_HEIGHT, color);
            }
            else {
                ctx.fillRect(rect.left, rect.top, rect.width, SLICE_HEIGHT);
            }
            // Selected case
            if (isSelected) {
                drawRectOnSelected = () => {
                    ctx.strokeStyle = hsluv_1.hsluvToHex([hue, 100, 10]);
                    ctx.beginPath();
                    ctx.lineWidth = 3;
                    ctx.strokeRect(rect.left, rect.top - 1.5, rect.width, SLICE_HEIGHT + 3);
                    ctx.closePath();
                };
            }
            ctx.fillStyle = lightness > 65 ? '#404040' : 'white';
            const displayText = canvas_utils.cropText(title, charWidth, rect.width);
            const rectXCenter = rect.left + rect.width / 2;
            ctx.textBaseline = "middle";
            ctx.fillText(displayText, rectXCenter, rect.top + SLICE_HEIGHT / 2);
        }
        drawRectOnSelected();
    }
    drawChevron(ctx) {
        // Draw a chevron at a fixed location and size. Should be used with
        // ctx.translate and ctx.scale to alter location and size.
        ctx.beginPath();
        ctx.moveTo(0, 0);
        ctx.lineTo(HALF_CHEVRON_WIDTH_PX, SLICE_HEIGHT);
        ctx.lineTo(0, SLICE_HEIGHT - HALF_CHEVRON_WIDTH_PX);
        ctx.lineTo(-HALF_CHEVRON_WIDTH_PX, SLICE_HEIGHT);
        ctx.lineTo(0, 0);
        ctx.fill();
    }
    getSliceIndex({ x, y }) {
        const data = this.data();
        if (data === undefined)
            return;
        const { timeScale } = globals$1.globals.frontendLocalState;
        if (y < TRACK_PADDING)
            return;
        const instantWidthTime = timeScale.deltaPxToDuration(HALF_CHEVRON_WIDTH_PX);
        const t = timeScale.pxToTime(x);
        const depth = Math.floor((y - TRACK_PADDING) / SLICE_HEIGHT);
        for (let i = 0; i < data.starts.length; i++) {
            if (depth !== data.depths[i]) {
                continue;
            }
            const tStart = data.starts[i];
            if (data.isInstant[i]) {
                if (Math.abs(tStart - t) < instantWidthTime) {
                    return i;
                }
            }
            else {
                let tEnd = data.ends[i];
                if (data.isIncomplete[i]) {
                    tEnd = globals$1.globals.frontendLocalState.visibleWindowTime.end;
                }
                if (tStart <= t && t <= tEnd) {
                    return i;
                }
            }
        }
    }
    onMouseMove({ x, y }) {
        this.hoveredTitleId = -1;
        globals$1.globals.frontendLocalState.setHighlightedSliceId(-1);
        const sliceIndex = this.getSliceIndex({ x, y });
        if (sliceIndex === undefined)
            return;
        const data = this.data();
        if (data === undefined)
            return;
        this.hoveredTitleId = data.titles[sliceIndex];
        globals$1.globals.frontendLocalState.setHighlightedSliceId(data.sliceIds[sliceIndex]);
    }
    onMouseOut() {
        this.hoveredTitleId = -1;
        globals$1.globals.frontendLocalState.setHighlightedSliceId(-1);
    }
    onMouseClick({ x, y }) {
        const sliceIndex = this.getSliceIndex({ x, y });
        if (sliceIndex === undefined)
            return false;
        const data = this.data();
        if (data === undefined)
            return false;
        const sliceId = data.sliceIds[sliceIndex];
        if (sliceId !== undefined && sliceId !== -1) {
            globals$1.globals.makeSelection(actions.Actions.selectChromeSlice({
                id: sliceId,
                trackId: this.trackState.id,
                table: this.config.namespace
            }));
            return true;
        }
        return false;
    }
    getHeight() {
        return SLICE_HEIGHT * (this.config.maxDepth + 1) + 2 * TRACK_PADDING;
    }
    getSliceRect(tStart, tEnd, depth) {
        const { timeScale, visibleWindowTime } = globals$1.globals.frontendLocalState;
        const pxEnd = timeScale.timeToPx(visibleWindowTime.end);
        const left = Math.max(timeScale.timeToPx(tStart), -constants.TRACE_MARGIN_TIME_S);
        const right = Math.min(timeScale.timeToPx(tEnd), pxEnd);
        return {
            left,
            width: Math.max(right - left, 1),
            top: TRACK_PADDING + depth * SLICE_HEIGHT,
            height: SLICE_HEIGHT,
            visible: !(tEnd <= visibleWindowTime.start || tStart >= visibleWindowTime.end)
        };
    }
}
exports.ChromeSliceTrack = ChromeSliceTrack;
ChromeSliceTrack.kind = common$9.SLICE_TRACK_KIND;
track_registry.trackRegistry.register(ChromeSliceTrack);

});

var binary_search = createCommonjsModule(function (module, exports) {
// 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.
Object.defineProperty(exports, "__esModule", { value: true });
exports.searchSegment = exports.searchRange = exports.searchEq = exports.search = void 0;
function searchImpl(haystack, needle, i, j) {
    if (i === j)
        return -1;
    if (i + 1 === j) {
        return (needle >= haystack[i]) ? i : -1;
    }
    const mid = Math.floor((j - i) / 2) + i;
    const midValue = haystack[mid];
    if (needle < midValue) {
        return searchImpl(haystack, needle, i, mid);
    }
    else {
        return searchImpl(haystack, needle, mid, j);
    }
}
function searchRangeImpl(haystack, needle, i, j) {
    if (i === j)
        return [i, j];
    if (i + 1 === j) {
        if (haystack[i] <= needle) {
            return [i, j];
        }
        else {
            return [i, i];
        }
    }
    const mid = Math.floor((j - i) / 2) + i;
    const midValue = haystack[mid];
    if (needle < midValue) {
        return searchRangeImpl(haystack, needle, i, mid);
    }
    else if (needle > midValue) {
        return searchRangeImpl(haystack, needle, mid, j);
    }
    else {
        while (haystack[i] !== needle)
            i++;
        while (haystack[j - 1] !== needle)
            j--;
        return [i, j];
    }
}
function search(haystack, needle) {
    return searchImpl(haystack, needle, 0, haystack.length);
}
exports.search = search;
/**
 * Given a sorted array of numbers (|haystack|) and a |needle| return the
 * half open range [i, j) of indexes where |haystack| is equal to needle.
 */
function searchEq(haystack, needle, optRange) {
    const range = searchRange(haystack, needle, optRange);
    const [i, j] = range;
    if (haystack[i] === needle)
        return range;
    return [j, j];
}
exports.searchEq = searchEq;
/**
 * Given a sorted array of numbers (|haystack|) and a |needle| return the
 * smallest half open range [i, j) of indexes which contains |needle|.
 */
function searchRange(haystack, needle, optRange) {
    const [left, right] = optRange ? optRange : [0, haystack.length];
    return searchRangeImpl(haystack, needle, left, right);
}
exports.searchRange = searchRange;
/**
 * Given a sorted array of numbers (|haystack|) and a |needle| return a
 * pair of indexes [i, j] such that:
 * If there is at least one element in |haystack| smaller than |needle|
 * i is the index of the largest such number otherwise -1;
 * If there is at least one element in |haystack| larger than |needle|
 * j is the index of the smallest such element otherwise -1.
 *
 * So we try to get the indexes of the two data points around needle
 * or -1 if there is no such datapoint.
 */
function searchSegment(haystack, needle) {
    if (!haystack.length)
        return [-1, -1];
    const left = search(haystack, needle);
    if (left === -1) {
        return [left, 0];
    }
    else if (left + 1 === haystack.length) {
        return [left, -1];
    }
    else {
        return [left, left + 1];
    }
}
exports.searchSegment = searchSegment;

});

var css_constants = createCommonjsModule(function (module, exports) {
// Copyright (C) 2019 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.
Object.defineProperty(exports, "__esModule", { value: true });
exports.initCssConstants = exports.TOPBAR_HEIGHT = exports.TRACK_BORDER_COLOR = exports.SIDEBAR_WIDTH = exports.TRACK_SHELL_WIDTH = void 0;
// This code can be used in unittests where we can't read CSS variables.
// Also we cannot have global constructors beacause when the javascript is
// loaded, the CSS might not be ready yet.
exports.TRACK_SHELL_WIDTH = 100;
exports.SIDEBAR_WIDTH = 100;
exports.TRACK_BORDER_COLOR = '#ffc0cb';
exports.TOPBAR_HEIGHT = 48;
function initCssConstants() {
    exports.TRACK_SHELL_WIDTH = getCssNum('--track-shell-width') || exports.TRACK_SHELL_WIDTH;
    exports.SIDEBAR_WIDTH = getCssNum('--sidebar-width') || exports.SIDEBAR_WIDTH;
    exports.TRACK_BORDER_COLOR = getCssStr('--track-border-color') || exports.TRACK_BORDER_COLOR;
    exports.TOPBAR_HEIGHT = getCssNum('--topbar-height') || exports.TOPBAR_HEIGHT;
}
exports.initCssConstants = initCssConstants;
function getCssStr(prop) {
    if (typeof window === 'undefined')
        return undefined;
    const body = window.document.body;
    return window.getComputedStyle(body).getPropertyValue(prop);
}
function getCssNum(prop) {
    const str = getCssStr(prop);
    if (str === undefined)
        return undefined;
    const match = str.match(/^\W*(\d+)px$/);
    if (!match)
        throw Error(`Could not parse CSS property "${str}" as a number`);
    return Number(match[1]);
}

});

var gridline_helper = createCommonjsModule(function (module, exports) {
// 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.
Object.defineProperty(exports, "__esModule", { value: true });
exports.drawGridLines = exports.gridlines = exports.getGridStepSize = exports.DESIRED_PX_PER_STEP = void 0;

exports.DESIRED_PX_PER_STEP = 80;
/**
 * Returns the step size of a grid line in seconds.
 * The returned step size has two properties:
 * (1) It is 1, 2, or 5, multiplied by some integer power of 10.
 * (2) The number steps in |range| produced by |stepSize| is as close as
 *     possible to |desiredSteps|.
 */
function getGridStepSize(range, desiredSteps) {
    // First, get the largest possible power of 10 that is smaller than the
    // desired step size, and set it to the current step size.
    // For example, if the range is 2345ms and the desired steps is 10, then the
    // desired step size is 234.5 and the step size will be set to 100.
    const desiredStepSize = range / desiredSteps;
    const zeros = Math.floor(Math.log10(desiredStepSize));
    const initialStepSize = Math.pow(10, zeros);
    // This function first calculates how many steps within the range a certain
    // stepSize will produce, and returns the difference between that and
    // desiredSteps.
    const distToDesired = (evaluatedStepSize) => Math.abs(range / evaluatedStepSize - desiredSteps);
    // We know that |initialStepSize| is a power of 10, and
    // initialStepSize <= desiredStepSize <= 10 * initialStepSize. There are four
    // possible candidates for final step size: 1, 2, 5 or 10 * initialStepSize.
    // We pick the candidate that minimizes distToDesired(stepSize).
    const stepSizeMultipliers = [2, 5, 10];
    let minimalDistance = distToDesired(initialStepSize);
    let minimizingStepSize = initialStepSize;
    for (const multiplier of stepSizeMultipliers) {
        const newStepSize = multiplier * initialStepSize;
        const newDistance = distToDesired(newStepSize);
        if (newDistance < minimalDistance) {
            minimalDistance = newDistance;
            minimizingStepSize = newStepSize;
        }
    }
    return minimizingStepSize;
}
exports.getGridStepSize = getGridStepSize;
/**
 * Generator that returns that (given a width im px, span, and scale) returns
 * pairs of [xInPx, timestampInS] pairs describing where gridlines should be
 * drawn.
 */
function gridlines(width, span, timescale) {
    const desiredSteps = width / exports.DESIRED_PX_PER_STEP;
    const step = getGridStepSize(span.duration, desiredSteps);
    const actualSteps = Math.floor(span.duration / step);
    const start = Math.round(span.start / step) * step;
    const lines = [];
    let previousTimestamp = Number.NEGATIVE_INFINITY;
    // Iterating over the number of steps instead of
    // for (let s = start; s < span.end; s += step) because if start is very large
    // number and step very small, s will never reach end.
    for (let i = 0; i <= actualSteps; i++) {
        let xPos = css_constants.TRACK_SHELL_WIDTH;
        const timestamp = start + i * step;
        xPos += Math.floor(timescale.timeToPx(timestamp));
        if (xPos < css_constants.TRACK_SHELL_WIDTH)
            continue;
        if (xPos > width)
            break;
        if (Math.abs(timestamp - previousTimestamp) > Number.EPSILON) {
            previousTimestamp = timestamp;
            lines.push([xPos, timestamp]);
        }
    }
    return lines;
}
exports.gridlines = gridlines;
function drawGridLines(ctx, x, timeSpan, width, height) {
    ctx.strokeStyle = css_constants.TRACK_BORDER_COLOR;
    ctx.lineWidth = 1;
    for (const xAndTime of gridlines(width, timeSpan, x)) {
        ctx.beginPath();
        ctx.moveTo(xAndTime[0] + 0.5, 0);
        ctx.lineTo(xAndTime[0] + 0.5, height);
        ctx.stroke();
    }
}
exports.drawGridLines = drawGridLines;

});

var icons = createCommonjsModule(function (module, exports) {
// Copyright (C) 2020 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.
Object.defineProperty(exports, "__esModule", { value: true });
exports.STAR_BORDER = exports.STAR = exports.EXPAND_UP = exports.EXPAND_DOWN = exports.INDETERMINATE_CHECKBOX = exports.CHECKBOX = exports.BLANK_CHECKBOX = void 0;
exports.BLANK_CHECKBOX = 'check_box_outline_blank';
exports.CHECKBOX = 'check_box';
exports.INDETERMINATE_CHECKBOX = 'indeterminate_check_box';
exports.EXPAND_DOWN = 'expand_more';
exports.EXPAND_UP = 'expand_less';
exports.STAR = 'star';
exports.STAR_BORDER = 'star_border';

});

var panel = createCommonjsModule(function (module, exports) {
// 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.
Object.defineProperty(exports, "__esModule", { value: true });
exports.isPanelVNode = exports.Panel = void 0;
class Panel {
}
exports.Panel = Panel;
function isPanelVNode(vnode) {
    const tag = vnode.tag;
    return (typeof tag === 'function' && 'prototype' in tag &&
        tag.prototype instanceof Panel);
}
exports.isPanelVNode = isPanelVNode;

});

var scroll_helper = createCommonjsModule(function (module, exports) {
// Copyright (C) 2019 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.
Object.defineProperty(exports, "__esModule", { value: true });
exports.findUiTrackId = exports.scrollToTrackAndTs = exports.verticalScrollToTrack = exports.horizontalScrollAndZoomToRange = exports.horizontalScrollToTs = void 0;




const INCOMPLETE_SLICE_TIME_S = 0.00003;
/**
 * Given a timestamp, if |ts| is not currently in view move the view to
 * center |ts|, keeping the same zoom level.
 */
function horizontalScrollToTs(ts) {
    const startNs = time.toNs(globals$1.globals.frontendLocalState.visibleWindowTime.start);
    const endNs = time.toNs(globals$1.globals.frontendLocalState.visibleWindowTime.end);
    const currentViewNs = endNs - startNs;
    if (ts < startNs || ts > endNs) {
        // TODO(hjd): This is an ugly jump, we should do a smooth pan instead.
        globals$1.globals.frontendLocalState.updateVisibleTime(new time.TimeSpan(time.fromNs(ts - currentViewNs / 2), time.fromNs(ts + currentViewNs / 2)));
    }
}
exports.horizontalScrollToTs = horizontalScrollToTs;
/**
 * Given a start and end timestamp (in ns), move the view to center this range
 * and zoom to a level where the range is 1/5 of the viewport.
 */
function horizontalScrollAndZoomToRange(startTs, endTs) {
    const visibleDur = globals$1.globals.frontendLocalState.visibleWindowTime.end -
        globals$1.globals.frontendLocalState.visibleWindowTime.start;
    let selectDur = endTs - startTs;
    if (time.toNs(selectDur) === -1) { // Unfinished slice
        selectDur = INCOMPLETE_SLICE_TIME_S;
        endTs = startTs;
    }
    const viewStartNs = time.toNs(globals$1.globals.frontendLocalState.visibleWindowTime.start);
    const viewEndNs = time.toNs(globals$1.globals.frontendLocalState.visibleWindowTime.end);
    if (selectDur / visibleDur < 0.05 || startTs < viewStartNs ||
        endTs > viewEndNs) {
        globals$1.globals.frontendLocalState.updateVisibleTime(new time.TimeSpan(startTs - (selectDur * 2), endTs + (selectDur * 2)));
    }
}
exports.horizontalScrollAndZoomToRange = horizontalScrollAndZoomToRange;
/**
 * Given a track id, find a track with that id and scroll it into view. If the
 * track is nested inside a track group, scroll to that track group instead.
 * If |openGroup| then open the track group and scroll to the track.
 */
function verticalScrollToTrack(trackId, openGroup = false) {
    const trackIdString = `${trackId}`;
    const track = document.querySelector('#track_' + trackIdString);
    if (track) {
        // block: 'nearest' means that it will only scroll if the track is not
        // currently in view.
        track.scrollIntoView({ behavior: 'smooth', block: 'nearest' });
        return;
    }
    let trackGroup = null;
    const trackGroupId = state.getContainingTrackId(globals$1.globals.state, trackIdString);
    if (trackGroupId) {
        trackGroup = document.querySelector('#track_' + trackGroupId);
    }
    if (!trackGroupId || !trackGroup) {
        console.error(`Can't scroll, track (${trackIdString}) not found.`);
        return;
    }
    // The requested track is inside a closed track group, either open the track
    // group and scroll to the track or just scroll to the track group.
    if (openGroup) {
        // After the track exists in the dom, it will be scrolled to.
        globals$1.globals.frontendLocalState.scrollToTrackId = trackId;
        globals$1.globals.dispatch(actions.Actions.toggleTrackGroupCollapsed({ trackGroupId }));
        return;
    }
    else {
        trackGroup.scrollIntoView({ behavior: 'smooth', block: 'nearest' });
    }
}
exports.verticalScrollToTrack = verticalScrollToTrack;
/**
 * Scroll vertically and horizontally to reach track (|trackId|) at |ts|.
 */
function scrollToTrackAndTs(trackId, ts, openGroup = false) {
    if (trackId !== undefined) {
        verticalScrollToTrack(trackId, openGroup);
    }
    horizontalScrollToTs(ts);
}
exports.scrollToTrackAndTs = scrollToTrackAndTs;
/**
 * Returns the UI track Id that is associated with the given |traceTrackId| in
 * the trace_processor. Due to concepts like Async tracks and TrackGroups this
 * is not always a one to one mapping.
 */
function findUiTrackId(traceTrackId) {
    for (const [uiTrackId, trackState] of Object.entries(globals$1.globals.state.tracks)) {
        const config = trackState.config;
        if (config.trackId === traceTrackId)
            return uiTrackId;
        const multiple = trackState.config;
        if (multiple.trackIds !== undefined &&
            multiple.trackIds.includes(traceTrackId)) {
            return uiTrackId;
        }
    }
    return null;
}
exports.findUiTrackId = findUiTrackId;

});

var vertical_line_helper = createCommonjsModule(function (module, exports) {
// Copyright (C) 2019 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.
Object.defineProperty(exports, "__esModule", { value: true });
exports.drawVerticalLineAtTime = void 0;

function drawVerticalLineAtTime(ctx, timeScale, time, height, color, lineWidth = 2) {
    const xPos = css_constants.TRACK_SHELL_WIDTH + Math.floor(timeScale.timeToPx(time));
    drawVerticalLine(ctx, xPos, height, color, lineWidth);
}
exports.drawVerticalLineAtTime = drawVerticalLineAtTime;
function drawVerticalLine(ctx, xPos, height, color, lineWidth = 2) {
    ctx.beginPath();
    ctx.strokeStyle = color;
    const prevLineWidth = ctx.lineWidth;
    ctx.lineWidth = lineWidth;
    ctx.moveTo(xPos, 0);
    ctx.lineTo(xPos, height);
    ctx.stroke();
    ctx.closePath();
    ctx.lineWidth = prevLineWidth;
}

});

var track_panel = createCommonjsModule(function (module, exports) {
// 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.
Object.defineProperty(exports, "__esModule", { value: true });
exports.TrackPanel = exports.TrackButton = exports.TrackContent = void 0;











function isPinned(id) {
    return globals$1.globals.state.pinnedTracks.indexOf(id) !== -1;
}
function isSelected(id) {
    const selection = globals$1.globals.state.currentSelection;
    if (selection === null || selection.kind !== 'AREA')
        return false;
    const selectedArea = globals$1.globals.state.areas[selection.areaId];
    return selectedArea.tracks.includes(id);
}
class TrackShell {
    constructor() {
        // Set to true when we click down and drag the
        this.dragging = false;
        this.dropping = undefined;
    }
    oninit(vnode) {
        this.attrs = vnode.attrs;
    }
    view({ attrs }) {
        // The shell should be highlighted if the current search result is inside
        // this track.
        let highlightClass = '';
        const searchIndex = globals$1.globals.frontendLocalState.searchIndex;
        if (searchIndex !== -1) {
            const trackId = globals$1.globals.currentSearchResults
                .trackIds[globals$1.globals.frontendLocalState.searchIndex];
            if (trackId === attrs.trackState.id) {
                highlightClass = 'flash';
            }
        }
        const dragClass = this.dragging ? `drag` : '';
        const dropClass = this.dropping ? `drop-${this.dropping}` : '';
        return mithril(`.track-shell[draggable=true]`, {
            class: `${highlightClass} ${dragClass} ${dropClass}`,
            onmousedown: this.onmousedown.bind(this),
            ondragstart: this.ondragstart.bind(this),
            ondragend: this.ondragend.bind(this),
            ondragover: this.ondragover.bind(this),
            ondragleave: this.ondragleave.bind(this),
            ondrop: this.ondrop.bind(this),
        }, mithril('h1', {
            title: attrs.trackState.name,
        }, attrs.trackState.name), mithril('.track-buttons', attrs.track.getTrackShellButtons(), mithril(TrackButton, {
            action: () => {
                globals$1.globals.dispatch(actions.Actions.toggleTrackPinned({ trackId: attrs.trackState.id }));
            },
            i: isPinned(attrs.trackState.id) ? icons.STAR : icons.STAR_BORDER,
            tooltip: isPinned(attrs.trackState.id) ? 'Unpin' : 'Pin to top',
            showButton: isPinned(attrs.trackState.id),
        }), globals$1.globals.state.currentSelection !== null &&
            globals$1.globals.state.currentSelection.kind === 'AREA' ?
            mithril(TrackButton, {
                action: (e) => {
                    globals$1.globals.dispatch(actions.Actions.toggleTrackSelection({ id: attrs.trackState.id, isTrackGroup: false }));
                    e.stopPropagation();
                },
                i: isSelected(attrs.trackState.id) ? icons.CHECKBOX : icons.BLANK_CHECKBOX,
                tooltip: isSelected(attrs.trackState.id) ?
                    'Remove track' :
                    'Add track to selection',
                showButton: true,
            }) :
            ''));
    }
    onmousedown(e) {
        // Prevent that the click is intercepted by the PanAndZoomHandler and that
        // we start panning while dragging.
        e.stopPropagation();
    }
    ondragstart(e) {
        const dataTransfer = e.dataTransfer;
        if (dataTransfer === null)
            return;
        this.dragging = true;
        globals$1.globals.rafScheduler.scheduleFullRedraw();
        dataTransfer.setData('perfetto/track', `${this.attrs.trackState.id}`);
        dataTransfer.setDragImage(new Image(), 0, 0);
        e.stopImmediatePropagation();
    }
    ondragend() {
        this.dragging = false;
        globals$1.globals.rafScheduler.scheduleFullRedraw();
    }
    ondragover(e) {
        if (this.dragging)
            return;
        if (!(e.target instanceof HTMLElement))
            return;
        const dataTransfer = e.dataTransfer;
        if (dataTransfer === null)
            return;
        if (!dataTransfer.types.includes('perfetto/track'))
            return;
        dataTransfer.dropEffect = 'move';
        e.preventDefault();
        // Apply some hysteresis to the drop logic so that the lightened border
        // changes only when we get close enough to the border.
        if (e.offsetY < e.target.scrollHeight / 3) {
            this.dropping = 'before';
        }
        else if (e.offsetY > e.target.scrollHeight / 3 * 2) {
            this.dropping = 'after';
        }
        globals$1.globals.rafScheduler.scheduleFullRedraw();
    }
    ondragleave() {
        this.dropping = undefined;
        globals$1.globals.rafScheduler.scheduleFullRedraw();
    }
    ondrop(e) {
        if (this.dropping === undefined)
            return;
        const dataTransfer = e.dataTransfer;
        if (dataTransfer === null)
            return;
        globals$1.globals.rafScheduler.scheduleFullRedraw();
        const srcId = dataTransfer.getData('perfetto/track');
        const dstId = this.attrs.trackState.id;
        globals$1.globals.dispatch(actions.Actions.moveTrack({ srcId, op: this.dropping, dstId }));
        this.dropping = undefined;
    }
}
class TrackContent {
    constructor() {
        this.selectionOccurred = false;
    }
    view({ attrs }) {
        return mithril('.track-content', {
            onmousemove: (e) => {
                attrs.track.onMouseMove({ x: e.layerX - css_constants.TRACK_SHELL_WIDTH, y: e.layerY });
                globals$1.globals.rafScheduler.scheduleRedraw();
            },
            onmouseout: () => {
                attrs.track.onMouseOut();
                globals$1.globals.rafScheduler.scheduleRedraw();
            },
            onmousedown: (e) => {
                this.mouseDownX = e.layerX;
                this.mouseDownY = e.layerY;
            },
            onmouseup: (e) => {
                if (this.mouseDownX === undefined || this.mouseDownY === undefined) {
                    return;
                }
                if (Math.abs(e.layerX - this.mouseDownX) > 1 ||
                    Math.abs(e.layerY - this.mouseDownY) > 1) {
                    this.selectionOccurred = true;
                }
                this.mouseDownX = undefined;
                this.mouseDownY = undefined;
            },
            onclick: (e) => {
                // This click event occurs after any selection mouse up/drag events
                // so we have to look if the mouse moved during this click to know
                // if a selection occurred.
                if (this.selectionOccurred) {
                    this.selectionOccurred = false;
                    return;
                }
                // Returns true if something was selected, so stop propagation.
                if (attrs.track.onMouseClick({ x: e.layerX - css_constants.TRACK_SHELL_WIDTH, y: e.layerY })) {
                    e.stopPropagation();
                }
                globals$1.globals.rafScheduler.scheduleRedraw();
            }
        });
    }
}
exports.TrackContent = TrackContent;
class TrackComponent {
    view({ attrs }) {
        return mithril('.track', {
            style: {
                height: `${Math.max(24, attrs.track.getHeight())}px`,
            },
            id: 'track_' + attrs.trackState.id,
        }, [
            mithril(TrackShell, { track: attrs.track, trackState: attrs.trackState }),
            mithril(TrackContent, { track: attrs.track })
        ]);
    }
    oncreate({ attrs }) {
        if (globals$1.globals.frontendLocalState.scrollToTrackId === attrs.trackState.id) {
            scroll_helper.verticalScrollToTrack(attrs.trackState.id);
            globals$1.globals.frontendLocalState.scrollToTrackId = undefined;
        }
    }
}
class TrackButton {
    view({ attrs }) {
        return mithril('i.material-icons.track-button', {
            class: `${attrs.showButton ? 'show' : ''}`,
            onclick: attrs.action,
            title: attrs.tooltip,
        }, attrs.i);
    }
}
exports.TrackButton = TrackButton;
class TrackPanel extends panel.Panel {
    constructor(vnode) {
        super();
        this.trackState = globals$1.globals.state.tracks[vnode.attrs.id];
        const trackCreator = track_registry.trackRegistry.get(this.trackState.kind);
        this.track = trackCreator.create(this.trackState);
    }
    view() {
        return mithril(TrackComponent, { trackState: this.trackState, track: this.track });
    }
    highlightIfTrackSelected(ctx, size) {
        const localState = globals$1.globals.frontendLocalState;
        const selection = globals$1.globals.state.currentSelection;
        if (!selection || selection.kind !== 'AREA')
            return;
        const selectedArea = globals$1.globals.state.areas[selection.areaId];
        if (selectedArea.tracks.includes(this.trackState.id)) {
            const timeScale = localState.timeScale;
            ctx.fillStyle = 'rgba(131, 152, 230, 0.3)';
            ctx.fillRect(timeScale.timeToPx(selectedArea.startSec) + css_constants.TRACK_SHELL_WIDTH, 0, timeScale.deltaTimeToPx(selectedArea.endSec - selectedArea.startSec), size.height);
        }
    }
    renderCanvas(ctx, size) {
        ctx.save();
        gridline_helper.drawGridLines(ctx, globals$1.globals.frontendLocalState.timeScale, globals$1.globals.frontendLocalState.visibleWindowTime, size.width, size.height);
        ctx.translate(css_constants.TRACK_SHELL_WIDTH, 0);
        this.track.render(ctx);
        ctx.restore();
        this.highlightIfTrackSelected(ctx, size);
        const localState = globals$1.globals.frontendLocalState;
        // Draw vertical line when hovering on the notes panel.
        if (localState.hoveredNoteTimestamp !== -1) {
            vertical_line_helper.drawVerticalLineAtTime(ctx, localState.timeScale, localState.hoveredNoteTimestamp, size.height, `#aaa`);
        }
        if (localState.hoveredLogsTimestamp !== -1) {
            vertical_line_helper.drawVerticalLineAtTime(ctx, localState.timeScale, localState.hoveredLogsTimestamp, size.height, `#344596`);
        }
        if (globals$1.globals.state.currentSelection !== null) {
            if (globals$1.globals.state.currentSelection.kind === 'NOTE') {
                const note = globals$1.globals.state.notes[globals$1.globals.state.currentSelection.id];
                if (note.noteType === 'DEFAULT') {
                    vertical_line_helper.drawVerticalLineAtTime(ctx, localState.timeScale, note.timestamp, size.height, note.color);
                }
            }
            if (globals$1.globals.state.currentSelection.kind === 'SLICE' &&
                globals$1.globals.sliceDetails.wakeupTs !== undefined) {
                vertical_line_helper.drawVerticalLineAtTime(ctx, localState.timeScale, globals$1.globals.sliceDetails.wakeupTs, size.height, `black`);
            }
        }
        // All marked areas should have semi-transparent vertical lines
        // marking the start and end.
        for (const note of Object.values(globals$1.globals.state.notes)) {
            if (note.noteType === 'AREA') {
                const transparentNoteColor = 'rgba(' + colorConvert.hex.rgb(note.color.substr(1)).toString() + ', 0.65)';
                vertical_line_helper.drawVerticalLineAtTime(ctx, localState.timeScale, globals$1.globals.state.areas[note.areaId].startSec, size.height, transparentNoteColor, 1);
                vertical_line_helper.drawVerticalLineAtTime(ctx, localState.timeScale, globals$1.globals.state.areas[note.areaId].endSec, size.height, transparentNoteColor, 1);
            }
        }
    }
    getSliceRect(tStart, tDur, depth) {
        return this.track.getSliceRect(tStart, tDur, depth);
    }
}
exports.TrackPanel = TrackPanel;

});

createCommonjsModule(function (module, exports) {
// 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.
Object.defineProperty(exports, "__esModule", { value: true });











// 0.5 Makes the horizontal lines sharp.
const MARGIN_TOP = 3.5;
const RECT_HEIGHT = 24.5;
function scaleTooltip(scale) {
    const description = getCounterScaleAttribute(scale);
    const source = description.tooltip;
    const destination = getCounterScaleAttribute(description.follower).tooltip;
    return `Toggle scale from ${source} to ${destination}`;
}
function scaleIcon(scale) {
    return getCounterScaleAttribute(scale).icon;
}
function nextScale(scale) {
    return getCounterScaleAttribute(scale).follower;
}
function getCounterScaleAttribute(scale) {
    switch (scale) {
        case 'MIN_MAX':
            return {
                follower: 'DELTA_FROM_PREVIOUS',
                tooltip: 'min/max',
                icon: 'show_chart'
            };
        case 'DELTA_FROM_PREVIOUS':
            return { follower: 'ZERO_BASED', tooltip: 'delta', icon: 'bar_chart' };
        case 'ZERO_BASED':
        default:
            return {
                follower: 'MIN_MAX',
                tooltip: 'zero based',
                icon: 'waterfall_chart'
            };
    }
}
class CounterTrack extends track.Track {
    constructor(trackState) {
        super(trackState);
        this.mouseXpos = 0;
        this.hoveredValue = undefined;
        this.hoveredTs = undefined;
        this.hoveredTsEnd = undefined;
    }
    static create(trackState) {
        return new CounterTrack(trackState);
    }
    getHeight() {
        return MARGIN_TOP + RECT_HEIGHT;
    }
    getTrackShellButtons() {
        const buttons = [];
        buttons.push(mithril(track_panel.TrackButton, {
            action: () => {
                this.config.scale = nextScale(this.config.scale);
                actions.Actions.updateTrackConfig({ id: this.trackState.id, config: this.config });
                globals$1.globals.rafScheduler.scheduleFullRedraw();
            },
            i: scaleIcon(this.config.scale),
            tooltip: scaleTooltip(this.config.scale),
            showButton: !!this.config.scale && this.config.scale !== 'ZERO_BASED',
        }));
        return buttons;
    }
    renderCanvas(ctx) {
        // TODO: fonts and colors should come from the CSS and not hardcoded here.
        const { timeScale, visibleWindowTime } = globals$1.globals.frontendLocalState;
        const data = this.data();
        // Can't possibly draw anything.
        if (data === undefined || data.timestamps.length === 0) {
            return;
        }
        logging.assertTrue(data.timestamps.length === data.minValues.length);
        logging.assertTrue(data.timestamps.length === data.maxValues.length);
        logging.assertTrue(data.timestamps.length === data.lastValues.length);
        logging.assertTrue(data.timestamps.length === data.totalDeltas.length);
        const scale = this.config.scale || 'ZERO_BASED';
        let minValues = data.minValues;
        let maxValues = data.maxValues;
        let lastValues = data.lastValues;
        let maximumValue = data.maximumValue;
        let minimumValue = data.minimumValue;
        if (scale === 'DELTA_FROM_PREVIOUS') {
            lastValues = data.totalDeltas;
            minValues = data.totalDeltas;
            maxValues = data.totalDeltas;
            maximumValue = data.maximumDelta;
            minimumValue = data.minimumDelta;
        }
        const endPx = Math.floor(timeScale.timeToPx(visibleWindowTime.end));
        const zeroY = MARGIN_TOP + RECT_HEIGHT / (minimumValue < 0 ? 2 : 1);
        // Quantize the Y axis to quarters of powers of tens (7.5K, 10K, 12.5K).
        const maxValue = Math.max(maximumValue, 0);
        let yMax = Math.max(Math.abs(minimumValue), maxValue);
        const kUnits = ['', 'K', 'M', 'G', 'T', 'E'];
        const exp = Math.ceil(Math.log10(Math.max(yMax, 1)));
        const pow10 = Math.pow(10, exp);
        yMax = Math.ceil(yMax / (pow10 / 4)) * (pow10 / 4);
        let yRange = 0;
        const unitGroup = Math.floor(exp / 3);
        let yMin = 0;
        let yLabel = '';
        if (scale === 'MIN_MAX') {
            yRange = maximumValue - minimumValue;
            yMin = minimumValue;
            yLabel = 'min - max';
        }
        else {
            yRange = minimumValue < 0 ? yMax * 2 : yMax;
            yMin = minimumValue < 0 ? -yMax : 0;
            yLabel = `${yMax / Math.pow(10, unitGroup * 3)} ${kUnits[unitGroup]}`;
            if (scale === 'DELTA_FROM_PREVIOUS') {
                yLabel += '\u0394';
            }
        }
        // There are 360deg of hue. We want a scale that starts at green with
        // exp <= 3 (<= 1KB), goes orange around exp = 6 (~1MB) and red/violet
        // around exp >= 9 (1GB).
        // The hue scale looks like this:
        // 0                              180                                 360
        // Red        orange         green | blue         purple          magenta
        // So we want to start @ 180deg with pow=0, go down to 0deg and then wrap
        // back from 360deg back to 180deg.
        const expCapped = Math.min(Math.max(exp - 3), 9);
        const hue = (180 - Math.floor(expCapped * (180 / 6)) + 360) % 360;
        ctx.fillStyle = `hsl(${hue}, 45%, 75%)`;
        ctx.strokeStyle = `hsl(${hue}, 45%, 45%)`;
        const calculateX = (ts) => {
            return Math.floor(timeScale.timeToPx(ts));
        };
        const calculateY = (value) => {
            return MARGIN_TOP + RECT_HEIGHT -
                Math.round(((value - yMin) / yRange) * RECT_HEIGHT);
        };
        ctx.beginPath();
        ctx.moveTo(calculateX(data.timestamps[0]), zeroY);
        let lastDrawnY = zeroY;
        for (let i = 0; i < data.timestamps.length; i++) {
            const x = calculateX(data.timestamps[i]);
            const minY = calculateY(minValues[i]);
            const maxY = calculateY(maxValues[i]);
            const lastY = calculateY(lastValues[i]);
            ctx.lineTo(x, lastDrawnY);
            if (minY === maxY) {
                logging.assertTrue(lastY === minY);
                ctx.lineTo(x, lastY);
            }
            else {
                ctx.lineTo(x, minY);
                ctx.lineTo(x, maxY);
                ctx.lineTo(x, lastY);
            }
            lastDrawnY = lastY;
        }
        ctx.lineTo(endPx, lastDrawnY);
        ctx.lineTo(endPx, zeroY);
        ctx.closePath();
        ctx.fill();
        ctx.stroke();
        // Draw the Y=0 dashed line.
        ctx.strokeStyle = `hsl(${hue}, 10%, 71%)`;
        ctx.beginPath();
        ctx.setLineDash([2, 4]);
        ctx.moveTo(0, zeroY);
        ctx.lineTo(endPx, zeroY);
        ctx.closePath();
        ctx.stroke();
        ctx.setLineDash([]);
        ctx.font = '10px Roboto Condensed';
        if (this.hoveredValue !== undefined && this.hoveredTs !== undefined) {
            // TODO(hjd): Add units.
            let text = scale === 'DELTA_FROM_PREVIOUS' ? 'delta: ' : 'value: ';
            text += `${this.hoveredValue.toLocaleString()}`;
            ctx.fillStyle = `hsl(${hue}, 45%, 75%)`;
            ctx.strokeStyle = `hsl(${hue}, 45%, 45%)`;
            const xStart = Math.floor(timeScale.timeToPx(this.hoveredTs));
            const xEnd = this.hoveredTsEnd === undefined ?
                endPx :
                Math.floor(timeScale.timeToPx(this.hoveredTsEnd));
            const y = MARGIN_TOP + RECT_HEIGHT -
                Math.round(((this.hoveredValue - yMin) / yRange) * RECT_HEIGHT);
            // Highlight line.
            ctx.beginPath();
            ctx.moveTo(xStart, y);
            ctx.lineTo(xEnd, y);
            ctx.lineWidth = 3;
            ctx.stroke();
            ctx.lineWidth = 1;
            // Draw change marker.
            ctx.beginPath();
            ctx.arc(xStart, y, 3 /*r*/, 0 /*start angle*/, 2 * Math.PI /*end angle*/);
            ctx.fill();
            ctx.stroke();
            // Draw the tooltip.
            this.drawTrackHoverTooltip(ctx, this.mouseXpos, text);
        }
        // Write the Y scale on the top left corner.
        ctx.fillStyle = 'rgba(255, 255, 255, 0.6)';
        ctx.fillRect(0, 0, 42, 16);
        ctx.fillStyle = '#666';
        ctx.textAlign = 'left';
        ctx.textBaseline = 'alphabetic';
        ctx.fillText(`${yLabel}`, 5, 14);
        // TODO(hjd): Refactor this into checkerboardExcept
        {
            const endPx = timeScale.timeToPx(visibleWindowTime.end);
            const counterEndPx = Math.min(timeScale.timeToPx(this.config.endTs || Infinity), endPx);
            // Grey out RHS.
            if (counterEndPx < endPx) {
                ctx.fillStyle = '#0000001f';
                ctx.fillRect(counterEndPx, 0, endPx - counterEndPx, this.getHeight());
            }
        }
        // If the cached trace slices don't fully cover the visible time range,
        // show a gray rectangle with a "Loading..." label.
        checkerboard_1.checkerboardExcept(ctx, this.getHeight(), timeScale.timeToPx(visibleWindowTime.start), timeScale.timeToPx(visibleWindowTime.end), timeScale.timeToPx(data.start), timeScale.timeToPx(data.end));
    }
    onMouseMove({ x }) {
        const data = this.data();
        if (data === undefined)
            return;
        this.mouseXpos = x;
        const { timeScale } = globals$1.globals.frontendLocalState;
        const time = timeScale.pxToTime(x);
        const values = this.config.scale === 'DELTA_FROM_PREVIOUS' ?
            data.totalDeltas :
            data.lastValues;
        const [left, right] = binary_search.searchSegment(data.timestamps, time);
        this.hoveredTs = left === -1 ? undefined : data.timestamps[left];
        this.hoveredTsEnd = right === -1 ? undefined : data.timestamps[right];
        this.hoveredValue = left === -1 ? undefined : values[left];
    }
    onMouseOut() {
        this.hoveredValue = undefined;
        this.hoveredTs = undefined;
    }
    onMouseClick({ x }) {
        const data = this.data();
        if (data === undefined)
            return false;
        const { timeScale } = globals$1.globals.frontendLocalState;
        const time$1 = timeScale.pxToTime(x);
        const [left, right] = binary_search.searchSegment(data.timestamps, time$1);
        if (left === -1) {
            return false;
        }
        else {
            const counterId = data.lastIds[left];
            if (counterId === -1)
                return true;
            globals$1.globals.makeSelection(actions.Actions.selectCounter({
                leftTs: time.toNs(data.timestamps[left]),
                rightTs: right !== -1 ? time.toNs(data.timestamps[right]) : -1,
                id: counterId,
                trackId: this.trackState.id
            }));
            return true;
        }
    }
}
CounterTrack.kind = common$2.COUNTER_TRACK_KIND;
track_registry.trackRegistry.register(CounterTrack);

});

var flamegraph = createCommonjsModule(function (module, exports) {
// 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.
Object.defineProperty(exports, "__esModule", { value: true });
exports.splitIfTooBig = exports.Flamegraph = exports.findRootSize = exports.HEAP_PROFILE_HOVERED_COLOR = void 0;


// Height of one 'row' on the flame chart including 1px of whitespace
// below the box.
const NODE_HEIGHT = 18;
exports.HEAP_PROFILE_HOVERED_COLOR = 'hsl(224, 45%, 55%)';
function findRootSize(data) {
    let totalSize = 0;
    let i = 0;
    while (i < data.length && data[i].depth === 0) {
        totalSize += data[i].totalSize;
        i++;
    }
    return totalSize;
}
exports.findRootSize = findRootSize;
class Flamegraph {
    constructor(flamegraphData) {
        this.nodeRendering = {};
        this.highlightSomeNodes = false;
        this.maxDepth = -1;
        this.totalSize = -1;
        // Initialised on first draw() call
        this.labelCharWidth = 0;
        this.labelFontStyle = '12px Roboto Mono';
        this.rolloverFontStyle = '12px Roboto Condensed';
        // Key for the map is depth followed by x coordinate - `depth;x`
        this.graphData = new Map();
        this.xStartsPerDepth = new Map();
        this.hoveredX = -1;
        this.hoveredY = -1;
        this.startingY = 0;
        this.flamegraphData = flamegraphData;
        this.findMaxDepth();
    }
    findMaxDepth() {
        this.maxDepth = Math.max(...this.flamegraphData.map(value => value.depth));
    }
    // Instead of highlighting the interesting nodes, we actually want to
    // de-emphasize the non-highlighted nodes. Returns true if there
    // are any highlighted nodes in the flamegraph.
    highlightingExists() {
        this.highlightSomeNodes = this.flamegraphData.some((e) => e.highlighted);
    }
    generateColor(name, isGreyedOut = false, highlighted) {
        if (isGreyedOut) {
            return '#d9d9d9';
        }
        if (name === 'unknown' || name === 'root') {
            return '#c0c0c0';
        }
        let x = 0;
        for (let i = 0; i < name.length; i += 1) {
            x += name.charCodeAt(i) % 64;
        }
        x = x % 360;
        let l = '76';
        // Make non-highlighted node lighter.
        if (this.highlightSomeNodes && !highlighted) {
            l = '90';
        }
        return `hsl(${x}deg, 45%, ${l}%)`;
    }
    /**
     * Caller will have to call draw method after updating data to have updated
     * graph.
     */
    updateDataIfChanged(nodeRendering, flamegraphData, clickedCallsite) {
        this.nodeRendering = nodeRendering;
        this.clickedCallsite = clickedCallsite;
        if (this.flamegraphData === flamegraphData) {
            return;
        }
        this.flamegraphData = flamegraphData;
        this.clickedCallsite = clickedCallsite;
        this.findMaxDepth();
        this.highlightingExists();
        // Finding total size of roots.
        this.totalSize = findRootSize(flamegraphData);
    }
    draw(ctx, width, height, x = 0, y = 0, unit = 'B') {
        if (this.flamegraphData === undefined) {
            return;
        }
        ctx.font = this.labelFontStyle;
        ctx.textBaseline = 'middle';
        if (this.labelCharWidth === 0) {
            this.labelCharWidth = ctx.measureText('_').width;
        }
        this.startingY = y;
        // For each node, we use this map to get information about it's parent
        // (total size of it, width and where it starts in graph) so we can
        // calculate it's own position in graph.
        const nodesMap = new Map();
        let currentY = y;
        nodesMap.set(-1, { width, nextXForChildren: x, size: this.totalSize, x });
        // Initialize data needed for click/hover behavior.
        this.graphData = new Map();
        this.xStartsPerDepth = new Map();
        // Draw root node.
        ctx.fillStyle = this.generateColor('root', false, false);
        ctx.fillRect(x, currentY, width, NODE_HEIGHT - 1);
        const text = canvas_utils.cropText(`root: ${this.displaySize(this.totalSize, unit, unit === 'B' ? 1024 : 1000)}`, this.labelCharWidth, width - 2);
        ctx.fillStyle = 'black';
        ctx.fillText(text, x + 5, currentY + (NODE_HEIGHT - 1) / 2);
        currentY += NODE_HEIGHT;
        // Set style for borders.
        ctx.strokeStyle = 'white';
        ctx.lineWidth = 0.5;
        for (let i = 0; i < this.flamegraphData.length; i++) {
            if (currentY > height) {
                break;
            }
            const value = this.flamegraphData[i];
            const parentNode = nodesMap.get(value.parentId);
            if (parentNode === undefined) {
                continue;
            }
            const isClicked = this.clickedCallsite !== undefined;
            const isFullWidth = isClicked && value.depth <= this.clickedCallsite.depth;
            const isGreyedOut = isClicked && value.depth < this.clickedCallsite.depth;
            const parent = value.parentId;
            const parentSize = parent === -1 ? this.totalSize : parentNode.size;
            // Calculate node's width based on its proportion in parent.
            const width = (isFullWidth ? 1 : value.totalSize / parentSize) * parentNode.width;
            const currentX = parentNode.nextXForChildren;
            currentY = y + NODE_HEIGHT * (value.depth + 1);
            // Draw node.
            const name = this.getCallsiteName(value);
            ctx.fillStyle = this.generateColor(name, isGreyedOut, value.highlighted);
            ctx.fillRect(currentX, currentY, width, NODE_HEIGHT - 1);
            // Set current node's data in map for children to use.
            nodesMap.set(value.id, {
                width,
                nextXForChildren: currentX,
                size: value.totalSize,
                x: currentX
            });
            // Update next x coordinate in parent.
            nodesMap.set(value.parentId, {
                width: parentNode.width,
                nextXForChildren: currentX + width,
                size: parentNode.size,
                x: parentNode.x
            });
            // Draw name.
            const labelPaddingPx = 5;
            const maxLabelWidth = width - labelPaddingPx * 2;
            let text = canvas_utils.cropText(name, this.labelCharWidth, maxLabelWidth);
            // If cropped text and the original text are within 20% we keep the
            // original text and just squish it a bit.
            if (text.length * 1.2 > name.length) {
                text = name;
            }
            ctx.fillStyle = 'black';
            ctx.fillText(text, currentX + labelPaddingPx, currentY + (NODE_HEIGHT - 1) / 2, maxLabelWidth);
            // Draw border on the right of node.
            ctx.beginPath();
            ctx.moveTo(currentX + width, currentY);
            ctx.lineTo(currentX + width, currentY + NODE_HEIGHT);
            ctx.stroke();
            // Add this node for recognizing in click/hover.
            // Map graphData contains one callsite which is on that depth and X
            // start. Map xStartsPerDepth for each depth contains all X start
            // coordinates that callsites on that level have.
            this.graphData.set(`${value.depth};${currentX}`, { callsite: value, width });
            const xStarts = this.xStartsPerDepth.get(value.depth);
            if (xStarts === undefined) {
                this.xStartsPerDepth.set(value.depth, [currentX]);
            }
            else {
                xStarts.push(currentX);
            }
        }
        // Draw the tooltip.
        if (this.hoveredX > -1 && this.hoveredY > -1 && this.hoveredCallsite) {
            // Must set these before measureText below.
            ctx.font = this.rolloverFontStyle;
            ctx.textBaseline = 'top';
            // Size in px of the border around the text and the edge of the rollover
            // background.
            const paddingPx = 8;
            // Size in px of the x and y offset between the mouse and the top left
            // corner of the rollover box.
            const offsetPx = 4;
            const lines = [];
            let textWidth = this.addToTooltip(this.getCallsiteName(this.hoveredCallsite), width - paddingPx, ctx, lines);
            if (this.hoveredCallsite.location != null) {
                textWidth = Math.max(textWidth, this.addToTooltip(this.hoveredCallsite.location, width, ctx, lines));
            }
            textWidth = Math.max(textWidth, this.addToTooltip(this.hoveredCallsite.mapping, width, ctx, lines));
            if (this.nodeRendering.totalSize !== undefined) {
                const percentage = this.hoveredCallsite.totalSize / this.totalSize * 100;
                const totalSizeText = `${this.nodeRendering.totalSize}: ${this.displaySize(this.hoveredCallsite.totalSize, unit, unit === 'B' ? 1024 : 1000)} (${percentage.toFixed(2)}%)`;
                textWidth = Math.max(textWidth, this.addToTooltip(totalSizeText, width, ctx, lines));
            }
            if (this.nodeRendering.selfSize !== undefined &&
                this.hoveredCallsite.selfSize > 0) {
                const selfPercentage = this.hoveredCallsite.selfSize / this.totalSize * 100;
                const selfSizeText = `${this.nodeRendering.selfSize}: ${this.displaySize(this.hoveredCallsite.selfSize, unit, unit === 'B' ? 1024 : 1000)} (${selfPercentage.toFixed(2)}%)`;
                textWidth = Math.max(textWidth, this.addToTooltip(selfSizeText, width, ctx, lines));
            }
            // Compute a line height as the bounding box height + 50%:
            const heightSample = ctx.measureText('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ');
            const lineHeight = Math.round(heightSample.actualBoundingBoxDescent * 1.5);
            const rectWidth = textWidth + 2 * paddingPx;
            const rectHeight = lineHeight * lines.length + 2 * paddingPx;
            let rectXStart = this.hoveredX + offsetPx;
            let rectYStart = this.hoveredY + offsetPx;
            if (rectXStart + rectWidth > width) {
                rectXStart = width - rectWidth;
            }
            if (rectYStart + rectHeight > height) {
                rectYStart = height - rectHeight;
            }
            ctx.fillStyle = 'rgba(255, 255, 255, 0.9)';
            ctx.fillRect(rectXStart, rectYStart, rectWidth, rectHeight);
            ctx.fillStyle = 'hsl(200, 50%, 40%)';
            ctx.textAlign = 'left';
            for (let i = 0; i < lines.length; i++) {
                const line = lines[i];
                ctx.fillText(line, rectXStart + paddingPx, rectYStart + paddingPx + i * lineHeight);
            }
        }
    }
    addToTooltip(text, width, ctx, lines) {
        const lineSplitter = splitIfTooBig(text, width, ctx.measureText(text).width);
        lines.push(...lineSplitter.lines);
        return lineSplitter.lineWidth;
    }
    getCallsiteName(value) {
        return value.name === undefined || value.name === '' ? 'unknown' :
            value.name;
    }
    displaySize(totalSize, unit, step = 1024) {
        if (unit === '')
            return totalSize.toLocaleString();
        if (totalSize === 0)
            return `0 ${unit}`;
        let units = [];
        if (unit === "s") {
            units = [
                ['u', 1],
                ['m', step],
                ['', Math.pow(step, 2)],
            ];
        }
        else {
            units = [
                ['', 1],
                ['K', step],
                ['M', Math.pow(step, 2)],
                ['G', Math.pow(step, 3)]
            ];
        }
        let unitsIndex = Math.trunc(Math.log(totalSize) / Math.log(step));
        unitsIndex = unitsIndex > units.length - 1 ? units.length - 1 : unitsIndex;
        const result = totalSize / +units[unitsIndex][1];
        const resultString = totalSize % +units[unitsIndex][1] === 0 ?
            result.toString() :
            result.toFixed(2);
        return `${resultString} ${units[unitsIndex][0]}${unit}`;
    }
    onMouseMove({ x, y }) {
        this.hoveredX = x;
        this.hoveredY = y;
        this.hoveredCallsite = this.findSelectedCallsite(x, y);
        const isCallsiteSelected = this.hoveredCallsite !== undefined;
        if (!isCallsiteSelected) {
            this.onMouseOut();
        }
        return isCallsiteSelected;
    }
    onMouseOut() {
        this.hoveredX = -1;
        this.hoveredY = -1;
        this.hoveredCallsite = undefined;
    }
    onMouseClick({ x, y }) {
        const clickedCallsite = this.findSelectedCallsite(x, y);
        // TODO(b/148596659): Allow to expand [merged] callsites. Currently,
        // this expands to the biggest of the nodes that were merged, which
        // is confusing, so we disallow clicking on them.
        if (clickedCallsite === undefined || clickedCallsite.merged) {
            return undefined;
        }
        return clickedCallsite;
    }
    findSelectedCallsite(x, y) {
        const depth = Math.trunc((y - this.startingY) / NODE_HEIGHT) - 1; // at 0 is root
        if (depth >= 0 && this.xStartsPerDepth.has(depth)) {
            const startX = this.searchSmallest(this.xStartsPerDepth.get(depth), x);
            const result = this.graphData.get(`${depth};${startX}`);
            if (result !== undefined) {
                const width = result.width;
                return startX + width >= x ? result.callsite : undefined;
            }
        }
        return undefined;
    }
    searchSmallest(haystack, needle) {
        haystack = haystack.sort((n1, n2) => n1 - n2);
        const [left,] = binary_search.searchSegment(haystack, needle);
        return left === -1 ? -1 : haystack[left];
    }
    getHeight() {
        return this.flamegraphData.length === 0 ? 0 :
            (this.maxDepth + 2) * NODE_HEIGHT;
    }
}
exports.Flamegraph = Flamegraph;
function splitIfTooBig(line, width, lineWidth) {
    if (line === '')
        return { lineWidth, lines: [] };
    const lines = [];
    const charWidth = lineWidth / line.length;
    const maxWidth = width - 32;
    const maxLineLen = Math.trunc(maxWidth / charWidth);
    while (line.length > 0) {
        lines.push(line.slice(0, maxLineLen));
        line = line.slice(maxLineLen);
    }
    lineWidth = Math.min(maxLineLen * charWidth, lineWidth);
    return { lineWidth, lines };
}
exports.splitIfTooBig = splitIfTooBig;

});

createCommonjsModule(function (module, exports) {
// Copyright (C) 2019 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.
Object.defineProperty(exports, "__esModule", { value: true });








const HEAP_PROFILE_COLOR = 'hsl(224, 45%, 70%)';
// 0.5 Makes the horizontal lines sharp.
const MARGIN_TOP = 4.5;
const RECT_HEIGHT = 30.5;
class HeapProfileTrack extends track.Track {
    constructor(trackState) {
        super(trackState);
        this.centerY = this.getHeight() / 2;
        this.markerWidth = (this.getHeight() - MARGIN_TOP) / 2;
        this.hoveredTs = undefined;
    }
    static create(trackState) {
        return new HeapProfileTrack(trackState);
    }
    getHeight() {
        return MARGIN_TOP + RECT_HEIGHT - 1;
    }
    renderCanvas(ctx) {
        const { timeScale, } = globals$1.globals.frontendLocalState;
        const data = this.data();
        if (data === undefined)
            return;
        for (let i = 0; i < data.tsStarts.length; i++) {
            const centerX = data.tsStarts[i];
            const selection = globals$1.globals.state.currentSelection;
            const isHovered = this.hoveredTs === centerX;
            const isSelected = selection !== null &&
                selection.kind === 'HEAP_PROFILE' && selection.ts === centerX;
            const strokeWidth = isSelected ? 3 : 0;
            this.drawMarker(ctx, timeScale.timeToPx(time.fromNs(centerX)), this.centerY, isHovered, strokeWidth);
        }
    }
    drawMarker(ctx, x, y, isHovered, strokeWidth) {
        ctx.beginPath();
        ctx.moveTo(x, y - this.markerWidth);
        ctx.lineTo(x - this.markerWidth, y);
        ctx.lineTo(x, y + this.markerWidth);
        ctx.lineTo(x + this.markerWidth, y);
        ctx.lineTo(x, y - this.markerWidth);
        ctx.closePath();
        ctx.fillStyle = isHovered ? flamegraph.HEAP_PROFILE_HOVERED_COLOR : HEAP_PROFILE_COLOR;
        ctx.fill();
        if (strokeWidth > 0) {
            ctx.strokeStyle = flamegraph.HEAP_PROFILE_HOVERED_COLOR;
            ctx.lineWidth = strokeWidth;
            ctx.stroke();
        }
    }
    onMouseMove({ x, y }) {
        const data = this.data();
        if (data === undefined)
            return;
        const { timeScale } = globals$1.globals.frontendLocalState;
        const time$1 = time.toNs(timeScale.pxToTime(x));
        const [left, right] = binary_search.searchSegment(data.tsStarts, time$1);
        const index = this.findTimestampIndex(left, timeScale, data, x, y, right);
        this.hoveredTs = index === -1 ? undefined : data.tsStarts[index];
    }
    onMouseOut() {
        this.hoveredTs = undefined;
    }
    onMouseClick({ x, y }) {
        const data = this.data();
        if (data === undefined)
            return false;
        const { timeScale } = globals$1.globals.frontendLocalState;
        const time$1 = time.toNs(timeScale.pxToTime(x));
        const [left, right] = binary_search.searchSegment(data.tsStarts, time$1);
        const index = this.findTimestampIndex(left, timeScale, data, x, y, right);
        if (index !== -1) {
            const ts = data.tsStarts[index];
            const type = data.types[index];
            globals$1.globals.makeSelection(actions.Actions.selectHeapProfile({ id: index, upid: this.config.upid, ts, type }));
            return true;
        }
        return false;
    }
    // If the markers overlap the rightmost one will be selected.
    findTimestampIndex(left, timeScale, data, x, y, right) {
        let index = -1;
        if (left !== -1) {
            const centerX = timeScale.timeToPx(time.fromNs(data.tsStarts[left]));
            if (this.isInMarker(x, y, centerX)) {
                index = left;
            }
        }
        if (right !== -1) {
            const centerX = timeScale.timeToPx(time.fromNs(data.tsStarts[right]));
            if (this.isInMarker(x, y, centerX)) {
                index = right;
            }
        }
        return index;
    }
    isInMarker(x, y, centerX) {
        return Math.abs(x - centerX) + Math.abs(y - this.centerY) <=
            this.markerWidth;
    }
}
HeapProfileTrack.kind = common$5.HEAP_PROFILE_TRACK_KIND;
track_registry.trackRegistry.register(HeapProfileTrack);

});

var common$a = createCommonjsModule(function (module, exports) {
Object.defineProperty(exports, "__esModule", { value: true });
exports.CPU_FREQ_TRACK_KIND = void 0;
exports.CPU_FREQ_TRACK_KIND = 'CpuFreqTrack';

});

createCommonjsModule(function (module, exports) {
// Copyright (C) 2019 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.
Object.defineProperty(exports, "__esModule", { value: true });








// 0.5 Makes the horizontal lines sharp.
const MARGIN_TOP = 4.5;
const RECT_HEIGHT = 20;
class CpuFreqTrack extends track.Track {
    constructor(trackState) {
        super(trackState);
        this.mouseXpos = 0;
        this.hoveredValue = undefined;
        this.hoveredTs = undefined;
        this.hoveredTsEnd = undefined;
        this.hoveredIdle = undefined;
    }
    static create(trackState) {
        return new CpuFreqTrack(trackState);
    }
    getHeight() {
        return MARGIN_TOP + RECT_HEIGHT;
    }
    renderCanvas(ctx) {
        // TODO: fonts and colors should come from the CSS and not hardcoded here.
        const { timeScale, visibleWindowTime } = globals$1.globals.frontendLocalState;
        const data = this.data();
        if (data === undefined || data.timestamps.length === 0) {
            // Can't possibly draw anything.
            return;
        }
        logging.assertTrue(data.timestamps.length === data.lastFreqKHz.length);
        logging.assertTrue(data.timestamps.length === data.minFreqKHz.length);
        logging.assertTrue(data.timestamps.length === data.maxFreqKHz.length);
        logging.assertTrue(data.timestamps.length === data.lastIdleValues.length);
        const endPx = timeScale.timeToPx(visibleWindowTime.end);
        const zeroY = MARGIN_TOP + RECT_HEIGHT;
        // Quantize the Y axis to quarters of powers of tens (7.5K, 10K, 12.5K).
        let yMax = data.maximumValue;
        const kUnits = ['', 'K', 'M', 'G', 'T', 'E'];
        const exp = Math.ceil(Math.log10(Math.max(yMax, 1)));
        const pow10 = Math.pow(10, exp);
        yMax = Math.ceil(yMax / (pow10 / 4)) * (pow10 / 4);
        const unitGroup = Math.floor(exp / 3);
        const num = yMax / Math.pow(10, unitGroup * 3);
        // The values we have for cpufreq are in kHz so +1 to unitGroup.
        const yLabel = `${num} ${kUnits[unitGroup + 1]}Hz`;
        // Draw the CPU frequency graph.
        const hue = colorizer.hueForCpu(this.config.cpu);
        let saturation = 45;
        if (globals$1.globals.frontendLocalState.hoveredUtid !== -1) {
            saturation = 0;
        }
        ctx.fillStyle = `hsl(${hue}, ${saturation}%, 70%)`;
        ctx.strokeStyle = `hsl(${hue}, ${saturation}%, 55%)`;
        const calculateX = (timestamp) => {
            return Math.floor(timeScale.timeToPx(timestamp));
        };
        const calculateY = (value) => {
            return zeroY - Math.round((value / yMax) * RECT_HEIGHT);
        };
        const [rawStartIdx,] = binary_search.searchSegment(data.timestamps, visibleWindowTime.start);
        const startIdx = rawStartIdx === -1 ? 0 : rawStartIdx;
        const [, rawEndIdx] = binary_search.searchSegment(data.timestamps, visibleWindowTime.end);
        const endIdx = rawEndIdx === -1 ? data.timestamps.length : rawEndIdx;
        ctx.beginPath();
        ctx.moveTo(Math.max(calculateX(data.timestamps[startIdx]), 0), zeroY);
        let lastDrawnY = zeroY;
        for (let i = startIdx; i < endIdx; i++) {
            const x = calculateX(data.timestamps[i]);
            const minY = calculateY(data.minFreqKHz[i]);
            const maxY = calculateY(data.maxFreqKHz[i]);
            const lastY = calculateY(data.lastFreqKHz[i]);
            ctx.lineTo(x, lastDrawnY);
            if (minY === maxY) {
                logging.assertTrue(lastY === minY);
                ctx.lineTo(x, lastY);
            }
            else {
                ctx.lineTo(x, minY);
                ctx.lineTo(x, maxY);
                ctx.lineTo(x, lastY);
            }
            lastDrawnY = lastY;
        }
        // Find the end time for the last frequency event and then draw
        // down to zero to show that we do not have data after that point.
        const finalX = Math.min(calculateX(data.maxTsEnd), endPx);
        ctx.lineTo(finalX, lastDrawnY);
        ctx.lineTo(finalX, zeroY);
        ctx.lineTo(endPx, zeroY);
        ctx.closePath();
        ctx.fill();
        ctx.stroke();
        // Draw CPU idle rectangles that overlay the CPU freq graph.
        ctx.fillStyle = `rgba(240, 240, 240, 1)`;
        for (let i = 0; i < data.lastIdleValues.length; i++) {
            if (data.lastIdleValues[i] < 0) {
                continue;
            }
            // We intentionally don't use the floor function here when computing x
            // coordinates. Instead we use floating point which prevents flickering as
            // we pan and zoom; this relies on the browser anti-aliasing pixels
            // correctly.
            const x = timeScale.timeToPx(data.timestamps[i]);
            const xEnd = i === data.lastIdleValues.length - 1 ?
                finalX :
                timeScale.timeToPx(data.timestamps[i + 1]);
            const width = xEnd - x;
            const height = calculateY(data.lastFreqKHz[i]) - zeroY;
            ctx.fillRect(x, zeroY, width, height);
        }
        ctx.font = '10px Roboto Condensed';
        if (this.hoveredValue !== undefined && this.hoveredTs !== undefined) {
            let text = `${this.hoveredValue.toLocaleString()}kHz`;
            ctx.fillStyle = `hsl(${hue}, 45%, 75%)`;
            ctx.strokeStyle = `hsl(${hue}, 45%, 45%)`;
            const xStart = Math.floor(timeScale.timeToPx(this.hoveredTs));
            const xEnd = this.hoveredTsEnd === undefined ?
                endPx :
                Math.floor(timeScale.timeToPx(this.hoveredTsEnd));
            const y = zeroY - Math.round((this.hoveredValue / yMax) * RECT_HEIGHT);
            // Highlight line.
            ctx.beginPath();
            ctx.moveTo(xStart, y);
            ctx.lineTo(xEnd, y);
            ctx.lineWidth = 3;
            ctx.stroke();
            ctx.lineWidth = 1;
            // Draw change marker.
            ctx.beginPath();
            ctx.arc(xStart, y, 3 /*r*/, 0 /*start angle*/, 2 * Math.PI /*end angle*/);
            ctx.fill();
            ctx.stroke();
            // Display idle value if current hover is idle.
            if (this.hoveredIdle !== undefined && this.hoveredIdle !== -1) {
                // Display the idle value +1 to be consistent with catapult.
                text += ` (Idle: ${(this.hoveredIdle + 1).toLocaleString()})`;
            }
            // Draw the tooltip.
            this.drawTrackHoverTooltip(ctx, this.mouseXpos, text);
        }
        // Write the Y scale on the top left corner.
        ctx.textBaseline = 'alphabetic';
        ctx.fillStyle = 'rgba(255, 255, 255, 0.6)';
        ctx.fillRect(0, 0, 42, 18);
        ctx.fillStyle = '#666';
        ctx.textAlign = 'left';
        ctx.fillText(`${yLabel}`, 4, 14);
        // If the cached trace slices don't fully cover the visible time range,
        // show a gray rectangle with a "Loading..." label.
        checkerboard_1.checkerboardExcept(ctx, this.getHeight(), timeScale.timeToPx(visibleWindowTime.start), timeScale.timeToPx(visibleWindowTime.end), timeScale.timeToPx(data.start), timeScale.timeToPx(data.end));
    }
    onMouseMove({ x }) {
        const data = this.data();
        if (data === undefined)
            return;
        this.mouseXpos = x;
        const { timeScale } = globals$1.globals.frontendLocalState;
        const time = timeScale.pxToTime(x);
        const [left, right] = binary_search.searchSegment(data.timestamps, time);
        this.hoveredTs = left === -1 ? undefined : data.timestamps[left];
        this.hoveredTsEnd = right === -1 ? undefined : data.timestamps[right];
        this.hoveredValue = left === -1 ? undefined : data.lastFreqKHz[left];
        this.hoveredIdle = left === -1 ? undefined : data.lastIdleValues[left];
    }
    onMouseOut() {
        this.hoveredValue = undefined;
        this.hoveredTs = undefined;
        this.hoveredTsEnd = undefined;
        this.hoveredIdle = undefined;
    }
}
CpuFreqTrack.kind = common$a.CPU_FREQ_TRACK_KIND;
track_registry.trackRegistry.register(CpuFreqTrack);

});

var common$b = createCommonjsModule(function (module, exports) {
// Copyright (C) 2020 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.
Object.defineProperty(exports, "__esModule", { value: true });
exports.CPU_PROFILE_TRACK_KIND = void 0;
exports.CPU_PROFILE_TRACK_KIND = 'CpuProfileTrack';

});

createCommonjsModule(function (module, exports) {
// Copyright (C) 2020 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.
Object.defineProperty(exports, "__esModule", { value: true });









const MARGIN_TOP = 4.5;
const RECT_HEIGHT = 30.5;
function colorForSample(callsiteId, isHovered) {
    return hsluv_1.hsluvToHex(colorizer.hslForSlice(String(callsiteId), isHovered));
}
class CpuProfileTrack extends track.Track {
    constructor(trackState) {
        super(trackState);
        this.centerY = this.getHeight() / 2;
        this.markerWidth = (this.getHeight() - MARGIN_TOP) / 2;
        this.hoveredTs = undefined;
    }
    static create(trackState) {
        return new CpuProfileTrack(trackState);
    }
    getHeight() {
        return MARGIN_TOP + RECT_HEIGHT - 1;
    }
    renderCanvas(ctx) {
        const { timeScale, } = globals$1.globals.frontendLocalState;
        const data = this.data();
        if (data === undefined)
            return;
        for (let i = 0; i < data.tsStarts.length; i++) {
            const centerX = data.tsStarts[i];
            const selection = globals$1.globals.state.currentSelection;
            const isHovered = this.hoveredTs === centerX;
            const isSelected = selection !== null &&
                selection.kind === 'CPU_PROFILE_SAMPLE' && selection.ts === centerX;
            const strokeWidth = isSelected ? 3 : 0;
            this.drawMarker(ctx, timeScale.timeToPx(time.fromNs(centerX)), this.centerY, isHovered, strokeWidth, data.callsiteId[i]);
        }
    }
    drawMarker(ctx, x, y, isHovered, strokeWidth, callsiteId) {
        ctx.beginPath();
        ctx.moveTo(x - this.markerWidth, y - this.markerWidth);
        ctx.lineTo(x, y + this.markerWidth);
        ctx.lineTo(x + this.markerWidth, y - this.markerWidth);
        ctx.lineTo(x - this.markerWidth, y - this.markerWidth);
        ctx.closePath();
        ctx.fillStyle = colorForSample(callsiteId, isHovered);
        ctx.fill();
        if (strokeWidth > 0) {
            ctx.strokeStyle = colorForSample(callsiteId, false);
            ctx.lineWidth = strokeWidth;
            ctx.stroke();
        }
    }
    onMouseMove({ x, y }) {
        const data = this.data();
        if (data === undefined)
            return;
        const { timeScale } = globals$1.globals.frontendLocalState;
        const time$1 = time.toNs(timeScale.pxToTime(x));
        const [left, right] = binary_search.searchSegment(data.tsStarts, time$1);
        const index = this.findTimestampIndex(left, timeScale, data, x, y, right);
        this.hoveredTs = index === -1 ? undefined : data.tsStarts[index];
    }
    onMouseOut() {
        this.hoveredTs = undefined;
    }
    onMouseClick({ x, y }) {
        const data = this.data();
        if (data === undefined)
            return false;
        const { timeScale } = globals$1.globals.frontendLocalState;
        const time$1 = time.toNs(timeScale.pxToTime(x));
        const [left, right] = binary_search.searchSegment(data.tsStarts, time$1);
        const index = this.findTimestampIndex(left, timeScale, data, x, y, right);
        if (index !== -1) {
            const id = data.ids[index];
            const ts = data.tsStarts[index];
            globals$1.globals.makeSelection(actions.Actions.selectCpuProfileSample({ id, utid: this.config.utid, ts }));
            return true;
        }
        return false;
    }
    // If the markers overlap the rightmost one will be selected.
    findTimestampIndex(left, timeScale, data, x, y, right) {
        let index = -1;
        if (left !== -1) {
            const centerX = timeScale.timeToPx(time.fromNs(data.tsStarts[left]));
            if (this.isInMarker(x, y, centerX)) {
                index = left;
            }
        }
        if (right !== -1) {
            const centerX = timeScale.timeToPx(time.fromNs(data.tsStarts[right]));
            if (this.isInMarker(x, y, centerX)) {
                index = right;
            }
        }
        return index;
    }
    isInMarker(x, y, centerX) {
        return Math.abs(x - centerX) + Math.abs(y - this.centerY) <=
            this.markerWidth;
    }
}
CpuProfileTrack.kind = common$b.CPU_PROFILE_TRACK_KIND;
track_registry.trackRegistry.register(CpuProfileTrack);

});

var common$c = createCommonjsModule(function (module, exports) {
// 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.
Object.defineProperty(exports, "__esModule", { value: true });
exports.CPU_SLICE_TRACK_KIND = void 0;
exports.CPU_SLICE_TRACK_KIND = 'CpuSliceTrack';

});

createCommonjsModule(function (module, exports) {
// 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.
Object.defineProperty(exports, "__esModule", { value: true });











const MARGIN_TOP = 3;
const RECT_HEIGHT = 24;
const TRACK_HEIGHT = MARGIN_TOP * 2 + RECT_HEIGHT;
class CpuSliceTrack extends track.Track {
    constructor(trackState) {
        super(trackState);
        this.utidHoveredInThisTrack = -1;
    }
    static create(trackState) {
        return new CpuSliceTrack(trackState);
    }
    getHeight() {
        return TRACK_HEIGHT;
    }
    renderCanvas(ctx) {
        // TODO: fonts and colors should come from the CSS and not hardcoded here.
        const { timeScale, visibleWindowTime } = globals$1.globals.frontendLocalState;
        const data = this.data();
        if (data === undefined)
            return; // Can't possibly draw anything.
        // If the cached trace slices don't fully cover the visible time range,
        // show a gray rectangle with a "Loading..." label.
        checkerboard_1.checkerboardExcept(ctx, this.getHeight(), timeScale.timeToPx(visibleWindowTime.start), timeScale.timeToPx(visibleWindowTime.end), timeScale.timeToPx(data.start), timeScale.timeToPx(data.end));
        this.renderSlices(ctx, data);
    }
    renderSlices(ctx, data) {
        const { timeScale, visibleWindowTime } = globals$1.globals.frontendLocalState;
        logging.assertTrue(data.starts.length === data.ends.length);
        logging.assertTrue(data.starts.length === data.utids.length);
        ctx.textAlign = 'center';
        ctx.font = '12px Roboto Condensed';
        const charWidth = ctx.measureText('dbpqaouk').width / 8;
        const rawStartIdx = data.ends.findIndex(end => end >= visibleWindowTime.start);
        const startIdx = rawStartIdx === -1 ? 0 : rawStartIdx;
        const [, rawEndIdx] = binary_search.searchSegment(data.starts, visibleWindowTime.end);
        const endIdx = rawEndIdx === -1 ? data.starts.length : rawEndIdx;
        for (let i = startIdx; i < endIdx; i++) {
            const tStart = data.starts[i];
            const tEnd = data.ends[i];
            const utid = data.utids[i];
            const rectStart = timeScale.timeToPx(tStart);
            const rectEnd = timeScale.timeToPx(tEnd);
            const rectWidth = Math.max(1, rectEnd - rectStart);
            const threadInfo = globals$1.globals.threads.get(utid);
            const pid = threadInfo && threadInfo.pid ? threadInfo.pid : -1;
            const isHovering = globals$1.globals.frontendLocalState.hoveredUtid !== -1;
            const isThreadHovered = globals$1.globals.frontendLocalState.hoveredUtid === utid;
            const isProcessHovered = globals$1.globals.frontendLocalState.hoveredPid === pid;
            const color = colorizer.colorForThread(threadInfo);
            if (isHovering && !isThreadHovered) {
                if (!isProcessHovered) {
                    color.l = 90;
                    color.s = 0;
                }
                else {
                    color.l = Math.min(color.l + 30, 80);
                    color.s -= 20;
                }
            }
            else {
                color.l = Math.min(color.l + 10, 60);
                color.s -= 20;
            }
            ctx.fillStyle = `hsl(${color.h}, ${color.s}%, ${color.l}%)`;
            ctx.fillRect(rectStart, MARGIN_TOP, rectWidth, RECT_HEIGHT);
            // Don't render text when we have less than 5px to play with.
            if (rectWidth < 5)
                continue;
            // TODO: consider de-duplicating this code with the copied one from
            // chrome_slices/frontend.ts.
            let title = `[utid:${utid}]`;
            let subTitle = '';
            if (threadInfo) {
                if (threadInfo.pid) {
                    let procName = threadInfo.procName || '';
                    if (procName.startsWith('/')) { // Remove folder paths from name
                        procName = procName.substring(procName.lastIndexOf('/') + 1);
                    }
                    title = `${procName} [${threadInfo.pid}]`;
                    subTitle = `${threadInfo.threadName} [${threadInfo.tid}]`;
                }
                else {
                    title = `${threadInfo.threadName} [${threadInfo.tid}]`;
                }
            }
            title = canvas_utils.cropText(title, charWidth, rectWidth);
            subTitle = canvas_utils.cropText(subTitle, charWidth, rectWidth);
            const rectXCenter = rectStart + rectWidth / 2;
            ctx.fillStyle = '#fff';
            ctx.font = '12px Roboto Condensed';
            ctx.fillText(title, rectXCenter, MARGIN_TOP + RECT_HEIGHT / 2 - 1);
            ctx.fillStyle = 'rgba(255, 255, 255, 0.6)';
            ctx.font = '10px Roboto Condensed';
            ctx.fillText(subTitle, rectXCenter, MARGIN_TOP + RECT_HEIGHT / 2 + 9);
        }
        const selection = globals$1.globals.state.currentSelection;
        const details = globals$1.globals.sliceDetails;
        if (selection !== null && selection.kind === 'SLICE') {
            const [startIndex, endIndex] = binary_search.searchEq(data.ids, selection.id);
            if (startIndex !== endIndex) {
                const tStart = data.starts[startIndex];
                const tEnd = data.ends[startIndex];
                const utid = data.utids[startIndex];
                const color = colorizer.colorForThread(globals$1.globals.threads.get(utid));
                const rectStart = timeScale.timeToPx(tStart);
                const rectEnd = timeScale.timeToPx(tEnd);
                const rectWidth = Math.max(1, rectEnd - rectStart);
                // Draw a rectangle around the slice that is currently selected.
                ctx.strokeStyle = `hsl(${color.h}, ${color.s}%, 30%)`;
                ctx.beginPath();
                ctx.lineWidth = 3;
                ctx.strokeRect(rectStart, MARGIN_TOP - 1.5, rectWidth, RECT_HEIGHT + 3);
                ctx.closePath();
                // Draw arrow from wakeup time of current slice.
                if (details.wakeupTs) {
                    const wakeupPos = timeScale.timeToPx(details.wakeupTs);
                    const latencyWidth = rectStart - wakeupPos;
                    canvas_utils.drawDoubleHeadedArrow(ctx, wakeupPos, MARGIN_TOP + RECT_HEIGHT, latencyWidth, latencyWidth >= 20);
                    // Latency time with a white semi-transparent background.
                    const displayText = time.timeToString(tStart - details.wakeupTs);
                    const measured = ctx.measureText(displayText);
                    if (latencyWidth >= measured.width + 2) {
                        ctx.fillStyle = 'rgba(255,255,255,0.7)';
                        ctx.fillRect(wakeupPos + latencyWidth / 2 - measured.width / 2 - 1, MARGIN_TOP + RECT_HEIGHT - 12, measured.width + 2, 11);
                        ctx.textBaseline = 'bottom';
                        ctx.fillStyle = 'black';
                        ctx.fillText(displayText, wakeupPos + (latencyWidth) / 2, MARGIN_TOP + RECT_HEIGHT - 1);
                    }
                }
            }
            // Draw diamond if the track being drawn is the cpu of the waker.
            if (this.config.cpu === details.wakerCpu && details.wakeupTs) {
                const wakeupPos = Math.floor(timeScale.timeToPx(details.wakeupTs));
                ctx.beginPath();
                ctx.moveTo(wakeupPos, MARGIN_TOP + RECT_HEIGHT / 2 + 8);
                ctx.fillStyle = 'black';
                ctx.lineTo(wakeupPos + 6, MARGIN_TOP + RECT_HEIGHT / 2);
                ctx.lineTo(wakeupPos, MARGIN_TOP + RECT_HEIGHT / 2 - 8);
                ctx.lineTo(wakeupPos - 6, MARGIN_TOP + RECT_HEIGHT / 2);
                ctx.fill();
                ctx.closePath();
            }
        }
        const hoveredThread = globals$1.globals.threads.get(this.utidHoveredInThisTrack);
        if (hoveredThread !== undefined && this.mouseXpos !== undefined) {
            const tidText = `T: ${hoveredThread.threadName} [${hoveredThread.tid}]`;
            if (hoveredThread.pid) {
                const pidText = `P: ${hoveredThread.procName} [${hoveredThread.pid}]`;
                this.drawTrackHoverTooltip(ctx, this.mouseXpos, pidText, tidText);
            }
            else {
                this.drawTrackHoverTooltip(ctx, this.mouseXpos, tidText);
            }
        }
    }
    onMouseMove({ x, y }) {
        const data = this.data();
        this.mouseXpos = x;
        if (data === undefined)
            return;
        const { timeScale } = globals$1.globals.frontendLocalState;
        if (y < MARGIN_TOP || y > MARGIN_TOP + RECT_HEIGHT) {
            this.utidHoveredInThisTrack = -1;
            globals$1.globals.frontendLocalState.setHoveredUtidAndPid(-1, -1);
            return;
        }
        const t = timeScale.pxToTime(x);
        let hoveredUtid = -1;
        for (let i = 0; i < data.starts.length; i++) {
            const tStart = data.starts[i];
            const tEnd = data.ends[i];
            const utid = data.utids[i];
            if (tStart <= t && t <= tEnd) {
                hoveredUtid = utid;
                break;
            }
        }
        this.utidHoveredInThisTrack = hoveredUtid;
        const threadInfo = globals$1.globals.threads.get(hoveredUtid);
        const hoveredPid = threadInfo ? (threadInfo.pid ? threadInfo.pid : -1) : -1;
        globals$1.globals.frontendLocalState.setHoveredUtidAndPid(hoveredUtid, hoveredPid);
    }
    onMouseOut() {
        this.utidHoveredInThisTrack = -1;
        globals$1.globals.frontendLocalState.setHoveredUtidAndPid(-1, -1);
        this.mouseXpos = 0;
    }
    onMouseClick({ x }) {
        const data = this.data();
        if (data === undefined)
            return false;
        const { timeScale } = globals$1.globals.frontendLocalState;
        const time = timeScale.pxToTime(x);
        const index = binary_search.search(data.starts, time);
        const id = index === -1 ? undefined : data.ids[index];
        if (!id || this.utidHoveredInThisTrack === -1)
            return false;
        globals$1.globals.makeSelection(actions.Actions.selectSlice({ id, trackId: this.trackState.id }));
        return true;
    }
}
CpuSliceTrack.kind = common$c.CPU_SLICE_TRACK_KIND;
track_registry.trackRegistry.register(CpuSliceTrack);

});

createCommonjsModule(function (module, exports) {
// Copyright (C) 2019 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.
Object.defineProperty(exports, "__esModule", { value: true });








const MARGIN_TOP = 5;
const RECT_HEIGHT = 30;
const TRACK_HEIGHT = MARGIN_TOP * 2 + RECT_HEIGHT;
class ProcessSchedulingTrack extends track.Track {
    constructor(trackState) {
        super(trackState);
        this.utidHoveredInThisTrack = -1;
    }
    static create(trackState) {
        return new ProcessSchedulingTrack(trackState);
    }
    getHeight() {
        return TRACK_HEIGHT;
    }
    renderCanvas(ctx) {
        // TODO: fonts and colors should come from the CSS and not hardcoded here.
        const { timeScale, visibleWindowTime } = globals$1.globals.frontendLocalState;
        const data = this.data();
        if (data === undefined)
            return; // Can't possibly draw anything.
        // If the cached trace slices don't fully cover the visible time range,
        // show a gray rectangle with a "Loading..." label.
        checkerboard_1.checkerboardExcept(ctx, this.getHeight(), timeScale.timeToPx(visibleWindowTime.start), timeScale.timeToPx(visibleWindowTime.end), timeScale.timeToPx(data.start), timeScale.timeToPx(data.end));
        logging.assertTrue(data.starts.length === data.ends.length);
        logging.assertTrue(data.starts.length === data.utids.length);
        const rawStartIdx = data.ends.findIndex(end => end >= visibleWindowTime.start);
        const startIdx = rawStartIdx === -1 ? data.starts.length : rawStartIdx;
        const [, rawEndIdx] = binary_search.searchSegment(data.starts, visibleWindowTime.end);
        const endIdx = rawEndIdx === -1 ? data.starts.length : rawEndIdx;
        const cpuTrackHeight = Math.floor(RECT_HEIGHT / data.maxCpu);
        for (let i = startIdx; i < endIdx; i++) {
            const tStart = data.starts[i];
            const tEnd = data.ends[i];
            const utid = data.utids[i];
            const cpu = data.cpus[i];
            const rectStart = timeScale.timeToPx(tStart);
            const rectEnd = timeScale.timeToPx(tEnd);
            const rectWidth = rectEnd - rectStart;
            if (rectWidth < 0.3)
                continue;
            const threadInfo = globals$1.globals.threads.get(utid);
            const pid = (threadInfo ? threadInfo.pid : -1) || -1;
            const isHovering = globals$1.globals.frontendLocalState.hoveredUtid !== -1;
            const isThreadHovered = globals$1.globals.frontendLocalState.hoveredUtid === utid;
            const isProcessHovered = globals$1.globals.frontendLocalState.hoveredPid === pid;
            const color = colorizer.colorForThread(threadInfo);
            if (isHovering && !isThreadHovered) {
                if (!isProcessHovered) {
                    color.l = 90;
                    color.s = 0;
                }
                else {
                    color.l = Math.min(color.l + 30, 80);
                    color.s -= 20;
                }
            }
            else {
                color.l = Math.min(color.l + 10, 60);
                color.s -= 20;
            }
            ctx.fillStyle = `hsl(${color.h}, ${color.s}%, ${color.l}%)`;
            const y = MARGIN_TOP + cpuTrackHeight * cpu + cpu;
            ctx.fillRect(rectStart, y, rectEnd - rectStart, cpuTrackHeight);
        }
        const hoveredThread = globals$1.globals.threads.get(this.utidHoveredInThisTrack);
        if (hoveredThread !== undefined && this.mouseXpos !== undefined) {
            const tidText = `T: ${hoveredThread.threadName} [${hoveredThread.tid}]`;
            if (hoveredThread.pid) {
                const pidText = `P: ${hoveredThread.procName} [${hoveredThread.pid}]`;
                this.drawTrackHoverTooltip(ctx, this.mouseXpos, pidText, tidText);
            }
            else {
                this.drawTrackHoverTooltip(ctx, this.mouseXpos, tidText);
            }
        }
    }
    onMouseMove({ x, y }) {
        const data = this.data();
        this.mouseXpos = x;
        if (data === undefined)
            return;
        if (y < MARGIN_TOP || y > MARGIN_TOP + RECT_HEIGHT) {
            this.utidHoveredInThisTrack = -1;
            globals$1.globals.frontendLocalState.setHoveredUtidAndPid(-1, -1);
            return;
        }
        const cpuTrackHeight = Math.floor(RECT_HEIGHT / data.maxCpu);
        const cpu = Math.floor((y - MARGIN_TOP) / (cpuTrackHeight + 1));
        const { timeScale } = globals$1.globals.frontendLocalState;
        const t = timeScale.pxToTime(x);
        const [i, j] = binary_search.searchRange(data.starts, t, binary_search.searchEq(data.cpus, cpu));
        if (i === j || i >= data.starts.length || t > data.ends[i]) {
            this.utidHoveredInThisTrack = -1;
            globals$1.globals.frontendLocalState.setHoveredUtidAndPid(-1, -1);
            return;
        }
        const utid = data.utids[i];
        this.utidHoveredInThisTrack = utid;
        const threadInfo = globals$1.globals.threads.get(utid);
        const pid = threadInfo ? (threadInfo.pid ? threadInfo.pid : -1) : -1;
        globals$1.globals.frontendLocalState.setHoveredUtidAndPid(utid, pid);
    }
    onMouseOut() {
        this.utidHoveredInThisTrack = -1;
        globals$1.globals.frontendLocalState.setHoveredUtidAndPid(-1, -1);
        this.mouseXpos = 0;
    }
}
ProcessSchedulingTrack.kind = common$6.PROCESS_SCHEDULING_TRACK_KIND;
track_registry.trackRegistry.register(ProcessSchedulingTrack);

});

createCommonjsModule(function (module, exports) {
// 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.
Object.defineProperty(exports, "__esModule", { value: true });






const MARGIN_TOP = 5;
const RECT_HEIGHT = 30;
const TRACK_HEIGHT = MARGIN_TOP * 2 + RECT_HEIGHT;
const SUMMARY_HEIGHT = TRACK_HEIGHT - MARGIN_TOP;
class ProcessSummaryTrack extends track.Track {
    constructor(trackState) {
        super(trackState);
    }
    static create(trackState) {
        return new ProcessSummaryTrack(trackState);
    }
    getHeight() {
        return TRACK_HEIGHT;
    }
    renderCanvas(ctx) {
        const { timeScale, visibleWindowTime } = globals$1.globals.frontendLocalState;
        const data = this.data();
        if (data === undefined)
            return; // Can't possibly draw anything.
        checkerboard_1.checkerboardExcept(ctx, this.getHeight(), timeScale.timeToPx(visibleWindowTime.start), timeScale.timeToPx(visibleWindowTime.end), timeScale.timeToPx(data.start), timeScale.timeToPx(data.end));
        this.renderSummary(ctx, data);
    }
    // TODO(dproy): Dedup with CPU slices.
    renderSummary(ctx, data) {
        const { timeScale, visibleWindowTime } = globals$1.globals.frontendLocalState;
        const startPx = Math.floor(timeScale.timeToPx(visibleWindowTime.start));
        const bottomY = TRACK_HEIGHT;
        let lastX = startPx;
        let lastY = bottomY;
        // TODO(hjd): Dedupe this math.
        const color = colorizer.colorForTid(this.config.pidForColor);
        color.l = Math.min(color.l + 10, 60);
        color.s -= 20;
        ctx.fillStyle = `hsl(${color.h}, ${color.s}%, ${color.l}%)`;
        ctx.beginPath();
        ctx.moveTo(lastX, lastY);
        for (let i = 0; i < data.utilizations.length; i++) {
            // TODO(dproy): Investigate why utilization is > 1 sometimes.
            const utilization = Math.min(data.utilizations[i], 1);
            const startTime = i * data.bucketSizeSeconds + data.start;
            lastX = Math.floor(timeScale.timeToPx(startTime));
            ctx.lineTo(lastX, lastY);
            lastY = MARGIN_TOP + Math.round(SUMMARY_HEIGHT * (1 - utilization));
            ctx.lineTo(lastX, lastY);
        }
        ctx.lineTo(lastX, bottomY);
        ctx.closePath();
        ctx.fill();
    }
}
ProcessSummaryTrack.kind = common$7.PROCESS_SUMMARY_TRACK;
track_registry.trackRegistry.register(ProcessSummaryTrack);

});

var common$d = createCommonjsModule(function (module, exports) {
Object.defineProperty(exports, "__esModule", { value: true });
exports.THREAD_STATE_TRACK_KIND = void 0;
exports.THREAD_STATE_TRACK_KIND = 'ThreadStateTrack';

});

createCommonjsModule(function (module, exports) {
// Copyright (C) 2019 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.
Object.defineProperty(exports, "__esModule", { value: true });









const MARGIN_TOP = 4;
const RECT_HEIGHT = 14;
const EXCESS_WIDTH = 10;
class ThreadStateTrack extends track.Track {
    constructor(trackState) {
        super(trackState);
    }
    static create(trackState) {
        return new ThreadStateTrack(trackState);
    }
    getHeight() {
        return 2 * MARGIN_TOP + RECT_HEIGHT;
    }
    renderCanvas(ctx) {
        const { timeScale, visibleWindowTime } = globals$1.globals.frontendLocalState;
        const data = this.data();
        const charWidth = ctx.measureText('dbpqaouk').width / 8;
        if (data === undefined)
            return; // Can't possibly draw anything.
        // The draw of the rect on the selected slice must happen after the other
        // drawings, otherwise it would result under another rect.
        let drawRectOnSelected = () => { };
        checkerboard_1.checkerboardExcept(ctx, this.getHeight(), timeScale.timeToPx(visibleWindowTime.start), timeScale.timeToPx(visibleWindowTime.end), timeScale.timeToPx(data.start), timeScale.timeToPx(data.end));
        ctx.textAlign = 'center';
        ctx.font = '10px Roboto Condensed';
        for (let i = 0; i < data.starts.length; i++) {
            const tStart = data.starts[i];
            const tEnd = data.ends[i];
            const state = data.strings[data.state[i]];
            if (tEnd <= visibleWindowTime.start || tStart >= visibleWindowTime.end) {
                continue;
            }
            // Don't display a slice for Task Dead.
            if (state === 'x')
                continue;
            const rectStart = timeScale.timeToPx(tStart);
            const rectEnd = timeScale.timeToPx(tEnd);
            const currentSelection = globals$1.globals.state.currentSelection;
            const isSelected = currentSelection &&
                currentSelection.kind === 'THREAD_STATE' &&
                currentSelection.id === data.ids[i];
            const color = colorizer.colorForState(state);
            let colorStr = `hsl(${color.h},${color.s}%,${color.l}%)`;
            if (color.a) {
                colorStr = `hsla(${color.h},${color.s}%,${color.l}%, ${color.a})`;
            }
            ctx.fillStyle = colorStr;
            const rectWidth = rectEnd - rectStart;
            ctx.fillRect(rectStart, MARGIN_TOP, rectWidth, RECT_HEIGHT);
            // Don't render text when we have less than 10px to play with.
            if (rectWidth < 10 || state === 'Sleeping')
                continue;
            const title = canvas_utils.cropText(state, charWidth, rectWidth);
            const rectXCenter = rectStart + rectWidth / 2;
            ctx.fillStyle = color.l > 80 ? '#404040' : '#fff';
            ctx.fillText(title, rectXCenter, MARGIN_TOP + RECT_HEIGHT / 2 + 3);
            if (isSelected) {
                drawRectOnSelected = () => {
                    const rectStart = Math.max(0 - EXCESS_WIDTH, timeScale.timeToPx(tStart));
                    const rectEnd = Math.min(timeScale.timeToPx(visibleWindowTime.end) + EXCESS_WIDTH, timeScale.timeToPx(tEnd));
                    const color = colorizer.colorForState(state);
                    ctx.strokeStyle = `hsl(${color.h},${color.s}%,${color.l * 0.7}%)`;
                    ctx.beginPath();
                    ctx.lineWidth = 3;
                    ctx.strokeRect(rectStart, MARGIN_TOP - 1.5, rectEnd - rectStart, RECT_HEIGHT + 3);
                    ctx.closePath();
                };
            }
        }
        drawRectOnSelected();
    }
    onMouseClick({ x }) {
        const data = this.data();
        if (data === undefined)
            return false;
        const { timeScale } = globals$1.globals.frontendLocalState;
        const time = timeScale.pxToTime(x);
        const index = binary_search.search(data.starts, time);
        if (index === -1)
            return false;
        const id = data.ids[index];
        globals$1.globals.makeSelection(actions.Actions.selectThreadState({ id, trackId: this.trackState.id }));
        return true;
    }
}
ThreadStateTrack.kind = common$d.THREAD_STATE_TRACK_KIND;
track_registry.trackRegistry.register(ThreadStateTrack);

});

createCommonjsModule(function (module, exports) {
// Copyright (C) 2019 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.
Object.defineProperty(exports, "__esModule", { value: true });
exports.AsyncSliceTrack = void 0;



class AsyncSliceTrack extends frontend.ChromeSliceTrack {
    static create(trackState) {
        return new AsyncSliceTrack(trackState);
    }
}
exports.AsyncSliceTrack = AsyncSliceTrack;
AsyncSliceTrack.kind = common$1.ASYNC_SLICE_TRACK_KIND;
track_registry.trackRegistry.register(AsyncSliceTrack);

});

createCommonjsModule(function (module, exports) {
// Copyright (C) 2020 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.
Object.defineProperty(exports, "__esModule", { value: true });
exports.DebugSliceTrack = void 0;







class DebugSliceTrack extends frontend.ChromeSliceTrack {
    static create(trackState) {
        return new DebugSliceTrack(trackState);
    }
    getTrackShellButtons() {
        const buttons = [];
        buttons.push(mithril(track_panel.TrackButton, {
            action: () => {
                globals$1.globals.dispatch(actions.Actions.requestTrackReload({}));
            },
            i: 'refresh',
            tooltip: 'Refresh tracks',
            showButton: true,
        }));
        buttons.push(mithril(track_panel.TrackButton, {
            action: () => {
                globals$1.globals.dispatch(actions.Actions.removeDebugTrack({}));
            },
            i: 'close',
            tooltip: 'Close',
            showButton: true,
        }));
        return buttons;
    }
}
exports.DebugSliceTrack = DebugSliceTrack;
DebugSliceTrack.kind = common$3.DEBUG_SLICE_TRACK_KIND;
track_registry.trackRegistry.register(DebugSliceTrack);

});

createCommonjsModule(function (module, exports) {
// Copyright (C) 2021 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.
Object.defineProperty(exports, "__esModule", { value: true });
exports.ActualFramesSliceTrack = void 0;



class ActualFramesSliceTrack extends frontend.ChromeSliceTrack {
    static create(trackState) {
        return new ActualFramesSliceTrack(trackState);
    }
}
exports.ActualFramesSliceTrack = ActualFramesSliceTrack;
ActualFramesSliceTrack.kind = common.ACTUAL_FRAMES_SLICE_TRACK_KIND;
track_registry.trackRegistry.register(ActualFramesSliceTrack);

});

createCommonjsModule(function (module, exports) {
// Copyright (C) 2021 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.
Object.defineProperty(exports, "__esModule", { value: true });
exports.ExpectedFramesSliceTrack = void 0;



class ExpectedFramesSliceTrack extends frontend.ChromeSliceTrack {
    static create(trackState) {
        return new ExpectedFramesSliceTrack(trackState);
    }
}
exports.ExpectedFramesSliceTrack = ExpectedFramesSliceTrack;
ExpectedFramesSliceTrack.kind = common$4.EXPECTED_FRAMES_SLICE_TRACK_KIND;
track_registry.trackRegistry.register(ExpectedFramesSliceTrack);

});

createCommonjsModule(function (module, exports) {
// 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.
Object.defineProperty(exports, "__esModule", { value: true });
// Import all currently implemented tracks. After implemeting a new track, an
// import statement for it needs to be added here.















});

var remote = createCommonjsModule(function (module, exports) {
// 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.
Object.defineProperty(exports, "__esModule", { value: true });
exports.forwardRemoteCalls = exports.Remote = void 0;

/**
 * A proxy for an object that lives on another thread.
 */
class Remote {
    constructor(port) {
        this.nextRequestId = 0;
        this.deferredRequests = new Map();
        this.port = port;
        this.port.onmessage = (event) => {
            this.receive(event.data);
        };
    }
    /**
     * Invoke method with name |method| with |args| on the remote object.
     * Optionally set |transferList| to transfer those objects.
     */
    // tslint:disable-next-line no-any
    send(method, args, transferList) {
        const d = deferred.defer();
        this.deferredRequests.set(this.nextRequestId, d);
        const message = {
            responseId: this.nextRequestId,
            method,
            args,
        };
        if (transferList === undefined) {
            this.port.postMessage(message);
        }
        else {
            this.port.postMessage(message, transferList);
        }
        this.nextRequestId += 1;
        return d;
    }
    receive(response) {
        const d = this.deferredRequests.get(response.id);
        if (!d)
            throw new Error(`No deferred response with ID ${response.id}`);
        this.deferredRequests.delete(response.id);
        d.resolve(response.result);
    }
}
exports.Remote = Remote;
/**
 * Given a MessagePort |port| where the other end is owned by a Remote
 * (see above) turn each incoming MessageEvent into a call on |handler|
 * and post the result back to the calling thread.
 */
function forwardRemoteCalls(port, 
// tslint:disable-next-line no-any
handler) {
    port.onmessage = (msg) => {
        const method = msg.data.method;
        const id = msg.data.responseId;
        const args = msg.data.args || [];
        if (method === undefined || id === undefined) {
            throw new Error(`Invalid call method: ${method} id: ${id}`);
        }
        if (!(handler[method] instanceof Function)) {
            throw new Error(`Method not known: ${method}(${args})`);
        }
        const result = handler[method].apply(handler, args);
        const transferList = [];
        if (result !== undefined && result.port instanceof MessagePort) {
            transferList.push(result.port);
        }
        port.postMessage({
            id,
            result,
        }, transferList);
    };
}
exports.forwardRemoteCalls = forwardRemoteCalls;

});

var logs = createCommonjsModule(function (module, exports) {
// Copyright (C) 2019 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.
Object.defineProperty(exports, "__esModule", { value: true });
exports.LogEntriesKey = exports.LogBoundsKey = exports.LogExistsKey = void 0;
exports.LogExistsKey = 'log-exists';
exports.LogBoundsKey = 'log-bounds';
exports.LogEntriesKey = 'log-entries';

});

var cookie_consent = createCommonjsModule(function (module, exports) {
// Copyright (C) 2020 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.
Object.defineProperty(exports, "__esModule", { value: true });
exports.CookieConsent = void 0;


const COOKIE_ACK_KEY = 'cookieAck';
class CookieConsent {
    constructor() {
        this.showCookieConsent = true;
    }
    view() {
        if (this.showCookieConsent) {
            this.showCookieConsent = localStorage.getItem(COOKIE_ACK_KEY) === null;
        }
        if (!this.showCookieConsent)
            return;
        return mithril('.cookie-consent', mithril('.cookie-text', `This site uses cookies from Google to deliver its services and to
          analyze traffic.`), mithril('.buttons', mithril('button', mithril('a', {
            href: 'https://policies.google.com/technologies/cookies',
            target: '_blank'
        }, 'More details')), mithril('button', {
            onclick: () => {
                this.showCookieConsent = false;
                localStorage.setItem(COOKIE_ACK_KEY, 'true');
                globals$1.globals.rafScheduler.scheduleFullRedraw();
            }
        }, 'OK')));
    }
}
exports.CookieConsent = CookieConsent;

});

var animation = createCommonjsModule(function (module, exports) {
// 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.
Object.defineProperty(exports, "__esModule", { value: true });
exports.Animation = void 0;

class Animation {
    constructor(onAnimationStep) {
        this.onAnimationStep = onAnimationStep;
        this.startMs = 0;
        this.endMs = 0;
        this.boundOnAnimationFrame = this.onAnimationFrame.bind(this);
    }
    start(durationMs) {
        const nowMs = performance.now();
        // If the animation is already happening, just update its end time.
        if (nowMs <= this.endMs) {
            this.endMs = nowMs + durationMs;
            return;
        }
        this.startMs = nowMs;
        this.endMs = nowMs + durationMs;
        globals$1.globals.rafScheduler.start(this.boundOnAnimationFrame);
    }
    stop() {
        this.endMs = 0;
        globals$1.globals.rafScheduler.stop(this.boundOnAnimationFrame);
    }
    get startTimeMs() {
        return this.startMs;
    }
    onAnimationFrame(nowMs) {
        if (nowMs >= this.endMs) {
            globals$1.globals.rafScheduler.stop(this.boundOnAnimationFrame);
            return;
        }
        this.onAnimationStep(Math.max(Math.round(nowMs - this.startMs), 0));
    }
}
exports.Animation = Animation;

});

var clipboard = createCommonjsModule(function (module, exports) {
// 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.
Object.defineProperty(exports, "__esModule", { value: true });
exports.copyToClipboard = void 0;

function copyToClipboard(text) {
    return tslib.__awaiter(this, void 0, void 0, function* () {
        try {
            // TODO(hjd): Fix typescript type for navigator.
            // tslint:disable-next-line no-any
            yield navigator.clipboard.writeText(text);
        }
        catch (err) {
            console.error(`Failed to copy "${text}" to clipboard: ${err}`);
        }
    });
}
exports.copyToClipboard = copyToClipboard;

});

var micromodal = createCommonjsModule(function (module, exports) {
(function (global, factory) {
  module.exports = factory() ;
}(commonjsGlobal, (function () {
  function _classCallCheck(instance, Constructor) {
    if (!(instance instanceof Constructor)) {
      throw new TypeError("Cannot call a class as a function");
    }
  }

  function _defineProperties(target, props) {
    for (var i = 0; i < props.length; i++) {
      var descriptor = props[i];
      descriptor.enumerable = descriptor.enumerable || false;
      descriptor.configurable = true;
      if ("value" in descriptor) descriptor.writable = true;
      Object.defineProperty(target, descriptor.key, descriptor);
    }
  }

  function _createClass(Constructor, protoProps, staticProps) {
    if (protoProps) _defineProperties(Constructor.prototype, protoProps);
    if (staticProps) _defineProperties(Constructor, staticProps);
    return Constructor;
  }

  function _toConsumableArray(arr) {
    return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread();
  }

  function _arrayWithoutHoles(arr) {
    if (Array.isArray(arr)) return _arrayLikeToArray(arr);
  }

  function _iterableToArray(iter) {
    if (typeof Symbol !== "undefined" && Symbol.iterator in Object(iter)) return Array.from(iter);
  }

  function _unsupportedIterableToArray(o, minLen) {
    if (!o) return;
    if (typeof o === "string") return _arrayLikeToArray(o, minLen);
    var n = Object.prototype.toString.call(o).slice(8, -1);
    if (n === "Object" && o.constructor) n = o.constructor.name;
    if (n === "Map" || n === "Set") return Array.from(n);
    if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen);
  }

  function _arrayLikeToArray(arr, len) {
    if (len == null || len > arr.length) len = arr.length;

    for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i];

    return arr2;
  }

  function _nonIterableSpread() {
    throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
  }

  var MicroModal = function () {

    var FOCUSABLE_ELEMENTS = ['a[href]', 'area[href]', 'input:not([disabled]):not([type="hidden"]):not([aria-hidden])', 'select:not([disabled]):not([aria-hidden])', 'textarea:not([disabled]):not([aria-hidden])', 'button:not([disabled]):not([aria-hidden])', 'iframe', 'object', 'embed', '[contenteditable]', '[tabindex]:not([tabindex^="-"])'];

    var Modal = /*#__PURE__*/function () {
      function Modal(_ref) {
        var targetModal = _ref.targetModal,
            _ref$triggers = _ref.triggers,
            triggers = _ref$triggers === void 0 ? [] : _ref$triggers,
            _ref$onShow = _ref.onShow,
            onShow = _ref$onShow === void 0 ? function () {} : _ref$onShow,
            _ref$onClose = _ref.onClose,
            onClose = _ref$onClose === void 0 ? function () {} : _ref$onClose,
            _ref$openTrigger = _ref.openTrigger,
            openTrigger = _ref$openTrigger === void 0 ? 'data-micromodal-trigger' : _ref$openTrigger,
            _ref$closeTrigger = _ref.closeTrigger,
            closeTrigger = _ref$closeTrigger === void 0 ? 'data-micromodal-close' : _ref$closeTrigger,
            _ref$openClass = _ref.openClass,
            openClass = _ref$openClass === void 0 ? 'is-open' : _ref$openClass,
            _ref$disableScroll = _ref.disableScroll,
            disableScroll = _ref$disableScroll === void 0 ? false : _ref$disableScroll,
            _ref$disableFocus = _ref.disableFocus,
            disableFocus = _ref$disableFocus === void 0 ? false : _ref$disableFocus,
            _ref$awaitCloseAnimat = _ref.awaitCloseAnimation,
            awaitCloseAnimation = _ref$awaitCloseAnimat === void 0 ? false : _ref$awaitCloseAnimat,
            _ref$awaitOpenAnimati = _ref.awaitOpenAnimation,
            awaitOpenAnimation = _ref$awaitOpenAnimati === void 0 ? false : _ref$awaitOpenAnimati,
            _ref$debugMode = _ref.debugMode,
            debugMode = _ref$debugMode === void 0 ? false : _ref$debugMode;

        _classCallCheck(this, Modal);

        // Save a reference of the modal
        this.modal = document.getElementById(targetModal); // Save a reference to the passed config

        this.config = {
          debugMode: debugMode,
          disableScroll: disableScroll,
          openTrigger: openTrigger,
          closeTrigger: closeTrigger,
          openClass: openClass,
          onShow: onShow,
          onClose: onClose,
          awaitCloseAnimation: awaitCloseAnimation,
          awaitOpenAnimation: awaitOpenAnimation,
          disableFocus: disableFocus
        }; // Register click events only if pre binding eventListeners

        if (triggers.length > 0) this.registerTriggers.apply(this, _toConsumableArray(triggers)); // pre bind functions for event listeners

        this.onClick = this.onClick.bind(this);
        this.onKeydown = this.onKeydown.bind(this);
      }
      /**
       * Loops through all openTriggers and binds click event
       * @param  {array} triggers [Array of node elements]
       * @return {void}
       */


      _createClass(Modal, [{
        key: "registerTriggers",
        value: function registerTriggers() {
          var _this = this;

          for (var _len = arguments.length, triggers = new Array(_len), _key = 0; _key < _len; _key++) {
            triggers[_key] = arguments[_key];
          }

          triggers.filter(Boolean).forEach(function (trigger) {
            trigger.addEventListener('click', function (event) {
              return _this.showModal(event);
            });
          });
        }
      }, {
        key: "showModal",
        value: function showModal() {
          var _this2 = this;

          var event = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;
          this.activeElement = document.activeElement;
          this.modal.setAttribute('aria-hidden', 'false');
          this.modal.classList.add(this.config.openClass);
          this.scrollBehaviour('disable');
          this.addEventListeners();

          if (this.config.awaitOpenAnimation) {
            var handler = function handler() {
              _this2.modal.removeEventListener('animationend', handler, false);

              _this2.setFocusToFirstNode();
            };

            this.modal.addEventListener('animationend', handler, false);
          } else {
            this.setFocusToFirstNode();
          }

          this.config.onShow(this.modal, this.activeElement, event);
        }
      }, {
        key: "closeModal",
        value: function closeModal() {
          var event = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;
          var modal = this.modal;
          this.modal.setAttribute('aria-hidden', 'true');
          this.removeEventListeners();
          this.scrollBehaviour('enable');

          if (this.activeElement && this.activeElement.focus) {
            this.activeElement.focus();
          }

          this.config.onClose(this.modal, this.activeElement, event);

          if (this.config.awaitCloseAnimation) {
            var openClass = this.config.openClass; // <- old school ftw

            this.modal.addEventListener('animationend', function handler() {
              modal.classList.remove(openClass);
              modal.removeEventListener('animationend', handler, false);
            }, false);
          } else {
            modal.classList.remove(this.config.openClass);
          }
        }
      }, {
        key: "closeModalById",
        value: function closeModalById(targetModal) {
          this.modal = document.getElementById(targetModal);
          if (this.modal) this.closeModal();
        }
      }, {
        key: "scrollBehaviour",
        value: function scrollBehaviour(toggle) {
          if (!this.config.disableScroll) return;
          var body = document.querySelector('body');

          switch (toggle) {
            case 'enable':
              Object.assign(body.style, {
                overflow: ''
              });
              break;

            case 'disable':
              Object.assign(body.style, {
                overflow: 'hidden'
              });
              break;
          }
        }
      }, {
        key: "addEventListeners",
        value: function addEventListeners() {
          this.modal.addEventListener('touchstart', this.onClick);
          this.modal.addEventListener('click', this.onClick);
          document.addEventListener('keydown', this.onKeydown);
        }
      }, {
        key: "removeEventListeners",
        value: function removeEventListeners() {
          this.modal.removeEventListener('touchstart', this.onClick);
          this.modal.removeEventListener('click', this.onClick);
          document.removeEventListener('keydown', this.onKeydown);
        }
      }, {
        key: "onClick",
        value: function onClick(event) {
          if (event.target.hasAttribute(this.config.closeTrigger)) {
            this.closeModal(event);
          }
        }
      }, {
        key: "onKeydown",
        value: function onKeydown(event) {
          if (event.keyCode === 27) this.closeModal(event); // esc

          if (event.keyCode === 9) this.retainFocus(event); // tab
        }
      }, {
        key: "getFocusableNodes",
        value: function getFocusableNodes() {
          var nodes = this.modal.querySelectorAll(FOCUSABLE_ELEMENTS);
          return Array.apply(void 0, _toConsumableArray(nodes));
        }
        /**
         * Tries to set focus on a node which is not a close trigger
         * if no other nodes exist then focuses on first close trigger
         */

      }, {
        key: "setFocusToFirstNode",
        value: function setFocusToFirstNode() {
          var _this3 = this;

          if (this.config.disableFocus) return;
          var focusableNodes = this.getFocusableNodes(); // no focusable nodes

          if (focusableNodes.length === 0) return; // remove nodes on whose click, the modal closes
          // could not think of a better name :(

          var nodesWhichAreNotCloseTargets = focusableNodes.filter(function (node) {
            return !node.hasAttribute(_this3.config.closeTrigger);
          });
          if (nodesWhichAreNotCloseTargets.length > 0) nodesWhichAreNotCloseTargets[0].focus();
          if (nodesWhichAreNotCloseTargets.length === 0) focusableNodes[0].focus();
        }
      }, {
        key: "retainFocus",
        value: function retainFocus(event) {
          var focusableNodes = this.getFocusableNodes(); // no focusable nodes

          if (focusableNodes.length === 0) return;
          /**
           * Filters nodes which are hidden to prevent
           * focus leak outside modal
           */

          focusableNodes = focusableNodes.filter(function (node) {
            return node.offsetParent !== null;
          }); // if disableFocus is true

          if (!this.modal.contains(document.activeElement)) {
            focusableNodes[0].focus();
          } else {
            var focusedItemIndex = focusableNodes.indexOf(document.activeElement);

            if (event.shiftKey && focusedItemIndex === 0) {
              focusableNodes[focusableNodes.length - 1].focus();
              event.preventDefault();
            }

            if (!event.shiftKey && focusableNodes.length > 0 && focusedItemIndex === focusableNodes.length - 1) {
              focusableNodes[0].focus();
              event.preventDefault();
            }
          }
        }
      }]);

      return Modal;
    }();
    /**
     * Modal prototype ends.
     * Here on code is responsible for detecting and
     * auto binding event handlers on modal triggers
     */
    // Keep a reference to the opened modal


    var activeModal = null;
    /**
     * Generates an associative array of modals and it's
     * respective triggers
     * @param  {array} triggers     An array of all triggers
     * @param  {string} triggerAttr The data-attribute which triggers the module
     * @return {array}
     */

    var generateTriggerMap = function generateTriggerMap(triggers, triggerAttr) {
      var triggerMap = [];
      triggers.forEach(function (trigger) {
        var targetModal = trigger.attributes[triggerAttr].value;
        if (triggerMap[targetModal] === undefined) triggerMap[targetModal] = [];
        triggerMap[targetModal].push(trigger);
      });
      return triggerMap;
    };
    /**
     * Validates whether a modal of the given id exists
     * in the DOM
     * @param  {number} id  The id of the modal
     * @return {boolean}
     */


    var validateModalPresence = function validateModalPresence(id) {
      if (!document.getElementById(id)) {
        console.warn("MicroModal: \u2757Seems like you have missed %c'".concat(id, "'"), 'background-color: #f8f9fa;color: #50596c;font-weight: bold;', 'ID somewhere in your code. Refer example below to resolve it.');
        console.warn("%cExample:", 'background-color: #f8f9fa;color: #50596c;font-weight: bold;', "<div class=\"modal\" id=\"".concat(id, "\"></div>"));
        return false;
      }
    };
    /**
     * Validates if there are modal triggers present
     * in the DOM
     * @param  {array} triggers An array of data-triggers
     * @return {boolean}
     */


    var validateTriggerPresence = function validateTriggerPresence(triggers) {
      if (triggers.length <= 0) {
        console.warn("MicroModal: \u2757Please specify at least one %c'micromodal-trigger'", 'background-color: #f8f9fa;color: #50596c;font-weight: bold;', 'data attribute.');
        console.warn("%cExample:", 'background-color: #f8f9fa;color: #50596c;font-weight: bold;', "<a href=\"#\" data-micromodal-trigger=\"my-modal\"></a>");
        return false;
      }
    };
    /**
     * Checks if triggers and their corresponding modals
     * are present in the DOM
     * @param  {array} triggers   Array of DOM nodes which have data-triggers
     * @param  {array} triggerMap Associative array of modals and their triggers
     * @return {boolean}
     */


    var validateArgs = function validateArgs(triggers, triggerMap) {
      validateTriggerPresence(triggers);
      if (!triggerMap) return true;

      for (var id in triggerMap) {
        validateModalPresence(id);
      }

      return true;
    };
    /**
     * Binds click handlers to all modal triggers
     * @param  {object} config [description]
     * @return void
     */


    var init = function init(config) {
      // Create an config object with default openTrigger
      var options = Object.assign({}, {
        openTrigger: 'data-micromodal-trigger'
      }, config); // Collects all the nodes with the trigger

      var triggers = _toConsumableArray(document.querySelectorAll("[".concat(options.openTrigger, "]"))); // Makes a mappings of modals with their trigger nodes


      var triggerMap = generateTriggerMap(triggers, options.openTrigger); // Checks if modals and triggers exist in dom

      if (options.debugMode === true && validateArgs(triggers, triggerMap) === false) return; // For every target modal creates a new instance

      for (var key in triggerMap) {
        var value = triggerMap[key];
        options.targetModal = key;
        options.triggers = _toConsumableArray(value);
        activeModal = new Modal(options); // eslint-disable-line no-new
      }
    };
    /**
     * Shows a particular modal
     * @param  {string} targetModal [The id of the modal to display]
     * @param  {object} config [The configuration object to pass]
     * @return {void}
     */


    var show = function show(targetModal, config) {
      var options = config || {};
      options.targetModal = targetModal; // Checks if modals and triggers exist in dom

      if (options.debugMode === true && validateModalPresence(targetModal) === false) return; // clear events in case previous modal wasn't close

      if (activeModal) activeModal.removeEventListeners(); // stores reference to active modal

      activeModal = new Modal(options); // eslint-disable-line no-new

      activeModal.showModal();
    };
    /**
     * Closes the active modal
     * @param  {string} targetModal [The id of the modal to close]
     * @return {void}
     */


    var close = function close(targetModal) {
      targetModal ? activeModal.closeModalById(targetModal) : activeModal.closeModal();
    };

    return {
      init: init,
      show: show,
      close: close
    };
  }();
  window.MicroModal = MicroModal;

  return MicroModal;

})));
});

var modal = createCommonjsModule(function (module, exports) {
// Copyright (C) 2019 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.
Object.defineProperty(exports, "__esModule", { value: true });
exports.hideModel = exports.showModal = void 0;



// We need to create a div outside of the mithril's render root (<main>), that's
// why the manual DOM manipulation.
function getOrCreateDOM() {
    let div = document.getElementById('main-modal');
    if (div)
        return div;
    div = document.createElement('div');
    div.id = 'main-modal';
    div.classList.add('modal');
    div.classList.add('micromodal-slide');
    div.ariaHidden = true;
    document.body.appendChild(div);
    micromodal.init();
    return div;
}
function showModal(attrs) {
    return tslib.__awaiter(this, void 0, void 0, function* () {
        const modal = getOrCreateDOM();
        mithril.render(modal, mithril('.modal-overlay[data-micromodal-close]', { tabindex: -1 }, mithril('.modal-container[aria-labelledby=mm-title][aria-model][role=dialog]', mithril('header.modal-header', mithril('h2.modal-title', { id: 'mm-title' }, attrs.title), mithril('button.modal-close[aria-label=Close Modal]' +
            '[data-micromodal-close]')), mithril('main.modal-content', attrs.content), mithril('footer.modal-footer', ...makeButtons(attrs.buttons)))));
        return new Promise(resolve => {
            micromodal.show('main-modal', { onClose: () => resolve(), awaitCloseAnimation: true });
        });
    });
}
exports.showModal = showModal;
function hideModel() {
    micromodal.close();
}
exports.hideModel = hideModel;
function makeButtons(buttonDefinition) {
    const buttons = [];
    buttonDefinition.forEach(button => {
        buttons.push(mithril('button[data-micromodal-close].modal-btn', {
            class: button.primary ? 'modal-btn-primary' : '',
            id: button.id,
            onclick: button.action
        }, button.text));
    });
    return buttons;
}

});

var help_modal = createCommonjsModule(function (module, exports) {
// Copyright (C) 2019 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.
Object.defineProperty(exports, "__esModule", { value: true });
exports.toggleHelp = void 0;



let helpModelOpen = false;
function toggleHelp() {
    if (helpModelOpen) {
        hideHelp();
    }
    else {
        globals$1.globals.logging.logEvent('User Actions', 'Show help');
        showHelp();
    }
}
exports.toggleHelp = toggleHelp;
function keycap(key) {
    return mithril('.keycap', key);
}
function showHelp() {
    helpModelOpen = true;
    modal.showModal({
        title: 'Perfetto Help',
        content: mithril('.help', mithril('h2', 'Navigation'), mithril('table', mithril('tr', mithril('td', keycap('w'), '/', keycap('s')), mithril('td', 'Zoom in/out')), mithril('tr', mithril('td', keycap('a'), '/', keycap('d')), mithril('td', 'Pan left/right'))), mithril('h2', 'Mouse Controls'), mithril('table', mithril('tr', mithril('td', 'Click'), mithril('td', 'Select event')), mithril('tr', mithril('td', 'Ctrl + Scroll wheel'), mithril('td', 'Zoom in/out')), mithril('tr', mithril('td', 'Click + Drag'), mithril('td', 'Select area')), mithril('tr', mithril('td', 'Shift + Click + Drag'), mithril('td', 'Pan left/right'))), mithril('h2', 'Other'), mithril('table', mithril('tr', mithril('td', keycap('f'), ' (with event selected)'), mithril('td', 'Scroll + zoom to current selection')), mithril('tr', mithril('td', keycap('['), '/', keycap(']'), ' (with event selected)'), mithril('td', 'Select next/previous slice that is connected by a flow.', mithril('br'), 'If there are multiple flows,' +
            'the one that is in focus (bold) is selected')), mithril('tr', mithril('td', keycap('Ctrl'), ' + ', keycap('['), '/', keycap(']'), ' (with event selected)'), mithril('td', 'Switch focus to another flow')), mithril('tr', mithril('td', keycap('m'), ' (with event or area selected)'), mithril('td', 'Mark the area (temporarily)')), mithril('tr', mithril('td', keycap('Shift'), ' + ', keycap('m'), ' (with event or area selected)'), mithril('td', 'Mark the area (persistently)')), mithril('tr', mithril('td', keycap('Ctrl'), ' + ', keycap('b')), mithril('td', 'Toggle display of sidebar')), mithril('tr', mithril('td', keycap('?')), mithril('td', 'Show help')))),
        buttons: [],
    }).finally(() => {
        helpModelOpen = false;
    });
}
function hideHelp() {
    if (helpModelOpen) {
        modal.hideModel();
    }
}

});

var common$e = createCommonjsModule(function (module, exports) {


var TYPED_OK =  (typeof Uint8Array !== 'undefined') &&
                (typeof Uint16Array !== 'undefined') &&
                (typeof Int32Array !== 'undefined');

function _has(obj, key) {
  return Object.prototype.hasOwnProperty.call(obj, key);
}

exports.assign = function (obj /*from1, from2, from3, ...*/) {
  var sources = Array.prototype.slice.call(arguments, 1);
  while (sources.length) {
    var source = sources.shift();
    if (!source) { continue; }

    if (typeof source !== 'object') {
      throw new TypeError(source + 'must be non-object');
    }

    for (var p in source) {
      if (_has(source, p)) {
        obj[p] = source[p];
      }
    }
  }

  return obj;
};


// reduce buffer size, avoiding mem copy
exports.shrinkBuf = function (buf, size) {
  if (buf.length === size) { return buf; }
  if (buf.subarray) { return buf.subarray(0, size); }
  buf.length = size;
  return buf;
};


var fnTyped = {
  arraySet: function (dest, src, src_offs, len, dest_offs) {
    if (src.subarray && dest.subarray) {
      dest.set(src.subarray(src_offs, src_offs + len), dest_offs);
      return;
    }
    // Fallback to ordinary array
    for (var i = 0; i < len; i++) {
      dest[dest_offs + i] = src[src_offs + i];
    }
  },
  // Join array of chunks to single array.
  flattenChunks: function (chunks) {
    var i, l, len, pos, chunk, result;

    // calculate data length
    len = 0;
    for (i = 0, l = chunks.length; i < l; i++) {
      len += chunks[i].length;
    }

    // join chunks
    result = new Uint8Array(len);
    pos = 0;
    for (i = 0, l = chunks.length; i < l; i++) {
      chunk = chunks[i];
      result.set(chunk, pos);
      pos += chunk.length;
    }

    return result;
  }
};

var fnUntyped = {
  arraySet: function (dest, src, src_offs, len, dest_offs) {
    for (var i = 0; i < len; i++) {
      dest[dest_offs + i] = src[src_offs + i];
    }
  },
  // Join array of chunks to single array.
  flattenChunks: function (chunks) {
    return [].concat.apply([], chunks);
  }
};


// Enable/Disable typed arrays use, for testing
//
exports.setTyped = function (on) {
  if (on) {
    exports.Buf8  = Uint8Array;
    exports.Buf16 = Uint16Array;
    exports.Buf32 = Int32Array;
    exports.assign(exports, fnTyped);
  } else {
    exports.Buf8  = Array;
    exports.Buf16 = Array;
    exports.Buf32 = Array;
    exports.assign(exports, fnUntyped);
  }
};

exports.setTyped(TYPED_OK);
});

// (C) 1995-2013 Jean-loup Gailly and Mark Adler
// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented; you must not
//   claim that you wrote the original software. If you use this software
//   in a product, an acknowledgment in the product documentation would be
//   appreciated but is not required.
// 2. Altered source versions must be plainly marked as such, and must not be
//   misrepresented as being the original software.
// 3. This notice may not be removed or altered from any source distribution.

/* eslint-disable space-unary-ops */



/* Public constants ==========================================================*/
/* ===========================================================================*/


//var Z_FILTERED          = 1;
//var Z_HUFFMAN_ONLY      = 2;
//var Z_RLE               = 3;
var Z_FIXED               = 4;
//var Z_DEFAULT_STRATEGY  = 0;

/* Possible values of the data_type field (though see inflate()) */
var Z_BINARY              = 0;
var Z_TEXT                = 1;
//var Z_ASCII             = 1; // = Z_TEXT
var Z_UNKNOWN             = 2;

/*============================================================================*/


function zero(buf) { var len = buf.length; while (--len >= 0) { buf[len] = 0; } }

// From zutil.h

var STORED_BLOCK = 0;
var STATIC_TREES = 1;
var DYN_TREES    = 2;
/* The three kinds of block type */

var MIN_MATCH    = 3;
var MAX_MATCH    = 258;
/* The minimum and maximum match lengths */

// From deflate.h
/* ===========================================================================
 * Internal compression state.
 */

var LENGTH_CODES  = 29;
/* number of length codes, not counting the special END_BLOCK code */

var LITERALS      = 256;
/* number of literal bytes 0..255 */

var L_CODES       = LITERALS + 1 + LENGTH_CODES;
/* number of Literal or Length codes, including the END_BLOCK code */

var D_CODES       = 30;
/* number of distance codes */

var BL_CODES      = 19;
/* number of codes used to transfer the bit lengths */

var HEAP_SIZE     = 2 * L_CODES + 1;
/* maximum heap size */

var MAX_BITS      = 15;
/* All codes must not exceed MAX_BITS bits */

var Buf_size      = 16;
/* size of bit buffer in bi_buf */


/* ===========================================================================
 * Constants
 */

var MAX_BL_BITS = 7;
/* Bit length codes must not exceed MAX_BL_BITS bits */

var END_BLOCK   = 256;
/* end of block literal code */

var REP_3_6     = 16;
/* repeat previous bit length 3-6 times (2 bits of repeat count) */

var REPZ_3_10   = 17;
/* repeat a zero length 3-10 times  (3 bits of repeat count) */

var REPZ_11_138 = 18;
/* repeat a zero length 11-138 times  (7 bits of repeat count) */

/* eslint-disable comma-spacing,array-bracket-spacing */
var extra_lbits =   /* extra bits for each length code */
  [0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0];

var extra_dbits =   /* extra bits for each distance code */
  [0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13];

var extra_blbits =  /* extra bits for each bit length code */
  [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7];

var bl_order =
  [16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15];
/* eslint-enable comma-spacing,array-bracket-spacing */

/* The lengths of the bit length codes are sent in order of decreasing
 * probability, to avoid transmitting the lengths for unused bit length codes.
 */

/* ===========================================================================
 * Local data. These are initialized only once.
 */

// We pre-fill arrays with 0 to avoid uninitialized gaps

var DIST_CODE_LEN = 512; /* see definition of array dist_code below */

// !!!! Use flat array instead of structure, Freq = i*2, Len = i*2+1
var static_ltree  = new Array((L_CODES + 2) * 2);
zero(static_ltree);
/* The static literal tree. Since the bit lengths are imposed, there is no
 * need for the L_CODES extra codes used during heap construction. However
 * The codes 286 and 287 are needed to build a canonical tree (see _tr_init
 * below).
 */

var static_dtree  = new Array(D_CODES * 2);
zero(static_dtree);
/* The static distance tree. (Actually a trivial tree since all codes use
 * 5 bits.)
 */

var _dist_code    = new Array(DIST_CODE_LEN);
zero(_dist_code);
/* Distance codes. The first 256 values correspond to the distances
 * 3 .. 258, the last 256 values correspond to the top 8 bits of
 * the 15 bit distances.
 */

var _length_code  = new Array(MAX_MATCH - MIN_MATCH + 1);
zero(_length_code);
/* length code for each normalized match length (0 == MIN_MATCH) */

var base_length   = new Array(LENGTH_CODES);
zero(base_length);
/* First normalized length for each code (0 = MIN_MATCH) */

var base_dist     = new Array(D_CODES);
zero(base_dist);
/* First normalized distance for each code (0 = distance of 1) */


function StaticTreeDesc(static_tree, extra_bits, extra_base, elems, max_length) {

  this.static_tree  = static_tree;  /* static tree or NULL */
  this.extra_bits   = extra_bits;   /* extra bits for each code or NULL */
  this.extra_base   = extra_base;   /* base index for extra_bits */
  this.elems        = elems;        /* max number of elements in the tree */
  this.max_length   = max_length;   /* max bit length for the codes */

  // show if `static_tree` has data or dummy - needed for monomorphic objects
  this.has_stree    = static_tree && static_tree.length;
}


var static_l_desc;
var static_d_desc;
var static_bl_desc;


function TreeDesc(dyn_tree, stat_desc) {
  this.dyn_tree = dyn_tree;     /* the dynamic tree */
  this.max_code = 0;            /* largest code with non zero frequency */
  this.stat_desc = stat_desc;   /* the corresponding static tree */
}



function d_code(dist) {
  return dist < 256 ? _dist_code[dist] : _dist_code[256 + (dist >>> 7)];
}


/* ===========================================================================
 * Output a short LSB first on the stream.
 * IN assertion: there is enough room in pendingBuf.
 */
function put_short(s, w) {
//    put_byte(s, (uch)((w) & 0xff));
//    put_byte(s, (uch)((ush)(w) >> 8));
  s.pending_buf[s.pending++] = (w) & 0xff;
  s.pending_buf[s.pending++] = (w >>> 8) & 0xff;
}


/* ===========================================================================
 * Send a value on a given number of bits.
 * IN assertion: length <= 16 and value fits in length bits.
 */
function send_bits(s, value, length) {
  if (s.bi_valid > (Buf_size - length)) {
    s.bi_buf |= (value << s.bi_valid) & 0xffff;
    put_short(s, s.bi_buf);
    s.bi_buf = value >> (Buf_size - s.bi_valid);
    s.bi_valid += length - Buf_size;
  } else {
    s.bi_buf |= (value << s.bi_valid) & 0xffff;
    s.bi_valid += length;
  }
}


function send_code(s, c, tree) {
  send_bits(s, tree[c * 2]/*.Code*/, tree[c * 2 + 1]/*.Len*/);
}


/* ===========================================================================
 * Reverse the first len bits of a code, using straightforward code (a faster
 * method would use a table)
 * IN assertion: 1 <= len <= 15
 */
function bi_reverse(code, len) {
  var res = 0;
  do {
    res |= code & 1;
    code >>>= 1;
    res <<= 1;
  } while (--len > 0);
  return res >>> 1;
}


/* ===========================================================================
 * Flush the bit buffer, keeping at most 7 bits in it.
 */
function bi_flush(s) {
  if (s.bi_valid === 16) {
    put_short(s, s.bi_buf);
    s.bi_buf = 0;
    s.bi_valid = 0;

  } else if (s.bi_valid >= 8) {
    s.pending_buf[s.pending++] = s.bi_buf & 0xff;
    s.bi_buf >>= 8;
    s.bi_valid -= 8;
  }
}


/* ===========================================================================
 * Compute the optimal bit lengths for a tree and update the total bit length
 * for the current block.
 * IN assertion: the fields freq and dad are set, heap[heap_max] and
 *    above are the tree nodes sorted by increasing frequency.
 * OUT assertions: the field len is set to the optimal bit length, the
 *     array bl_count contains the frequencies for each bit length.
 *     The length opt_len is updated; static_len is also updated if stree is
 *     not null.
 */
function gen_bitlen(s, desc)
//    deflate_state *s;
//    tree_desc *desc;    /* the tree descriptor */
{
  var tree            = desc.dyn_tree;
  var max_code        = desc.max_code;
  var stree           = desc.stat_desc.static_tree;
  var has_stree       = desc.stat_desc.has_stree;
  var extra           = desc.stat_desc.extra_bits;
  var base            = desc.stat_desc.extra_base;
  var max_length      = desc.stat_desc.max_length;
  var h;              /* heap index */
  var n, m;           /* iterate over the tree elements */
  var bits;           /* bit length */
  var xbits;          /* extra bits */
  var f;              /* frequency */
  var overflow = 0;   /* number of elements with bit length too large */

  for (bits = 0; bits <= MAX_BITS; bits++) {
    s.bl_count[bits] = 0;
  }

  /* In a first pass, compute the optimal bit lengths (which may
   * overflow in the case of the bit length tree).
   */
  tree[s.heap[s.heap_max] * 2 + 1]/*.Len*/ = 0; /* root of the heap */

  for (h = s.heap_max + 1; h < HEAP_SIZE; h++) {
    n = s.heap[h];
    bits = tree[tree[n * 2 + 1]/*.Dad*/ * 2 + 1]/*.Len*/ + 1;
    if (bits > max_length) {
      bits = max_length;
      overflow++;
    }
    tree[n * 2 + 1]/*.Len*/ = bits;
    /* We overwrite tree[n].Dad which is no longer needed */

    if (n > max_code) { continue; } /* not a leaf node */

    s.bl_count[bits]++;
    xbits = 0;
    if (n >= base) {
      xbits = extra[n - base];
    }
    f = tree[n * 2]/*.Freq*/;
    s.opt_len += f * (bits + xbits);
    if (has_stree) {
      s.static_len += f * (stree[n * 2 + 1]/*.Len*/ + xbits);
    }
  }
  if (overflow === 0) { return; }

  // Trace((stderr,"\nbit length overflow\n"));
  /* This happens for example on obj2 and pic of the Calgary corpus */

  /* Find the first bit length which could increase: */
  do {
    bits = max_length - 1;
    while (s.bl_count[bits] === 0) { bits--; }
    s.bl_count[bits]--;      /* move one leaf down the tree */
    s.bl_count[bits + 1] += 2; /* move one overflow item as its brother */
    s.bl_count[max_length]--;
    /* The brother of the overflow item also moves one step up,
     * but this does not affect bl_count[max_length]
     */
    overflow -= 2;
  } while (overflow > 0);

  /* Now recompute all bit lengths, scanning in increasing frequency.
   * h is still equal to HEAP_SIZE. (It is simpler to reconstruct all
   * lengths instead of fixing only the wrong ones. This idea is taken
   * from 'ar' written by Haruhiko Okumura.)
   */
  for (bits = max_length; bits !== 0; bits--) {
    n = s.bl_count[bits];
    while (n !== 0) {
      m = s.heap[--h];
      if (m > max_code) { continue; }
      if (tree[m * 2 + 1]/*.Len*/ !== bits) {
        // Trace((stderr,"code %d bits %d->%d\n", m, tree[m].Len, bits));
        s.opt_len += (bits - tree[m * 2 + 1]/*.Len*/) * tree[m * 2]/*.Freq*/;
        tree[m * 2 + 1]/*.Len*/ = bits;
      }
      n--;
    }
  }
}


/* ===========================================================================
 * Generate the codes for a given tree and bit counts (which need not be
 * optimal).
 * IN assertion: the array bl_count contains the bit length statistics for
 * the given tree and the field len is set for all tree elements.
 * OUT assertion: the field code is set for all tree elements of non
 *     zero code length.
 */
function gen_codes(tree, max_code, bl_count)
//    ct_data *tree;             /* the tree to decorate */
//    int max_code;              /* largest code with non zero frequency */
//    ushf *bl_count;            /* number of codes at each bit length */
{
  var next_code = new Array(MAX_BITS + 1); /* next code value for each bit length */
  var code = 0;              /* running code value */
  var bits;                  /* bit index */
  var n;                     /* code index */

  /* The distribution counts are first used to generate the code values
   * without bit reversal.
   */
  for (bits = 1; bits <= MAX_BITS; bits++) {
    next_code[bits] = code = (code + bl_count[bits - 1]) << 1;
  }
  /* Check that the bit counts in bl_count are consistent. The last code
   * must be all ones.
   */
  //Assert (code + bl_count[MAX_BITS]-1 == (1<<MAX_BITS)-1,
  //        "inconsistent bit counts");
  //Tracev((stderr,"\ngen_codes: max_code %d ", max_code));

  for (n = 0;  n <= max_code; n++) {
    var len = tree[n * 2 + 1]/*.Len*/;
    if (len === 0) { continue; }
    /* Now reverse the bits */
    tree[n * 2]/*.Code*/ = bi_reverse(next_code[len]++, len);

    //Tracecv(tree != static_ltree, (stderr,"\nn %3d %c l %2d c %4x (%x) ",
    //     n, (isgraph(n) ? n : ' '), len, tree[n].Code, next_code[len]-1));
  }
}


/* ===========================================================================
 * Initialize the various 'constant' tables.
 */
function tr_static_init() {
  var n;        /* iterates over tree elements */
  var bits;     /* bit counter */
  var length;   /* length value */
  var code;     /* code value */
  var dist;     /* distance index */
  var bl_count = new Array(MAX_BITS + 1);
  /* number of codes at each bit length for an optimal tree */

  // do check in _tr_init()
  //if (static_init_done) return;

  /* For some embedded targets, global variables are not initialized: */
/*#ifdef NO_INIT_GLOBAL_POINTERS
  static_l_desc.static_tree = static_ltree;
  static_l_desc.extra_bits = extra_lbits;
  static_d_desc.static_tree = static_dtree;
  static_d_desc.extra_bits = extra_dbits;
  static_bl_desc.extra_bits = extra_blbits;
#endif*/

  /* Initialize the mapping length (0..255) -> length code (0..28) */
  length = 0;
  for (code = 0; code < LENGTH_CODES - 1; code++) {
    base_length[code] = length;
    for (n = 0; n < (1 << extra_lbits[code]); n++) {
      _length_code[length++] = code;
    }
  }
  //Assert (length == 256, "tr_static_init: length != 256");
  /* Note that the length 255 (match length 258) can be represented
   * in two different ways: code 284 + 5 bits or code 285, so we
   * overwrite length_code[255] to use the best encoding:
   */
  _length_code[length - 1] = code;

  /* Initialize the mapping dist (0..32K) -> dist code (0..29) */
  dist = 0;
  for (code = 0; code < 16; code++) {
    base_dist[code] = dist;
    for (n = 0; n < (1 << extra_dbits[code]); n++) {
      _dist_code[dist++] = code;
    }
  }
  //Assert (dist == 256, "tr_static_init: dist != 256");
  dist >>= 7; /* from now on, all distances are divided by 128 */
  for (; code < D_CODES; code++) {
    base_dist[code] = dist << 7;
    for (n = 0; n < (1 << (extra_dbits[code] - 7)); n++) {
      _dist_code[256 + dist++] = code;
    }
  }
  //Assert (dist == 256, "tr_static_init: 256+dist != 512");

  /* Construct the codes of the static literal tree */
  for (bits = 0; bits <= MAX_BITS; bits++) {
    bl_count[bits] = 0;
  }

  n = 0;
  while (n <= 143) {
    static_ltree[n * 2 + 1]/*.Len*/ = 8;
    n++;
    bl_count[8]++;
  }
  while (n <= 255) {
    static_ltree[n * 2 + 1]/*.Len*/ = 9;
    n++;
    bl_count[9]++;
  }
  while (n <= 279) {
    static_ltree[n * 2 + 1]/*.Len*/ = 7;
    n++;
    bl_count[7]++;
  }
  while (n <= 287) {
    static_ltree[n * 2 + 1]/*.Len*/ = 8;
    n++;
    bl_count[8]++;
  }
  /* Codes 286 and 287 do not exist, but we must include them in the
   * tree construction to get a canonical Huffman tree (longest code
   * all ones)
   */
  gen_codes(static_ltree, L_CODES + 1, bl_count);

  /* The static distance tree is trivial: */
  for (n = 0; n < D_CODES; n++) {
    static_dtree[n * 2 + 1]/*.Len*/ = 5;
    static_dtree[n * 2]/*.Code*/ = bi_reverse(n, 5);
  }

  // Now data ready and we can init static trees
  static_l_desc = new StaticTreeDesc(static_ltree, extra_lbits, LITERALS + 1, L_CODES, MAX_BITS);
  static_d_desc = new StaticTreeDesc(static_dtree, extra_dbits, 0,          D_CODES, MAX_BITS);
  static_bl_desc = new StaticTreeDesc(new Array(0), extra_blbits, 0,         BL_CODES, MAX_BL_BITS);

  //static_init_done = true;
}


/* ===========================================================================
 * Initialize a new block.
 */
function init_block(s) {
  var n; /* iterates over tree elements */

  /* Initialize the trees. */
  for (n = 0; n < L_CODES;  n++) { s.dyn_ltree[n * 2]/*.Freq*/ = 0; }
  for (n = 0; n < D_CODES;  n++) { s.dyn_dtree[n * 2]/*.Freq*/ = 0; }
  for (n = 0; n < BL_CODES; n++) { s.bl_tree[n * 2]/*.Freq*/ = 0; }

  s.dyn_ltree[END_BLOCK * 2]/*.Freq*/ = 1;
  s.opt_len = s.static_len = 0;
  s.last_lit = s.matches = 0;
}


/* ===========================================================================
 * Flush the bit buffer and align the output on a byte boundary
 */
function bi_windup(s)
{
  if (s.bi_valid > 8) {
    put_short(s, s.bi_buf);
  } else if (s.bi_valid > 0) {
    //put_byte(s, (Byte)s->bi_buf);
    s.pending_buf[s.pending++] = s.bi_buf;
  }
  s.bi_buf = 0;
  s.bi_valid = 0;
}

/* ===========================================================================
 * Copy a stored block, storing first the length and its
 * one's complement if requested.
 */
function copy_block(s, buf, len, header)
//DeflateState *s;
//charf    *buf;    /* the input data */
//unsigned len;     /* its length */
//int      header;  /* true if block header must be written */
{
  bi_windup(s);        /* align on byte boundary */

  if (header) {
    put_short(s, len);
    put_short(s, ~len);
  }
//  while (len--) {
//    put_byte(s, *buf++);
//  }
  common$e.arraySet(s.pending_buf, s.window, buf, len, s.pending);
  s.pending += len;
}

/* ===========================================================================
 * Compares to subtrees, using the tree depth as tie breaker when
 * the subtrees have equal frequency. This minimizes the worst case length.
 */
function smaller(tree, n, m, depth) {
  var _n2 = n * 2;
  var _m2 = m * 2;
  return (tree[_n2]/*.Freq*/ < tree[_m2]/*.Freq*/ ||
         (tree[_n2]/*.Freq*/ === tree[_m2]/*.Freq*/ && depth[n] <= depth[m]));
}

/* ===========================================================================
 * Restore the heap property by moving down the tree starting at node k,
 * exchanging a node with the smallest of its two sons if necessary, stopping
 * when the heap property is re-established (each father smaller than its
 * two sons).
 */
function pqdownheap(s, tree, k)
//    deflate_state *s;
//    ct_data *tree;  /* the tree to restore */
//    int k;               /* node to move down */
{
  var v = s.heap[k];
  var j = k << 1;  /* left son of k */
  while (j <= s.heap_len) {
    /* Set j to the smallest of the two sons: */
    if (j < s.heap_len &&
      smaller(tree, s.heap[j + 1], s.heap[j], s.depth)) {
      j++;
    }
    /* Exit if v is smaller than both sons */
    if (smaller(tree, v, s.heap[j], s.depth)) { break; }

    /* Exchange v with the smallest son */
    s.heap[k] = s.heap[j];
    k = j;

    /* And continue down the tree, setting j to the left son of k */
    j <<= 1;
  }
  s.heap[k] = v;
}


// inlined manually
// var SMALLEST = 1;

/* ===========================================================================
 * Send the block data compressed using the given Huffman trees
 */
function compress_block(s, ltree, dtree)
//    deflate_state *s;
//    const ct_data *ltree; /* literal tree */
//    const ct_data *dtree; /* distance tree */
{
  var dist;           /* distance of matched string */
  var lc;             /* match length or unmatched char (if dist == 0) */
  var lx = 0;         /* running index in l_buf */
  var code;           /* the code to send */
  var extra;          /* number of extra bits to send */

  if (s.last_lit !== 0) {
    do {
      dist = (s.pending_buf[s.d_buf + lx * 2] << 8) | (s.pending_buf[s.d_buf + lx * 2 + 1]);
      lc = s.pending_buf[s.l_buf + lx];
      lx++;

      if (dist === 0) {
        send_code(s, lc, ltree); /* send a literal byte */
        //Tracecv(isgraph(lc), (stderr," '%c' ", lc));
      } else {
        /* Here, lc is the match length - MIN_MATCH */
        code = _length_code[lc];
        send_code(s, code + LITERALS + 1, ltree); /* send the length code */
        extra = extra_lbits[code];
        if (extra !== 0) {
          lc -= base_length[code];
          send_bits(s, lc, extra);       /* send the extra length bits */
        }
        dist--; /* dist is now the match distance - 1 */
        code = d_code(dist);
        //Assert (code < D_CODES, "bad d_code");

        send_code(s, code, dtree);       /* send the distance code */
        extra = extra_dbits[code];
        if (extra !== 0) {
          dist -= base_dist[code];
          send_bits(s, dist, extra);   /* send the extra distance bits */
        }
      } /* literal or match pair ? */

      /* Check that the overlay between pending_buf and d_buf+l_buf is ok: */
      //Assert((uInt)(s->pending) < s->lit_bufsize + 2*lx,
      //       "pendingBuf overflow");

    } while (lx < s.last_lit);
  }

  send_code(s, END_BLOCK, ltree);
}


/* ===========================================================================
 * Construct one Huffman tree and assigns the code bit strings and lengths.
 * Update the total bit length for the current block.
 * IN assertion: the field freq is set for all tree elements.
 * OUT assertions: the fields len and code are set to the optimal bit length
 *     and corresponding code. The length opt_len is updated; static_len is
 *     also updated if stree is not null. The field max_code is set.
 */
function build_tree(s, desc)
//    deflate_state *s;
//    tree_desc *desc; /* the tree descriptor */
{
  var tree     = desc.dyn_tree;
  var stree    = desc.stat_desc.static_tree;
  var has_stree = desc.stat_desc.has_stree;
  var elems    = desc.stat_desc.elems;
  var n, m;          /* iterate over heap elements */
  var max_code = -1; /* largest code with non zero frequency */
  var node;          /* new node being created */

  /* Construct the initial heap, with least frequent element in
   * heap[SMALLEST]. The sons of heap[n] are heap[2*n] and heap[2*n+1].
   * heap[0] is not used.
   */
  s.heap_len = 0;
  s.heap_max = HEAP_SIZE;

  for (n = 0; n < elems; n++) {
    if (tree[n * 2]/*.Freq*/ !== 0) {
      s.heap[++s.heap_len] = max_code = n;
      s.depth[n] = 0;

    } else {
      tree[n * 2 + 1]/*.Len*/ = 0;
    }
  }

  /* The pkzip format requires that at least one distance code exists,
   * and that at least one bit should be sent even if there is only one
   * possible code. So to avoid special checks later on we force at least
   * two codes of non zero frequency.
   */
  while (s.heap_len < 2) {
    node = s.heap[++s.heap_len] = (max_code < 2 ? ++max_code : 0);
    tree[node * 2]/*.Freq*/ = 1;
    s.depth[node] = 0;
    s.opt_len--;

    if (has_stree) {
      s.static_len -= stree[node * 2 + 1]/*.Len*/;
    }
    /* node is 0 or 1 so it does not have extra bits */
  }
  desc.max_code = max_code;

  /* The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree,
   * establish sub-heaps of increasing lengths:
   */
  for (n = (s.heap_len >> 1/*int /2*/); n >= 1; n--) { pqdownheap(s, tree, n); }

  /* Construct the Huffman tree by repeatedly combining the least two
   * frequent nodes.
   */
  node = elems;              /* next internal node of the tree */
  do {
    //pqremove(s, tree, n);  /* n = node of least frequency */
    /*** pqremove ***/
    n = s.heap[1/*SMALLEST*/];
    s.heap[1/*SMALLEST*/] = s.heap[s.heap_len--];
    pqdownheap(s, tree, 1/*SMALLEST*/);
    /***/

    m = s.heap[1/*SMALLEST*/]; /* m = node of next least frequency */

    s.heap[--s.heap_max] = n; /* keep the nodes sorted by frequency */
    s.heap[--s.heap_max] = m;

    /* Create a new node father of n and m */
    tree[node * 2]/*.Freq*/ = tree[n * 2]/*.Freq*/ + tree[m * 2]/*.Freq*/;
    s.depth[node] = (s.depth[n] >= s.depth[m] ? s.depth[n] : s.depth[m]) + 1;
    tree[n * 2 + 1]/*.Dad*/ = tree[m * 2 + 1]/*.Dad*/ = node;

    /* and insert the new node in the heap */
    s.heap[1/*SMALLEST*/] = node++;
    pqdownheap(s, tree, 1/*SMALLEST*/);

  } while (s.heap_len >= 2);

  s.heap[--s.heap_max] = s.heap[1/*SMALLEST*/];

  /* At this point, the fields freq and dad are set. We can now
   * generate the bit lengths.
   */
  gen_bitlen(s, desc);

  /* The field len is now set, we can generate the bit codes */
  gen_codes(tree, max_code, s.bl_count);
}


/* ===========================================================================
 * Scan a literal or distance tree to determine the frequencies of the codes
 * in the bit length tree.
 */
function scan_tree(s, tree, max_code)
//    deflate_state *s;
//    ct_data *tree;   /* the tree to be scanned */
//    int max_code;    /* and its largest code of non zero frequency */
{
  var n;                     /* iterates over all tree elements */
  var prevlen = -1;          /* last emitted length */
  var curlen;                /* length of current code */

  var nextlen = tree[0 * 2 + 1]/*.Len*/; /* length of next code */

  var count = 0;             /* repeat count of the current code */
  var max_count = 7;         /* max repeat count */
  var min_count = 4;         /* min repeat count */

  if (nextlen === 0) {
    max_count = 138;
    min_count = 3;
  }
  tree[(max_code + 1) * 2 + 1]/*.Len*/ = 0xffff; /* guard */

  for (n = 0; n <= max_code; n++) {
    curlen = nextlen;
    nextlen = tree[(n + 1) * 2 + 1]/*.Len*/;

    if (++count < max_count && curlen === nextlen) {
      continue;

    } else if (count < min_count) {
      s.bl_tree[curlen * 2]/*.Freq*/ += count;

    } else if (curlen !== 0) {

      if (curlen !== prevlen) { s.bl_tree[curlen * 2]/*.Freq*/++; }
      s.bl_tree[REP_3_6 * 2]/*.Freq*/++;

    } else if (count <= 10) {
      s.bl_tree[REPZ_3_10 * 2]/*.Freq*/++;

    } else {
      s.bl_tree[REPZ_11_138 * 2]/*.Freq*/++;
    }

    count = 0;
    prevlen = curlen;

    if (nextlen === 0) {
      max_count = 138;
      min_count = 3;

    } else if (curlen === nextlen) {
      max_count = 6;
      min_count = 3;

    } else {
      max_count = 7;
      min_count = 4;
    }
  }
}


/* ===========================================================================
 * Send a literal or distance tree in compressed form, using the codes in
 * bl_tree.
 */
function send_tree(s, tree, max_code)
//    deflate_state *s;
//    ct_data *tree; /* the tree to be scanned */
//    int max_code;       /* and its largest code of non zero frequency */
{
  var n;                     /* iterates over all tree elements */
  var prevlen = -1;          /* last emitted length */
  var curlen;                /* length of current code */

  var nextlen = tree[0 * 2 + 1]/*.Len*/; /* length of next code */

  var count = 0;             /* repeat count of the current code */
  var max_count = 7;         /* max repeat count */
  var min_count = 4;         /* min repeat count */

  /* tree[max_code+1].Len = -1; */  /* guard already set */
  if (nextlen === 0) {
    max_count = 138;
    min_count = 3;
  }

  for (n = 0; n <= max_code; n++) {
    curlen = nextlen;
    nextlen = tree[(n + 1) * 2 + 1]/*.Len*/;

    if (++count < max_count && curlen === nextlen) {
      continue;

    } else if (count < min_count) {
      do { send_code(s, curlen, s.bl_tree); } while (--count !== 0);

    } else if (curlen !== 0) {
      if (curlen !== prevlen) {
        send_code(s, curlen, s.bl_tree);
        count--;
      }
      //Assert(count >= 3 && count <= 6, " 3_6?");
      send_code(s, REP_3_6, s.bl_tree);
      send_bits(s, count - 3, 2);

    } else if (count <= 10) {
      send_code(s, REPZ_3_10, s.bl_tree);
      send_bits(s, count - 3, 3);

    } else {
      send_code(s, REPZ_11_138, s.bl_tree);
      send_bits(s, count - 11, 7);
    }

    count = 0;
    prevlen = curlen;
    if (nextlen === 0) {
      max_count = 138;
      min_count = 3;

    } else if (curlen === nextlen) {
      max_count = 6;
      min_count = 3;

    } else {
      max_count = 7;
      min_count = 4;
    }
  }
}


/* ===========================================================================
 * Construct the Huffman tree for the bit lengths and return the index in
 * bl_order of the last bit length code to send.
 */
function build_bl_tree(s) {
  var max_blindex;  /* index of last bit length code of non zero freq */

  /* Determine the bit length frequencies for literal and distance trees */
  scan_tree(s, s.dyn_ltree, s.l_desc.max_code);
  scan_tree(s, s.dyn_dtree, s.d_desc.max_code);

  /* Build the bit length tree: */
  build_tree(s, s.bl_desc);
  /* opt_len now includes the length of the tree representations, except
   * the lengths of the bit lengths codes and the 5+5+4 bits for the counts.
   */

  /* Determine the number of bit length codes to send. The pkzip format
   * requires that at least 4 bit length codes be sent. (appnote.txt says
   * 3 but the actual value used is 4.)
   */
  for (max_blindex = BL_CODES - 1; max_blindex >= 3; max_blindex--) {
    if (s.bl_tree[bl_order[max_blindex] * 2 + 1]/*.Len*/ !== 0) {
      break;
    }
  }
  /* Update opt_len to include the bit length tree and counts */
  s.opt_len += 3 * (max_blindex + 1) + 5 + 5 + 4;
  //Tracev((stderr, "\ndyn trees: dyn %ld, stat %ld",
  //        s->opt_len, s->static_len));

  return max_blindex;
}


/* ===========================================================================
 * Send the header for a block using dynamic Huffman trees: the counts, the
 * lengths of the bit length codes, the literal tree and the distance tree.
 * IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4.
 */
function send_all_trees(s, lcodes, dcodes, blcodes)
//    deflate_state *s;
//    int lcodes, dcodes, blcodes; /* number of codes for each tree */
{
  var rank;                    /* index in bl_order */

  //Assert (lcodes >= 257 && dcodes >= 1 && blcodes >= 4, "not enough codes");
  //Assert (lcodes <= L_CODES && dcodes <= D_CODES && blcodes <= BL_CODES,
  //        "too many codes");
  //Tracev((stderr, "\nbl counts: "));
  send_bits(s, lcodes - 257, 5); /* not +255 as stated in appnote.txt */
  send_bits(s, dcodes - 1,   5);
  send_bits(s, blcodes - 4,  4); /* not -3 as stated in appnote.txt */
  for (rank = 0; rank < blcodes; rank++) {
    //Tracev((stderr, "\nbl code %2d ", bl_order[rank]));
    send_bits(s, s.bl_tree[bl_order[rank] * 2 + 1]/*.Len*/, 3);
  }
  //Tracev((stderr, "\nbl tree: sent %ld", s->bits_sent));

  send_tree(s, s.dyn_ltree, lcodes - 1); /* literal tree */
  //Tracev((stderr, "\nlit tree: sent %ld", s->bits_sent));

  send_tree(s, s.dyn_dtree, dcodes - 1); /* distance tree */
  //Tracev((stderr, "\ndist tree: sent %ld", s->bits_sent));
}


/* ===========================================================================
 * Check if the data type is TEXT or BINARY, using the following algorithm:
 * - TEXT if the two conditions below are satisfied:
 *    a) There are no non-portable control characters belonging to the
 *       "black list" (0..6, 14..25, 28..31).
 *    b) There is at least one printable character belonging to the
 *       "white list" (9 {TAB}, 10 {LF}, 13 {CR}, 32..255).
 * - BINARY otherwise.
 * - The following partially-portable control characters form a
 *   "gray list" that is ignored in this detection algorithm:
 *   (7 {BEL}, 8 {BS}, 11 {VT}, 12 {FF}, 26 {SUB}, 27 {ESC}).
 * IN assertion: the fields Freq of dyn_ltree are set.
 */
function detect_data_type(s) {
  /* black_mask is the bit mask of black-listed bytes
   * set bits 0..6, 14..25, and 28..31
   * 0xf3ffc07f = binary 11110011111111111100000001111111
   */
  var black_mask = 0xf3ffc07f;
  var n;

  /* Check for non-textual ("black-listed") bytes. */
  for (n = 0; n <= 31; n++, black_mask >>>= 1) {
    if ((black_mask & 1) && (s.dyn_ltree[n * 2]/*.Freq*/ !== 0)) {
      return Z_BINARY;
    }
  }

  /* Check for textual ("white-listed") bytes. */
  if (s.dyn_ltree[9 * 2]/*.Freq*/ !== 0 || s.dyn_ltree[10 * 2]/*.Freq*/ !== 0 ||
      s.dyn_ltree[13 * 2]/*.Freq*/ !== 0) {
    return Z_TEXT;
  }
  for (n = 32; n < LITERALS; n++) {
    if (s.dyn_ltree[n * 2]/*.Freq*/ !== 0) {
      return Z_TEXT;
    }
  }

  /* There are no "black-listed" or "white-listed" bytes:
   * this stream either is empty or has tolerated ("gray-listed") bytes only.
   */
  return Z_BINARY;
}


var static_init_done = false;

/* ===========================================================================
 * Initialize the tree data structures for a new zlib stream.
 */
function _tr_init(s)
{

  if (!static_init_done) {
    tr_static_init();
    static_init_done = true;
  }

  s.l_desc  = new TreeDesc(s.dyn_ltree, static_l_desc);
  s.d_desc  = new TreeDesc(s.dyn_dtree, static_d_desc);
  s.bl_desc = new TreeDesc(s.bl_tree, static_bl_desc);

  s.bi_buf = 0;
  s.bi_valid = 0;

  /* Initialize the first block of the first file: */
  init_block(s);
}


/* ===========================================================================
 * Send a stored block
 */
function _tr_stored_block(s, buf, stored_len, last)
//DeflateState *s;
//charf *buf;       /* input block */
//ulg stored_len;   /* length of input block */
//int last;         /* one if this is the last block for a file */
{
  send_bits(s, (STORED_BLOCK << 1) + (last ? 1 : 0), 3);    /* send block type */
  copy_block(s, buf, stored_len, true); /* with header */
}


/* ===========================================================================
 * Send one empty static block to give enough lookahead for inflate.
 * This takes 10 bits, of which 7 may remain in the bit buffer.
 */
function _tr_align(s) {
  send_bits(s, STATIC_TREES << 1, 3);
  send_code(s, END_BLOCK, static_ltree);
  bi_flush(s);
}


/* ===========================================================================
 * Determine the best encoding for the current block: dynamic trees, static
 * trees or store, and output the encoded block to the zip file.
 */
function _tr_flush_block(s, buf, stored_len, last)
//DeflateState *s;
//charf *buf;       /* input block, or NULL if too old */
//ulg stored_len;   /* length of input block */
//int last;         /* one if this is the last block for a file */
{
  var opt_lenb, static_lenb;  /* opt_len and static_len in bytes */
  var max_blindex = 0;        /* index of last bit length code of non zero freq */

  /* Build the Huffman trees unless a stored block is forced */
  if (s.level > 0) {

    /* Check if the file is binary or text */
    if (s.strm.data_type === Z_UNKNOWN) {
      s.strm.data_type = detect_data_type(s);
    }

    /* Construct the literal and distance trees */
    build_tree(s, s.l_desc);
    // Tracev((stderr, "\nlit data: dyn %ld, stat %ld", s->opt_len,
    //        s->static_len));

    build_tree(s, s.d_desc);
    // Tracev((stderr, "\ndist data: dyn %ld, stat %ld", s->opt_len,
    //        s->static_len));
    /* At this point, opt_len and static_len are the total bit lengths of
     * the compressed block data, excluding the tree representations.
     */

    /* Build the bit length tree for the above two trees, and get the index
     * in bl_order of the last bit length code to send.
     */
    max_blindex = build_bl_tree(s);

    /* Determine the best encoding. Compute the block lengths in bytes. */
    opt_lenb = (s.opt_len + 3 + 7) >>> 3;
    static_lenb = (s.static_len + 3 + 7) >>> 3;

    // Tracev((stderr, "\nopt %lu(%lu) stat %lu(%lu) stored %lu lit %u ",
    //        opt_lenb, s->opt_len, static_lenb, s->static_len, stored_len,
    //        s->last_lit));

    if (static_lenb <= opt_lenb) { opt_lenb = static_lenb; }

  } else {
    // Assert(buf != (char*)0, "lost buf");
    opt_lenb = static_lenb = stored_len + 5; /* force a stored block */
  }

  if ((stored_len + 4 <= opt_lenb) && (buf !== -1)) {
    /* 4: two words for the lengths */

    /* The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE.
     * Otherwise we can't have processed more than WSIZE input bytes since
     * the last block flush, because compression would have been
     * successful. If LIT_BUFSIZE <= WSIZE, it is never too late to
     * transform a block into a stored block.
     */
    _tr_stored_block(s, buf, stored_len, last);

  } else if (s.strategy === Z_FIXED || static_lenb === opt_lenb) {

    send_bits(s, (STATIC_TREES << 1) + (last ? 1 : 0), 3);
    compress_block(s, static_ltree, static_dtree);

  } else {
    send_bits(s, (DYN_TREES << 1) + (last ? 1 : 0), 3);
    send_all_trees(s, s.l_desc.max_code + 1, s.d_desc.max_code + 1, max_blindex + 1);
    compress_block(s, s.dyn_ltree, s.dyn_dtree);
  }
  // Assert (s->compressed_len == s->bits_sent, "bad compressed size");
  /* The above check is made mod 2^32, for files larger than 512 MB
   * and uLong implemented on 32 bits.
   */
  init_block(s);

  if (last) {
    bi_windup(s);
  }
  // Tracev((stderr,"\ncomprlen %lu(%lu) ", s->compressed_len>>3,
  //       s->compressed_len-7*last));
}

/* ===========================================================================
 * Save the match info and tally the frequency counts. Return true if
 * the current block must be flushed.
 */
function _tr_tally(s, dist, lc)
//    deflate_state *s;
//    unsigned dist;  /* distance of matched string */
//    unsigned lc;    /* match length-MIN_MATCH or unmatched char (if dist==0) */
{
  //var out_length, in_length, dcode;

  s.pending_buf[s.d_buf + s.last_lit * 2]     = (dist >>> 8) & 0xff;
  s.pending_buf[s.d_buf + s.last_lit * 2 + 1] = dist & 0xff;

  s.pending_buf[s.l_buf + s.last_lit] = lc & 0xff;
  s.last_lit++;

  if (dist === 0) {
    /* lc is the unmatched char */
    s.dyn_ltree[lc * 2]/*.Freq*/++;
  } else {
    s.matches++;
    /* Here, lc is the match length - MIN_MATCH */
    dist--;             /* dist = match distance - 1 */
    //Assert((ush)dist < (ush)MAX_DIST(s) &&
    //       (ush)lc <= (ush)(MAX_MATCH-MIN_MATCH) &&
    //       (ush)d_code(dist) < (ush)D_CODES,  "_tr_tally: bad match");

    s.dyn_ltree[(_length_code[lc] + LITERALS + 1) * 2]/*.Freq*/++;
    s.dyn_dtree[d_code(dist) * 2]/*.Freq*/++;
  }

// (!) This block is disabled in zlib defaults,
// don't enable it for binary compatibility

//#ifdef TRUNCATE_BLOCK
//  /* Try to guess if it is profitable to stop the current block here */
//  if ((s.last_lit & 0x1fff) === 0 && s.level > 2) {
//    /* Compute an upper bound for the compressed length */
//    out_length = s.last_lit*8;
//    in_length = s.strstart - s.block_start;
//
//    for (dcode = 0; dcode < D_CODES; dcode++) {
//      out_length += s.dyn_dtree[dcode*2]/*.Freq*/ * (5 + extra_dbits[dcode]);
//    }
//    out_length >>>= 3;
//    //Tracev((stderr,"\nlast_lit %u, in %ld, out ~%ld(%ld%%) ",
//    //       s->last_lit, in_length, out_length,
//    //       100L - out_length*100L/in_length));
//    if (s.matches < (s.last_lit>>1)/*int /2*/ && out_length < (in_length>>1)/*int /2*/) {
//      return true;
//    }
//  }
//#endif

  return (s.last_lit === s.lit_bufsize - 1);
  /* We avoid equality with lit_bufsize because of wraparound at 64K
   * on 16 bit machines and because stored blocks are restricted to
   * 64K-1 bytes.
   */
}

var _tr_init_1  = _tr_init;
var _tr_stored_block_1 = _tr_stored_block;
var _tr_flush_block_1  = _tr_flush_block;
var _tr_tally_1 = _tr_tally;
var _tr_align_1 = _tr_align;

var trees = {
	_tr_init: _tr_init_1,
	_tr_stored_block: _tr_stored_block_1,
	_tr_flush_block: _tr_flush_block_1,
	_tr_tally: _tr_tally_1,
	_tr_align: _tr_align_1
};

// Note: adler32 takes 12% for level 0 and 2% for level 6.
// It isn't worth it to make additional optimizations as in original.
// Small size is preferable.

// (C) 1995-2013 Jean-loup Gailly and Mark Adler
// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented; you must not
//   claim that you wrote the original software. If you use this software
//   in a product, an acknowledgment in the product documentation would be
//   appreciated but is not required.
// 2. Altered source versions must be plainly marked as such, and must not be
//   misrepresented as being the original software.
// 3. This notice may not be removed or altered from any source distribution.

function adler32(adler, buf, len, pos) {
  var s1 = (adler & 0xffff) |0,
      s2 = ((adler >>> 16) & 0xffff) |0,
      n = 0;

  while (len !== 0) {
    // Set limit ~ twice less than 5552, to keep
    // s2 in 31-bits, because we force signed ints.
    // in other case %= will fail.
    n = len > 2000 ? 2000 : len;
    len -= n;

    do {
      s1 = (s1 + buf[pos++]) |0;
      s2 = (s2 + s1) |0;
    } while (--n);

    s1 %= 65521;
    s2 %= 65521;
  }

  return (s1 | (s2 << 16)) |0;
}


var adler32_1 = adler32;

// Note: we can't get significant speed boost here.
// So write code to minimize size - no pregenerated tables
// and array tools dependencies.

// (C) 1995-2013 Jean-loup Gailly and Mark Adler
// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented; you must not
//   claim that you wrote the original software. If you use this software
//   in a product, an acknowledgment in the product documentation would be
//   appreciated but is not required.
// 2. Altered source versions must be plainly marked as such, and must not be
//   misrepresented as being the original software.
// 3. This notice may not be removed or altered from any source distribution.

// Use ordinary array, since untyped makes no boost here
function makeTable() {
  var c, table = [];

  for (var n = 0; n < 256; n++) {
    c = n;
    for (var k = 0; k < 8; k++) {
      c = ((c & 1) ? (0xEDB88320 ^ (c >>> 1)) : (c >>> 1));
    }
    table[n] = c;
  }

  return table;
}

// Create table on load. Just 255 signed longs. Not a problem.
var crcTable = makeTable();


function crc32(crc, buf, len, pos) {
  var t = crcTable,
      end = pos + len;

  crc ^= -1;

  for (var i = pos; i < end; i++) {
    crc = (crc >>> 8) ^ t[(crc ^ buf[i]) & 0xFF];
  }

  return (crc ^ (-1)); // >>> 0;
}


var crc32_1 = crc32;

// (C) 1995-2013 Jean-loup Gailly and Mark Adler
// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented; you must not
//   claim that you wrote the original software. If you use this software
//   in a product, an acknowledgment in the product documentation would be
//   appreciated but is not required.
// 2. Altered source versions must be plainly marked as such, and must not be
//   misrepresented as being the original software.
// 3. This notice may not be removed or altered from any source distribution.

var messages = {
  2:      'need dictionary',     /* Z_NEED_DICT       2  */
  1:      'stream end',          /* Z_STREAM_END      1  */
  0:      '',                    /* Z_OK              0  */
  '-1':   'file error',          /* Z_ERRNO         (-1) */
  '-2':   'stream error',        /* Z_STREAM_ERROR  (-2) */
  '-3':   'data error',          /* Z_DATA_ERROR    (-3) */
  '-4':   'insufficient memory', /* Z_MEM_ERROR     (-4) */
  '-5':   'buffer error',        /* Z_BUF_ERROR     (-5) */
  '-6':   'incompatible version' /* Z_VERSION_ERROR (-6) */
};

// (C) 1995-2013 Jean-loup Gailly and Mark Adler
// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented; you must not
//   claim that you wrote the original software. If you use this software
//   in a product, an acknowledgment in the product documentation would be
//   appreciated but is not required.
// 2. Altered source versions must be plainly marked as such, and must not be
//   misrepresented as being the original software.
// 3. This notice may not be removed or altered from any source distribution.







/* Public constants ==========================================================*/
/* ===========================================================================*/


/* Allowed flush values; see deflate() and inflate() below for details */
var Z_NO_FLUSH      = 0;
var Z_PARTIAL_FLUSH = 1;
//var Z_SYNC_FLUSH    = 2;
var Z_FULL_FLUSH    = 3;
var Z_FINISH        = 4;
var Z_BLOCK         = 5;
//var Z_TREES         = 6;


/* Return codes for the compression/decompression functions. Negative values
 * are errors, positive values are used for special but normal events.
 */
var Z_OK            = 0;
var Z_STREAM_END    = 1;
//var Z_NEED_DICT     = 2;
//var Z_ERRNO         = -1;
var Z_STREAM_ERROR  = -2;
var Z_DATA_ERROR    = -3;
//var Z_MEM_ERROR     = -4;
var Z_BUF_ERROR     = -5;
//var Z_VERSION_ERROR = -6;


/* compression levels */
//var Z_NO_COMPRESSION      = 0;
//var Z_BEST_SPEED          = 1;
//var Z_BEST_COMPRESSION    = 9;
var Z_DEFAULT_COMPRESSION = -1;


var Z_FILTERED            = 1;
var Z_HUFFMAN_ONLY        = 2;
var Z_RLE                 = 3;
var Z_FIXED$1               = 4;
var Z_DEFAULT_STRATEGY    = 0;

/* Possible values of the data_type field (though see inflate()) */
//var Z_BINARY              = 0;
//var Z_TEXT                = 1;
//var Z_ASCII               = 1; // = Z_TEXT
var Z_UNKNOWN$1             = 2;


/* The deflate compression method */
var Z_DEFLATED  = 8;

/*============================================================================*/


var MAX_MEM_LEVEL = 9;
/* Maximum value for memLevel in deflateInit2 */
var MAX_WBITS = 15;
/* 32K LZ77 window */
var DEF_MEM_LEVEL = 8;


var LENGTH_CODES$1  = 29;
/* number of length codes, not counting the special END_BLOCK code */
var LITERALS$1      = 256;
/* number of literal bytes 0..255 */
var L_CODES$1       = LITERALS$1 + 1 + LENGTH_CODES$1;
/* number of Literal or Length codes, including the END_BLOCK code */
var D_CODES$1       = 30;
/* number of distance codes */
var BL_CODES$1      = 19;
/* number of codes used to transfer the bit lengths */
var HEAP_SIZE$1     = 2 * L_CODES$1 + 1;
/* maximum heap size */
var MAX_BITS$1  = 15;
/* All codes must not exceed MAX_BITS bits */

var MIN_MATCH$1 = 3;
var MAX_MATCH$1 = 258;
var MIN_LOOKAHEAD = (MAX_MATCH$1 + MIN_MATCH$1 + 1);

var PRESET_DICT = 0x20;

var INIT_STATE = 42;
var EXTRA_STATE = 69;
var NAME_STATE = 73;
var COMMENT_STATE = 91;
var HCRC_STATE = 103;
var BUSY_STATE = 113;
var FINISH_STATE = 666;

var BS_NEED_MORE      = 1; /* block not completed, need more input or more output */
var BS_BLOCK_DONE     = 2; /* block flush performed */
var BS_FINISH_STARTED = 3; /* finish started, need only more output at next deflate */
var BS_FINISH_DONE    = 4; /* finish done, accept no more input or output */

var OS_CODE = 0x03; // Unix :) . Don't detect, use this default.

function err(strm, errorCode) {
  strm.msg = messages[errorCode];
  return errorCode;
}

function rank(f) {
  return ((f) << 1) - ((f) > 4 ? 9 : 0);
}

function zero$1(buf) { var len = buf.length; while (--len >= 0) { buf[len] = 0; } }


/* =========================================================================
 * Flush as much pending output as possible. All deflate() output goes
 * through this function so some applications may wish to modify it
 * to avoid allocating a large strm->output buffer and copying into it.
 * (See also read_buf()).
 */
function flush_pending(strm) {
  var s = strm.state;

  //_tr_flush_bits(s);
  var len = s.pending;
  if (len > strm.avail_out) {
    len = strm.avail_out;
  }
  if (len === 0) { return; }

  common$e.arraySet(strm.output, s.pending_buf, s.pending_out, len, strm.next_out);
  strm.next_out += len;
  s.pending_out += len;
  strm.total_out += len;
  strm.avail_out -= len;
  s.pending -= len;
  if (s.pending === 0) {
    s.pending_out = 0;
  }
}


function flush_block_only(s, last) {
  trees._tr_flush_block(s, (s.block_start >= 0 ? s.block_start : -1), s.strstart - s.block_start, last);
  s.block_start = s.strstart;
  flush_pending(s.strm);
}


function put_byte(s, b) {
  s.pending_buf[s.pending++] = b;
}


/* =========================================================================
 * Put a short in the pending buffer. The 16-bit value is put in MSB order.
 * IN assertion: the stream state is correct and there is enough room in
 * pending_buf.
 */
function putShortMSB(s, b) {
//  put_byte(s, (Byte)(b >> 8));
//  put_byte(s, (Byte)(b & 0xff));
  s.pending_buf[s.pending++] = (b >>> 8) & 0xff;
  s.pending_buf[s.pending++] = b & 0xff;
}


/* ===========================================================================
 * Read a new buffer from the current input stream, update the adler32
 * and total number of bytes read.  All deflate() input goes through
 * this function so some applications may wish to modify it to avoid
 * allocating a large strm->input buffer and copying from it.
 * (See also flush_pending()).
 */
function read_buf(strm, buf, start, size) {
  var len = strm.avail_in;

  if (len > size) { len = size; }
  if (len === 0) { return 0; }

  strm.avail_in -= len;

  // zmemcpy(buf, strm->next_in, len);
  common$e.arraySet(buf, strm.input, strm.next_in, len, start);
  if (strm.state.wrap === 1) {
    strm.adler = adler32_1(strm.adler, buf, len, start);
  }

  else if (strm.state.wrap === 2) {
    strm.adler = crc32_1(strm.adler, buf, len, start);
  }

  strm.next_in += len;
  strm.total_in += len;

  return len;
}


/* ===========================================================================
 * Set match_start to the longest match starting at the given string and
 * return its length. Matches shorter or equal to prev_length are discarded,
 * in which case the result is equal to prev_length and match_start is
 * garbage.
 * IN assertions: cur_match is the head of the hash chain for the current
 *   string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1
 * OUT assertion: the match length is not greater than s->lookahead.
 */
function longest_match(s, cur_match) {
  var chain_length = s.max_chain_length;      /* max hash chain length */
  var scan = s.strstart; /* current string */
  var match;                       /* matched string */
  var len;                           /* length of current match */
  var best_len = s.prev_length;              /* best match length so far */
  var nice_match = s.nice_match;             /* stop if match long enough */
  var limit = (s.strstart > (s.w_size - MIN_LOOKAHEAD)) ?
      s.strstart - (s.w_size - MIN_LOOKAHEAD) : 0/*NIL*/;

  var _win = s.window; // shortcut

  var wmask = s.w_mask;
  var prev  = s.prev;

  /* Stop when cur_match becomes <= limit. To simplify the code,
   * we prevent matches with the string of window index 0.
   */

  var strend = s.strstart + MAX_MATCH$1;
  var scan_end1  = _win[scan + best_len - 1];
  var scan_end   = _win[scan + best_len];

  /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16.
   * It is easy to get rid of this optimization if necessary.
   */
  // Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever");

  /* Do not waste too much time if we already have a good match: */
  if (s.prev_length >= s.good_match) {
    chain_length >>= 2;
  }
  /* Do not look for matches beyond the end of the input. This is necessary
   * to make deflate deterministic.
   */
  if (nice_match > s.lookahead) { nice_match = s.lookahead; }

  // Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead");

  do {
    // Assert(cur_match < s->strstart, "no future");
    match = cur_match;

    /* Skip to next match if the match length cannot increase
     * or if the match length is less than 2.  Note that the checks below
     * for insufficient lookahead only occur occasionally for performance
     * reasons.  Therefore uninitialized memory will be accessed, and
     * conditional jumps will be made that depend on those values.
     * However the length of the match is limited to the lookahead, so
     * the output of deflate is not affected by the uninitialized values.
     */

    if (_win[match + best_len]     !== scan_end  ||
        _win[match + best_len - 1] !== scan_end1 ||
        _win[match]                !== _win[scan] ||
        _win[++match]              !== _win[scan + 1]) {
      continue;
    }

    /* The check at best_len-1 can be removed because it will be made
     * again later. (This heuristic is not always a win.)
     * It is not necessary to compare scan[2] and match[2] since they
     * are always equal when the other bytes match, given that
     * the hash keys are equal and that HASH_BITS >= 8.
     */
    scan += 2;
    match++;
    // Assert(*scan == *match, "match[2]?");

    /* We check for insufficient lookahead only every 8th comparison;
     * the 256th check will be made at strstart+258.
     */
    do {
      /*jshint noempty:false*/
    } while (_win[++scan] === _win[++match] && _win[++scan] === _win[++match] &&
             _win[++scan] === _win[++match] && _win[++scan] === _win[++match] &&
             _win[++scan] === _win[++match] && _win[++scan] === _win[++match] &&
             _win[++scan] === _win[++match] && _win[++scan] === _win[++match] &&
             scan < strend);

    // Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan");

    len = MAX_MATCH$1 - (strend - scan);
    scan = strend - MAX_MATCH$1;

    if (len > best_len) {
      s.match_start = cur_match;
      best_len = len;
      if (len >= nice_match) {
        break;
      }
      scan_end1  = _win[scan + best_len - 1];
      scan_end   = _win[scan + best_len];
    }
  } while ((cur_match = prev[cur_match & wmask]) > limit && --chain_length !== 0);

  if (best_len <= s.lookahead) {
    return best_len;
  }
  return s.lookahead;
}


/* ===========================================================================
 * Fill the window when the lookahead becomes insufficient.
 * Updates strstart and lookahead.
 *
 * IN assertion: lookahead < MIN_LOOKAHEAD
 * OUT assertions: strstart <= window_size-MIN_LOOKAHEAD
 *    At least one byte has been read, or avail_in == 0; reads are
 *    performed for at least two bytes (required for the zip translate_eol
 *    option -- not supported here).
 */
function fill_window(s) {
  var _w_size = s.w_size;
  var p, n, m, more, str;

  //Assert(s->lookahead < MIN_LOOKAHEAD, "already enough lookahead");

  do {
    more = s.window_size - s.lookahead - s.strstart;

    // JS ints have 32 bit, block below not needed
    /* Deal with !@#$% 64K limit: */
    //if (sizeof(int) <= 2) {
    //    if (more == 0 && s->strstart == 0 && s->lookahead == 0) {
    //        more = wsize;
    //
    //  } else if (more == (unsigned)(-1)) {
    //        /* Very unlikely, but possible on 16 bit machine if
    //         * strstart == 0 && lookahead == 1 (input done a byte at time)
    //         */
    //        more--;
    //    }
    //}


    /* If the window is almost full and there is insufficient lookahead,
     * move the upper half to the lower one to make room in the upper half.
     */
    if (s.strstart >= _w_size + (_w_size - MIN_LOOKAHEAD)) {

      common$e.arraySet(s.window, s.window, _w_size, _w_size, 0);
      s.match_start -= _w_size;
      s.strstart -= _w_size;
      /* we now have strstart >= MAX_DIST */
      s.block_start -= _w_size;

      /* Slide the hash table (could be avoided with 32 bit values
       at the expense of memory usage). We slide even when level == 0
       to keep the hash table consistent if we switch back to level > 0
       later. (Using level 0 permanently is not an optimal usage of
       zlib, so we don't care about this pathological case.)
       */

      n = s.hash_size;
      p = n;
      do {
        m = s.head[--p];
        s.head[p] = (m >= _w_size ? m - _w_size : 0);
      } while (--n);

      n = _w_size;
      p = n;
      do {
        m = s.prev[--p];
        s.prev[p] = (m >= _w_size ? m - _w_size : 0);
        /* If n is not on any hash chain, prev[n] is garbage but
         * its value will never be used.
         */
      } while (--n);

      more += _w_size;
    }
    if (s.strm.avail_in === 0) {
      break;
    }

    /* If there was no sliding:
     *    strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 &&
     *    more == window_size - lookahead - strstart
     * => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1)
     * => more >= window_size - 2*WSIZE + 2
     * In the BIG_MEM or MMAP case (not yet supported),
     *   window_size == input_size + MIN_LOOKAHEAD  &&
     *   strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD.
     * Otherwise, window_size == 2*WSIZE so more >= 2.
     * If there was sliding, more >= WSIZE. So in all cases, more >= 2.
     */
    //Assert(more >= 2, "more < 2");
    n = read_buf(s.strm, s.window, s.strstart + s.lookahead, more);
    s.lookahead += n;

    /* Initialize the hash value now that we have some input: */
    if (s.lookahead + s.insert >= MIN_MATCH$1) {
      str = s.strstart - s.insert;
      s.ins_h = s.window[str];

      /* UPDATE_HASH(s, s->ins_h, s->window[str + 1]); */
      s.ins_h = ((s.ins_h << s.hash_shift) ^ s.window[str + 1]) & s.hash_mask;
//#if MIN_MATCH != 3
//        Call update_hash() MIN_MATCH-3 more times
//#endif
      while (s.insert) {
        /* UPDATE_HASH(s, s->ins_h, s->window[str + MIN_MATCH-1]); */
        s.ins_h = ((s.ins_h << s.hash_shift) ^ s.window[str + MIN_MATCH$1 - 1]) & s.hash_mask;

        s.prev[str & s.w_mask] = s.head[s.ins_h];
        s.head[s.ins_h] = str;
        str++;
        s.insert--;
        if (s.lookahead + s.insert < MIN_MATCH$1) {
          break;
        }
      }
    }
    /* If the whole input has less than MIN_MATCH bytes, ins_h is garbage,
     * but this is not important since only literal bytes will be emitted.
     */

  } while (s.lookahead < MIN_LOOKAHEAD && s.strm.avail_in !== 0);

  /* If the WIN_INIT bytes after the end of the current data have never been
   * written, then zero those bytes in order to avoid memory check reports of
   * the use of uninitialized (or uninitialised as Julian writes) bytes by
   * the longest match routines.  Update the high water mark for the next
   * time through here.  WIN_INIT is set to MAX_MATCH since the longest match
   * routines allow scanning to strstart + MAX_MATCH, ignoring lookahead.
   */
//  if (s.high_water < s.window_size) {
//    var curr = s.strstart + s.lookahead;
//    var init = 0;
//
//    if (s.high_water < curr) {
//      /* Previous high water mark below current data -- zero WIN_INIT
//       * bytes or up to end of window, whichever is less.
//       */
//      init = s.window_size - curr;
//      if (init > WIN_INIT)
//        init = WIN_INIT;
//      zmemzero(s->window + curr, (unsigned)init);
//      s->high_water = curr + init;
//    }
//    else if (s->high_water < (ulg)curr + WIN_INIT) {
//      /* High water mark at or above current data, but below current data
//       * plus WIN_INIT -- zero out to current data plus WIN_INIT, or up
//       * to end of window, whichever is less.
//       */
//      init = (ulg)curr + WIN_INIT - s->high_water;
//      if (init > s->window_size - s->high_water)
//        init = s->window_size - s->high_water;
//      zmemzero(s->window + s->high_water, (unsigned)init);
//      s->high_water += init;
//    }
//  }
//
//  Assert((ulg)s->strstart <= s->window_size - MIN_LOOKAHEAD,
//    "not enough room for search");
}

/* ===========================================================================
 * Copy without compression as much as possible from the input stream, return
 * the current block state.
 * This function does not insert new strings in the dictionary since
 * uncompressible data is probably not useful. This function is used
 * only for the level=0 compression option.
 * NOTE: this function should be optimized to avoid extra copying from
 * window to pending_buf.
 */
function deflate_stored(s, flush) {
  /* Stored blocks are limited to 0xffff bytes, pending_buf is limited
   * to pending_buf_size, and each stored block has a 5 byte header:
   */
  var max_block_size = 0xffff;

  if (max_block_size > s.pending_buf_size - 5) {
    max_block_size = s.pending_buf_size - 5;
  }

  /* Copy as much as possible from input to output: */
  for (;;) {
    /* Fill the window as much as possible: */
    if (s.lookahead <= 1) {

      //Assert(s->strstart < s->w_size+MAX_DIST(s) ||
      //  s->block_start >= (long)s->w_size, "slide too late");
//      if (!(s.strstart < s.w_size + (s.w_size - MIN_LOOKAHEAD) ||
//        s.block_start >= s.w_size)) {
//        throw  new Error("slide too late");
//      }

      fill_window(s);
      if (s.lookahead === 0 && flush === Z_NO_FLUSH) {
        return BS_NEED_MORE;
      }

      if (s.lookahead === 0) {
        break;
      }
      /* flush the current block */
    }
    //Assert(s->block_start >= 0L, "block gone");
//    if (s.block_start < 0) throw new Error("block gone");

    s.strstart += s.lookahead;
    s.lookahead = 0;

    /* Emit a stored block if pending_buf will be full: */
    var max_start = s.block_start + max_block_size;

    if (s.strstart === 0 || s.strstart >= max_start) {
      /* strstart == 0 is possible when wraparound on 16-bit machine */
      s.lookahead = s.strstart - max_start;
      s.strstart = max_start;
      /*** FLUSH_BLOCK(s, 0); ***/
      flush_block_only(s, false);
      if (s.strm.avail_out === 0) {
        return BS_NEED_MORE;
      }
      /***/


    }
    /* Flush if we may have to slide, otherwise block_start may become
     * negative and the data will be gone:
     */
    if (s.strstart - s.block_start >= (s.w_size - MIN_LOOKAHEAD)) {
      /*** FLUSH_BLOCK(s, 0); ***/
      flush_block_only(s, false);
      if (s.strm.avail_out === 0) {
        return BS_NEED_MORE;
      }
      /***/
    }
  }

  s.insert = 0;

  if (flush === Z_FINISH) {
    /*** FLUSH_BLOCK(s, 1); ***/
    flush_block_only(s, true);
    if (s.strm.avail_out === 0) {
      return BS_FINISH_STARTED;
    }
    /***/
    return BS_FINISH_DONE;
  }

  if (s.strstart > s.block_start) {
    /*** FLUSH_BLOCK(s, 0); ***/
    flush_block_only(s, false);
    if (s.strm.avail_out === 0) {
      return BS_NEED_MORE;
    }
    /***/
  }

  return BS_NEED_MORE;
}

/* ===========================================================================
 * Compress as much as possible from the input stream, return the current
 * block state.
 * This function does not perform lazy evaluation of matches and inserts
 * new strings in the dictionary only for unmatched strings or for short
 * matches. It is used only for the fast compression options.
 */
function deflate_fast(s, flush) {
  var hash_head;        /* head of the hash chain */
  var bflush;           /* set if current block must be flushed */

  for (;;) {
    /* Make sure that we always have enough lookahead, except
     * at the end of the input file. We need MAX_MATCH bytes
     * for the next match, plus MIN_MATCH bytes to insert the
     * string following the next match.
     */
    if (s.lookahead < MIN_LOOKAHEAD) {
      fill_window(s);
      if (s.lookahead < MIN_LOOKAHEAD && flush === Z_NO_FLUSH) {
        return BS_NEED_MORE;
      }
      if (s.lookahead === 0) {
        break; /* flush the current block */
      }
    }

    /* Insert the string window[strstart .. strstart+2] in the
     * dictionary, and set hash_head to the head of the hash chain:
     */
    hash_head = 0/*NIL*/;
    if (s.lookahead >= MIN_MATCH$1) {
      /*** INSERT_STRING(s, s.strstart, hash_head); ***/
      s.ins_h = ((s.ins_h << s.hash_shift) ^ s.window[s.strstart + MIN_MATCH$1 - 1]) & s.hash_mask;
      hash_head = s.prev[s.strstart & s.w_mask] = s.head[s.ins_h];
      s.head[s.ins_h] = s.strstart;
      /***/
    }

    /* Find the longest match, discarding those <= prev_length.
     * At this point we have always match_length < MIN_MATCH
     */
    if (hash_head !== 0/*NIL*/ && ((s.strstart - hash_head) <= (s.w_size - MIN_LOOKAHEAD))) {
      /* To simplify the code, we prevent matches with the string
       * of window index 0 (in particular we have to avoid a match
       * of the string with itself at the start of the input file).
       */
      s.match_length = longest_match(s, hash_head);
      /* longest_match() sets match_start */
    }
    if (s.match_length >= MIN_MATCH$1) {
      // check_match(s, s.strstart, s.match_start, s.match_length); // for debug only

      /*** _tr_tally_dist(s, s.strstart - s.match_start,
                     s.match_length - MIN_MATCH, bflush); ***/
      bflush = trees._tr_tally(s, s.strstart - s.match_start, s.match_length - MIN_MATCH$1);

      s.lookahead -= s.match_length;

      /* Insert new strings in the hash table only if the match length
       * is not too large. This saves time but degrades compression.
       */
      if (s.match_length <= s.max_lazy_match/*max_insert_length*/ && s.lookahead >= MIN_MATCH$1) {
        s.match_length--; /* string at strstart already in table */
        do {
          s.strstart++;
          /*** INSERT_STRING(s, s.strstart, hash_head); ***/
          s.ins_h = ((s.ins_h << s.hash_shift) ^ s.window[s.strstart + MIN_MATCH$1 - 1]) & s.hash_mask;
          hash_head = s.prev[s.strstart & s.w_mask] = s.head[s.ins_h];
          s.head[s.ins_h] = s.strstart;
          /***/
          /* strstart never exceeds WSIZE-MAX_MATCH, so there are
           * always MIN_MATCH bytes ahead.
           */
        } while (--s.match_length !== 0);
        s.strstart++;
      } else
      {
        s.strstart += s.match_length;
        s.match_length = 0;
        s.ins_h = s.window[s.strstart];
        /* UPDATE_HASH(s, s.ins_h, s.window[s.strstart+1]); */
        s.ins_h = ((s.ins_h << s.hash_shift) ^ s.window[s.strstart + 1]) & s.hash_mask;

//#if MIN_MATCH != 3
//                Call UPDATE_HASH() MIN_MATCH-3 more times
//#endif
        /* If lookahead < MIN_MATCH, ins_h is garbage, but it does not
         * matter since it will be recomputed at next deflate call.
         */
      }
    } else {
      /* No match, output a literal byte */
      //Tracevv((stderr,"%c", s.window[s.strstart]));
      /*** _tr_tally_lit(s, s.window[s.strstart], bflush); ***/
      bflush = trees._tr_tally(s, 0, s.window[s.strstart]);

      s.lookahead--;
      s.strstart++;
    }
    if (bflush) {
      /*** FLUSH_BLOCK(s, 0); ***/
      flush_block_only(s, false);
      if (s.strm.avail_out === 0) {
        return BS_NEED_MORE;
      }
      /***/
    }
  }
  s.insert = ((s.strstart < (MIN_MATCH$1 - 1)) ? s.strstart : MIN_MATCH$1 - 1);
  if (flush === Z_FINISH) {
    /*** FLUSH_BLOCK(s, 1); ***/
    flush_block_only(s, true);
    if (s.strm.avail_out === 0) {
      return BS_FINISH_STARTED;
    }
    /***/
    return BS_FINISH_DONE;
  }
  if (s.last_lit) {
    /*** FLUSH_BLOCK(s, 0); ***/
    flush_block_only(s, false);
    if (s.strm.avail_out === 0) {
      return BS_NEED_MORE;
    }
    /***/
  }
  return BS_BLOCK_DONE;
}

/* ===========================================================================
 * Same as above, but achieves better compression. We use a lazy
 * evaluation for matches: a match is finally adopted only if there is
 * no better match at the next window position.
 */
function deflate_slow(s, flush) {
  var hash_head;          /* head of hash chain */
  var bflush;              /* set if current block must be flushed */

  var max_insert;

  /* Process the input block. */
  for (;;) {
    /* Make sure that we always have enough lookahead, except
     * at the end of the input file. We need MAX_MATCH bytes
     * for the next match, plus MIN_MATCH bytes to insert the
     * string following the next match.
     */
    if (s.lookahead < MIN_LOOKAHEAD) {
      fill_window(s);
      if (s.lookahead < MIN_LOOKAHEAD && flush === Z_NO_FLUSH) {
        return BS_NEED_MORE;
      }
      if (s.lookahead === 0) { break; } /* flush the current block */
    }

    /* Insert the string window[strstart .. strstart+2] in the
     * dictionary, and set hash_head to the head of the hash chain:
     */
    hash_head = 0/*NIL*/;
    if (s.lookahead >= MIN_MATCH$1) {
      /*** INSERT_STRING(s, s.strstart, hash_head); ***/
      s.ins_h = ((s.ins_h << s.hash_shift) ^ s.window[s.strstart + MIN_MATCH$1 - 1]) & s.hash_mask;
      hash_head = s.prev[s.strstart & s.w_mask] = s.head[s.ins_h];
      s.head[s.ins_h] = s.strstart;
      /***/
    }

    /* Find the longest match, discarding those <= prev_length.
     */
    s.prev_length = s.match_length;
    s.prev_match = s.match_start;
    s.match_length = MIN_MATCH$1 - 1;

    if (hash_head !== 0/*NIL*/ && s.prev_length < s.max_lazy_match &&
        s.strstart - hash_head <= (s.w_size - MIN_LOOKAHEAD)/*MAX_DIST(s)*/) {
      /* To simplify the code, we prevent matches with the string
       * of window index 0 (in particular we have to avoid a match
       * of the string with itself at the start of the input file).
       */
      s.match_length = longest_match(s, hash_head);
      /* longest_match() sets match_start */

      if (s.match_length <= 5 &&
         (s.strategy === Z_FILTERED || (s.match_length === MIN_MATCH$1 && s.strstart - s.match_start > 4096/*TOO_FAR*/))) {

        /* If prev_match is also MIN_MATCH, match_start is garbage
         * but we will ignore the current match anyway.
         */
        s.match_length = MIN_MATCH$1 - 1;
      }
    }
    /* If there was a match at the previous step and the current
     * match is not better, output the previous match:
     */
    if (s.prev_length >= MIN_MATCH$1 && s.match_length <= s.prev_length) {
      max_insert = s.strstart + s.lookahead - MIN_MATCH$1;
      /* Do not insert strings in hash table beyond this. */

      //check_match(s, s.strstart-1, s.prev_match, s.prev_length);

      /***_tr_tally_dist(s, s.strstart - 1 - s.prev_match,
                     s.prev_length - MIN_MATCH, bflush);***/
      bflush = trees._tr_tally(s, s.strstart - 1 - s.prev_match, s.prev_length - MIN_MATCH$1);
      /* Insert in hash table all strings up to the end of the match.
       * strstart-1 and strstart are already inserted. If there is not
       * enough lookahead, the last two strings are not inserted in
       * the hash table.
       */
      s.lookahead -= s.prev_length - 1;
      s.prev_length -= 2;
      do {
        if (++s.strstart <= max_insert) {
          /*** INSERT_STRING(s, s.strstart, hash_head); ***/
          s.ins_h = ((s.ins_h << s.hash_shift) ^ s.window[s.strstart + MIN_MATCH$1 - 1]) & s.hash_mask;
          hash_head = s.prev[s.strstart & s.w_mask] = s.head[s.ins_h];
          s.head[s.ins_h] = s.strstart;
          /***/
        }
      } while (--s.prev_length !== 0);
      s.match_available = 0;
      s.match_length = MIN_MATCH$1 - 1;
      s.strstart++;

      if (bflush) {
        /*** FLUSH_BLOCK(s, 0); ***/
        flush_block_only(s, false);
        if (s.strm.avail_out === 0) {
          return BS_NEED_MORE;
        }
        /***/
      }

    } else if (s.match_available) {
      /* If there was no match at the previous position, output a
       * single literal. If there was a match but the current match
       * is longer, truncate the previous match to a single literal.
       */
      //Tracevv((stderr,"%c", s->window[s->strstart-1]));
      /*** _tr_tally_lit(s, s.window[s.strstart-1], bflush); ***/
      bflush = trees._tr_tally(s, 0, s.window[s.strstart - 1]);

      if (bflush) {
        /*** FLUSH_BLOCK_ONLY(s, 0) ***/
        flush_block_only(s, false);
        /***/
      }
      s.strstart++;
      s.lookahead--;
      if (s.strm.avail_out === 0) {
        return BS_NEED_MORE;
      }
    } else {
      /* There is no previous match to compare with, wait for
       * the next step to decide.
       */
      s.match_available = 1;
      s.strstart++;
      s.lookahead--;
    }
  }
  //Assert (flush != Z_NO_FLUSH, "no flush?");
  if (s.match_available) {
    //Tracevv((stderr,"%c", s->window[s->strstart-1]));
    /*** _tr_tally_lit(s, s.window[s.strstart-1], bflush); ***/
    bflush = trees._tr_tally(s, 0, s.window[s.strstart - 1]);

    s.match_available = 0;
  }
  s.insert = s.strstart < MIN_MATCH$1 - 1 ? s.strstart : MIN_MATCH$1 - 1;
  if (flush === Z_FINISH) {
    /*** FLUSH_BLOCK(s, 1); ***/
    flush_block_only(s, true);
    if (s.strm.avail_out === 0) {
      return BS_FINISH_STARTED;
    }
    /***/
    return BS_FINISH_DONE;
  }
  if (s.last_lit) {
    /*** FLUSH_BLOCK(s, 0); ***/
    flush_block_only(s, false);
    if (s.strm.avail_out === 0) {
      return BS_NEED_MORE;
    }
    /***/
  }

  return BS_BLOCK_DONE;
}


/* ===========================================================================
 * For Z_RLE, simply look for runs of bytes, generate matches only of distance
 * one.  Do not maintain a hash table.  (It will be regenerated if this run of
 * deflate switches away from Z_RLE.)
 */
function deflate_rle(s, flush) {
  var bflush;            /* set if current block must be flushed */
  var prev;              /* byte at distance one to match */
  var scan, strend;      /* scan goes up to strend for length of run */

  var _win = s.window;

  for (;;) {
    /* Make sure that we always have enough lookahead, except
     * at the end of the input file. We need MAX_MATCH bytes
     * for the longest run, plus one for the unrolled loop.
     */
    if (s.lookahead <= MAX_MATCH$1) {
      fill_window(s);
      if (s.lookahead <= MAX_MATCH$1 && flush === Z_NO_FLUSH) {
        return BS_NEED_MORE;
      }
      if (s.lookahead === 0) { break; } /* flush the current block */
    }

    /* See how many times the previous byte repeats */
    s.match_length = 0;
    if (s.lookahead >= MIN_MATCH$1 && s.strstart > 0) {
      scan = s.strstart - 1;
      prev = _win[scan];
      if (prev === _win[++scan] && prev === _win[++scan] && prev === _win[++scan]) {
        strend = s.strstart + MAX_MATCH$1;
        do {
          /*jshint noempty:false*/
        } while (prev === _win[++scan] && prev === _win[++scan] &&
                 prev === _win[++scan] && prev === _win[++scan] &&
                 prev === _win[++scan] && prev === _win[++scan] &&
                 prev === _win[++scan] && prev === _win[++scan] &&
                 scan < strend);
        s.match_length = MAX_MATCH$1 - (strend - scan);
        if (s.match_length > s.lookahead) {
          s.match_length = s.lookahead;
        }
      }
      //Assert(scan <= s->window+(uInt)(s->window_size-1), "wild scan");
    }

    /* Emit match if have run of MIN_MATCH or longer, else emit literal */
    if (s.match_length >= MIN_MATCH$1) {
      //check_match(s, s.strstart, s.strstart - 1, s.match_length);

      /*** _tr_tally_dist(s, 1, s.match_length - MIN_MATCH, bflush); ***/
      bflush = trees._tr_tally(s, 1, s.match_length - MIN_MATCH$1);

      s.lookahead -= s.match_length;
      s.strstart += s.match_length;
      s.match_length = 0;
    } else {
      /* No match, output a literal byte */
      //Tracevv((stderr,"%c", s->window[s->strstart]));
      /*** _tr_tally_lit(s, s.window[s.strstart], bflush); ***/
      bflush = trees._tr_tally(s, 0, s.window[s.strstart]);

      s.lookahead--;
      s.strstart++;
    }
    if (bflush) {
      /*** FLUSH_BLOCK(s, 0); ***/
      flush_block_only(s, false);
      if (s.strm.avail_out === 0) {
        return BS_NEED_MORE;
      }
      /***/
    }
  }
  s.insert = 0;
  if (flush === Z_FINISH) {
    /*** FLUSH_BLOCK(s, 1); ***/
    flush_block_only(s, true);
    if (s.strm.avail_out === 0) {
      return BS_FINISH_STARTED;
    }
    /***/
    return BS_FINISH_DONE;
  }
  if (s.last_lit) {
    /*** FLUSH_BLOCK(s, 0); ***/
    flush_block_only(s, false);
    if (s.strm.avail_out === 0) {
      return BS_NEED_MORE;
    }
    /***/
  }
  return BS_BLOCK_DONE;
}

/* ===========================================================================
 * For Z_HUFFMAN_ONLY, do not look for matches.  Do not maintain a hash table.
 * (It will be regenerated if this run of deflate switches away from Huffman.)
 */
function deflate_huff(s, flush) {
  var bflush;             /* set if current block must be flushed */

  for (;;) {
    /* Make sure that we have a literal to write. */
    if (s.lookahead === 0) {
      fill_window(s);
      if (s.lookahead === 0) {
        if (flush === Z_NO_FLUSH) {
          return BS_NEED_MORE;
        }
        break;      /* flush the current block */
      }
    }

    /* Output a literal byte */
    s.match_length = 0;
    //Tracevv((stderr,"%c", s->window[s->strstart]));
    /*** _tr_tally_lit(s, s.window[s.strstart], bflush); ***/
    bflush = trees._tr_tally(s, 0, s.window[s.strstart]);
    s.lookahead--;
    s.strstart++;
    if (bflush) {
      /*** FLUSH_BLOCK(s, 0); ***/
      flush_block_only(s, false);
      if (s.strm.avail_out === 0) {
        return BS_NEED_MORE;
      }
      /***/
    }
  }
  s.insert = 0;
  if (flush === Z_FINISH) {
    /*** FLUSH_BLOCK(s, 1); ***/
    flush_block_only(s, true);
    if (s.strm.avail_out === 0) {
      return BS_FINISH_STARTED;
    }
    /***/
    return BS_FINISH_DONE;
  }
  if (s.last_lit) {
    /*** FLUSH_BLOCK(s, 0); ***/
    flush_block_only(s, false);
    if (s.strm.avail_out === 0) {
      return BS_NEED_MORE;
    }
    /***/
  }
  return BS_BLOCK_DONE;
}

/* Values for max_lazy_match, good_match and max_chain_length, depending on
 * the desired pack level (0..9). The values given below have been tuned to
 * exclude worst case performance for pathological files. Better values may be
 * found for specific files.
 */
function Config(good_length, max_lazy, nice_length, max_chain, func) {
  this.good_length = good_length;
  this.max_lazy = max_lazy;
  this.nice_length = nice_length;
  this.max_chain = max_chain;
  this.func = func;
}

var configuration_table;

configuration_table = [
  /*      good lazy nice chain */
  new Config(0, 0, 0, 0, deflate_stored),          /* 0 store only */
  new Config(4, 4, 8, 4, deflate_fast),            /* 1 max speed, no lazy matches */
  new Config(4, 5, 16, 8, deflate_fast),           /* 2 */
  new Config(4, 6, 32, 32, deflate_fast),          /* 3 */

  new Config(4, 4, 16, 16, deflate_slow),          /* 4 lazy matches */
  new Config(8, 16, 32, 32, deflate_slow),         /* 5 */
  new Config(8, 16, 128, 128, deflate_slow),       /* 6 */
  new Config(8, 32, 128, 256, deflate_slow),       /* 7 */
  new Config(32, 128, 258, 1024, deflate_slow),    /* 8 */
  new Config(32, 258, 258, 4096, deflate_slow)     /* 9 max compression */
];


/* ===========================================================================
 * Initialize the "longest match" routines for a new zlib stream
 */
function lm_init(s) {
  s.window_size = 2 * s.w_size;

  /*** CLEAR_HASH(s); ***/
  zero$1(s.head); // Fill with NIL (= 0);

  /* Set the default configuration parameters:
   */
  s.max_lazy_match = configuration_table[s.level].max_lazy;
  s.good_match = configuration_table[s.level].good_length;
  s.nice_match = configuration_table[s.level].nice_length;
  s.max_chain_length = configuration_table[s.level].max_chain;

  s.strstart = 0;
  s.block_start = 0;
  s.lookahead = 0;
  s.insert = 0;
  s.match_length = s.prev_length = MIN_MATCH$1 - 1;
  s.match_available = 0;
  s.ins_h = 0;
}


function DeflateState() {
  this.strm = null;            /* pointer back to this zlib stream */
  this.status = 0;            /* as the name implies */
  this.pending_buf = null;      /* output still pending */
  this.pending_buf_size = 0;  /* size of pending_buf */
  this.pending_out = 0;       /* next pending byte to output to the stream */
  this.pending = 0;           /* nb of bytes in the pending buffer */
  this.wrap = 0;              /* bit 0 true for zlib, bit 1 true for gzip */
  this.gzhead = null;         /* gzip header information to write */
  this.gzindex = 0;           /* where in extra, name, or comment */
  this.method = Z_DEFLATED; /* can only be DEFLATED */
  this.last_flush = -1;   /* value of flush param for previous deflate call */

  this.w_size = 0;  /* LZ77 window size (32K by default) */
  this.w_bits = 0;  /* log2(w_size)  (8..16) */
  this.w_mask = 0;  /* w_size - 1 */

  this.window = null;
  /* Sliding window. Input bytes are read into the second half of the window,
   * and move to the first half later to keep a dictionary of at least wSize
   * bytes. With this organization, matches are limited to a distance of
   * wSize-MAX_MATCH bytes, but this ensures that IO is always
   * performed with a length multiple of the block size.
   */

  this.window_size = 0;
  /* Actual size of window: 2*wSize, except when the user input buffer
   * is directly used as sliding window.
   */

  this.prev = null;
  /* Link to older string with same hash index. To limit the size of this
   * array to 64K, this link is maintained only for the last 32K strings.
   * An index in this array is thus a window index modulo 32K.
   */

  this.head = null;   /* Heads of the hash chains or NIL. */

  this.ins_h = 0;       /* hash index of string to be inserted */
  this.hash_size = 0;   /* number of elements in hash table */
  this.hash_bits = 0;   /* log2(hash_size) */
  this.hash_mask = 0;   /* hash_size-1 */

  this.hash_shift = 0;
  /* Number of bits by which ins_h must be shifted at each input
   * step. It must be such that after MIN_MATCH steps, the oldest
   * byte no longer takes part in the hash key, that is:
   *   hash_shift * MIN_MATCH >= hash_bits
   */

  this.block_start = 0;
  /* Window position at the beginning of the current output block. Gets
   * negative when the window is moved backwards.
   */

  this.match_length = 0;      /* length of best match */
  this.prev_match = 0;        /* previous match */
  this.match_available = 0;   /* set if previous match exists */
  this.strstart = 0;          /* start of string to insert */
  this.match_start = 0;       /* start of matching string */
  this.lookahead = 0;         /* number of valid bytes ahead in window */

  this.prev_length = 0;
  /* Length of the best match at previous step. Matches not greater than this
   * are discarded. This is used in the lazy match evaluation.
   */

  this.max_chain_length = 0;
  /* To speed up deflation, hash chains are never searched beyond this
   * length.  A higher limit improves compression ratio but degrades the
   * speed.
   */

  this.max_lazy_match = 0;
  /* Attempt to find a better match only when the current match is strictly
   * smaller than this value. This mechanism is used only for compression
   * levels >= 4.
   */
  // That's alias to max_lazy_match, don't use directly
  //this.max_insert_length = 0;
  /* Insert new strings in the hash table only if the match length is not
   * greater than this length. This saves time but degrades compression.
   * max_insert_length is used only for compression levels <= 3.
   */

  this.level = 0;     /* compression level (1..9) */
  this.strategy = 0;  /* favor or force Huffman coding*/

  this.good_match = 0;
  /* Use a faster search when the previous match is longer than this */

  this.nice_match = 0; /* Stop searching when current match exceeds this */

              /* used by trees.c: */

  /* Didn't use ct_data typedef below to suppress compiler warning */

  // struct ct_data_s dyn_ltree[HEAP_SIZE];   /* literal and length tree */
  // struct ct_data_s dyn_dtree[2*D_CODES+1]; /* distance tree */
  // struct ct_data_s bl_tree[2*BL_CODES+1];  /* Huffman tree for bit lengths */

  // Use flat array of DOUBLE size, with interleaved fata,
  // because JS does not support effective
  this.dyn_ltree  = new common$e.Buf16(HEAP_SIZE$1 * 2);
  this.dyn_dtree  = new common$e.Buf16((2 * D_CODES$1 + 1) * 2);
  this.bl_tree    = new common$e.Buf16((2 * BL_CODES$1 + 1) * 2);
  zero$1(this.dyn_ltree);
  zero$1(this.dyn_dtree);
  zero$1(this.bl_tree);

  this.l_desc   = null;         /* desc. for literal tree */
  this.d_desc   = null;         /* desc. for distance tree */
  this.bl_desc  = null;         /* desc. for bit length tree */

  //ush bl_count[MAX_BITS+1];
  this.bl_count = new common$e.Buf16(MAX_BITS$1 + 1);
  /* number of codes at each bit length for an optimal tree */

  //int heap[2*L_CODES+1];      /* heap used to build the Huffman trees */
  this.heap = new common$e.Buf16(2 * L_CODES$1 + 1);  /* heap used to build the Huffman trees */
  zero$1(this.heap);

  this.heap_len = 0;               /* number of elements in the heap */
  this.heap_max = 0;               /* element of largest frequency */
  /* The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used.
   * The same heap array is used to build all trees.
   */

  this.depth = new common$e.Buf16(2 * L_CODES$1 + 1); //uch depth[2*L_CODES+1];
  zero$1(this.depth);
  /* Depth of each subtree used as tie breaker for trees of equal frequency
   */

  this.l_buf = 0;          /* buffer index for literals or lengths */

  this.lit_bufsize = 0;
  /* Size of match buffer for literals/lengths.  There are 4 reasons for
   * limiting lit_bufsize to 64K:
   *   - frequencies can be kept in 16 bit counters
   *   - if compression is not successful for the first block, all input
   *     data is still in the window so we can still emit a stored block even
   *     when input comes from standard input.  (This can also be done for
   *     all blocks if lit_bufsize is not greater than 32K.)
   *   - if compression is not successful for a file smaller than 64K, we can
   *     even emit a stored file instead of a stored block (saving 5 bytes).
   *     This is applicable only for zip (not gzip or zlib).
   *   - creating new Huffman trees less frequently may not provide fast
   *     adaptation to changes in the input data statistics. (Take for
   *     example a binary file with poorly compressible code followed by
   *     a highly compressible string table.) Smaller buffer sizes give
   *     fast adaptation but have of course the overhead of transmitting
   *     trees more frequently.
   *   - I can't count above 4
   */

  this.last_lit = 0;      /* running index in l_buf */

  this.d_buf = 0;
  /* Buffer index for distances. To simplify the code, d_buf and l_buf have
   * the same number of elements. To use different lengths, an extra flag
   * array would be necessary.
   */

  this.opt_len = 0;       /* bit length of current block with optimal trees */
  this.static_len = 0;    /* bit length of current block with static trees */
  this.matches = 0;       /* number of string matches in current block */
  this.insert = 0;        /* bytes at end of window left to insert */


  this.bi_buf = 0;
  /* Output buffer. bits are inserted starting at the bottom (least
   * significant bits).
   */
  this.bi_valid = 0;
  /* Number of valid bits in bi_buf.  All bits above the last valid bit
   * are always zero.
   */

  // Used for window memory init. We safely ignore it for JS. That makes
  // sense only for pointers and memory check tools.
  //this.high_water = 0;
  /* High water mark offset in window for initialized bytes -- bytes above
   * this are set to zero in order to avoid memory check warnings when
   * longest match routines access bytes past the input.  This is then
   * updated to the new high water mark.
   */
}


function deflateResetKeep(strm) {
  var s;

  if (!strm || !strm.state) {
    return err(strm, Z_STREAM_ERROR);
  }

  strm.total_in = strm.total_out = 0;
  strm.data_type = Z_UNKNOWN$1;

  s = strm.state;
  s.pending = 0;
  s.pending_out = 0;

  if (s.wrap < 0) {
    s.wrap = -s.wrap;
    /* was made negative by deflate(..., Z_FINISH); */
  }
  s.status = (s.wrap ? INIT_STATE : BUSY_STATE);
  strm.adler = (s.wrap === 2) ?
    0  // crc32(0, Z_NULL, 0)
  :
    1; // adler32(0, Z_NULL, 0)
  s.last_flush = Z_NO_FLUSH;
  trees._tr_init(s);
  return Z_OK;
}


function deflateReset(strm) {
  var ret = deflateResetKeep(strm);
  if (ret === Z_OK) {
    lm_init(strm.state);
  }
  return ret;
}


function deflateSetHeader(strm, head) {
  if (!strm || !strm.state) { return Z_STREAM_ERROR; }
  if (strm.state.wrap !== 2) { return Z_STREAM_ERROR; }
  strm.state.gzhead = head;
  return Z_OK;
}


function deflateInit2(strm, level, method, windowBits, memLevel, strategy) {
  if (!strm) { // === Z_NULL
    return Z_STREAM_ERROR;
  }
  var wrap = 1;

  if (level === Z_DEFAULT_COMPRESSION) {
    level = 6;
  }

  if (windowBits < 0) { /* suppress zlib wrapper */
    wrap = 0;
    windowBits = -windowBits;
  }

  else if (windowBits > 15) {
    wrap = 2;           /* write gzip wrapper instead */
    windowBits -= 16;
  }


  if (memLevel < 1 || memLevel > MAX_MEM_LEVEL || method !== Z_DEFLATED ||
    windowBits < 8 || windowBits > 15 || level < 0 || level > 9 ||
    strategy < 0 || strategy > Z_FIXED$1) {
    return err(strm, Z_STREAM_ERROR);
  }


  if (windowBits === 8) {
    windowBits = 9;
  }
  /* until 256-byte window bug fixed */

  var s = new DeflateState();

  strm.state = s;
  s.strm = strm;

  s.wrap = wrap;
  s.gzhead = null;
  s.w_bits = windowBits;
  s.w_size = 1 << s.w_bits;
  s.w_mask = s.w_size - 1;

  s.hash_bits = memLevel + 7;
  s.hash_size = 1 << s.hash_bits;
  s.hash_mask = s.hash_size - 1;
  s.hash_shift = ~~((s.hash_bits + MIN_MATCH$1 - 1) / MIN_MATCH$1);

  s.window = new common$e.Buf8(s.w_size * 2);
  s.head = new common$e.Buf16(s.hash_size);
  s.prev = new common$e.Buf16(s.w_size);

  // Don't need mem init magic for JS.
  //s.high_water = 0;  /* nothing written to s->window yet */

  s.lit_bufsize = 1 << (memLevel + 6); /* 16K elements by default */

  s.pending_buf_size = s.lit_bufsize * 4;

  //overlay = (ushf *) ZALLOC(strm, s->lit_bufsize, sizeof(ush)+2);
  //s->pending_buf = (uchf *) overlay;
  s.pending_buf = new common$e.Buf8(s.pending_buf_size);

  // It is offset from `s.pending_buf` (size is `s.lit_bufsize * 2`)
  //s->d_buf = overlay + s->lit_bufsize/sizeof(ush);
  s.d_buf = 1 * s.lit_bufsize;

  //s->l_buf = s->pending_buf + (1+sizeof(ush))*s->lit_bufsize;
  s.l_buf = (1 + 2) * s.lit_bufsize;

  s.level = level;
  s.strategy = strategy;
  s.method = method;

  return deflateReset(strm);
}

function deflateInit(strm, level) {
  return deflateInit2(strm, level, Z_DEFLATED, MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY);
}


function deflate(strm, flush) {
  var old_flush, s;
  var beg, val; // for gzip header write only

  if (!strm || !strm.state ||
    flush > Z_BLOCK || flush < 0) {
    return strm ? err(strm, Z_STREAM_ERROR) : Z_STREAM_ERROR;
  }

  s = strm.state;

  if (!strm.output ||
      (!strm.input && strm.avail_in !== 0) ||
      (s.status === FINISH_STATE && flush !== Z_FINISH)) {
    return err(strm, (strm.avail_out === 0) ? Z_BUF_ERROR : Z_STREAM_ERROR);
  }

  s.strm = strm; /* just in case */
  old_flush = s.last_flush;
  s.last_flush = flush;

  /* Write the header */
  if (s.status === INIT_STATE) {

    if (s.wrap === 2) { // GZIP header
      strm.adler = 0;  //crc32(0L, Z_NULL, 0);
      put_byte(s, 31);
      put_byte(s, 139);
      put_byte(s, 8);
      if (!s.gzhead) { // s->gzhead == Z_NULL
        put_byte(s, 0);
        put_byte(s, 0);
        put_byte(s, 0);
        put_byte(s, 0);
        put_byte(s, 0);
        put_byte(s, s.level === 9 ? 2 :
                    (s.strategy >= Z_HUFFMAN_ONLY || s.level < 2 ?
                     4 : 0));
        put_byte(s, OS_CODE);
        s.status = BUSY_STATE;
      }
      else {
        put_byte(s, (s.gzhead.text ? 1 : 0) +
                    (s.gzhead.hcrc ? 2 : 0) +
                    (!s.gzhead.extra ? 0 : 4) +
                    (!s.gzhead.name ? 0 : 8) +
                    (!s.gzhead.comment ? 0 : 16)
        );
        put_byte(s, s.gzhead.time & 0xff);
        put_byte(s, (s.gzhead.time >> 8) & 0xff);
        put_byte(s, (s.gzhead.time >> 16) & 0xff);
        put_byte(s, (s.gzhead.time >> 24) & 0xff);
        put_byte(s, s.level === 9 ? 2 :
                    (s.strategy >= Z_HUFFMAN_ONLY || s.level < 2 ?
                     4 : 0));
        put_byte(s, s.gzhead.os & 0xff);
        if (s.gzhead.extra && s.gzhead.extra.length) {
          put_byte(s, s.gzhead.extra.length & 0xff);
          put_byte(s, (s.gzhead.extra.length >> 8) & 0xff);
        }
        if (s.gzhead.hcrc) {
          strm.adler = crc32_1(strm.adler, s.pending_buf, s.pending, 0);
        }
        s.gzindex = 0;
        s.status = EXTRA_STATE;
      }
    }
    else // DEFLATE header
    {
      var header = (Z_DEFLATED + ((s.w_bits - 8) << 4)) << 8;
      var level_flags = -1;

      if (s.strategy >= Z_HUFFMAN_ONLY || s.level < 2) {
        level_flags = 0;
      } else if (s.level < 6) {
        level_flags = 1;
      } else if (s.level === 6) {
        level_flags = 2;
      } else {
        level_flags = 3;
      }
      header |= (level_flags << 6);
      if (s.strstart !== 0) { header |= PRESET_DICT; }
      header += 31 - (header % 31);

      s.status = BUSY_STATE;
      putShortMSB(s, header);

      /* Save the adler32 of the preset dictionary: */
      if (s.strstart !== 0) {
        putShortMSB(s, strm.adler >>> 16);
        putShortMSB(s, strm.adler & 0xffff);
      }
      strm.adler = 1; // adler32(0L, Z_NULL, 0);
    }
  }

//#ifdef GZIP
  if (s.status === EXTRA_STATE) {
    if (s.gzhead.extra/* != Z_NULL*/) {
      beg = s.pending;  /* start of bytes to update crc */

      while (s.gzindex < (s.gzhead.extra.length & 0xffff)) {
        if (s.pending === s.pending_buf_size) {
          if (s.gzhead.hcrc && s.pending > beg) {
            strm.adler = crc32_1(strm.adler, s.pending_buf, s.pending - beg, beg);
          }
          flush_pending(strm);
          beg = s.pending;
          if (s.pending === s.pending_buf_size) {
            break;
          }
        }
        put_byte(s, s.gzhead.extra[s.gzindex] & 0xff);
        s.gzindex++;
      }
      if (s.gzhead.hcrc && s.pending > beg) {
        strm.adler = crc32_1(strm.adler, s.pending_buf, s.pending - beg, beg);
      }
      if (s.gzindex === s.gzhead.extra.length) {
        s.gzindex = 0;
        s.status = NAME_STATE;
      }
    }
    else {
      s.status = NAME_STATE;
    }
  }
  if (s.status === NAME_STATE) {
    if (s.gzhead.name/* != Z_NULL*/) {
      beg = s.pending;  /* start of bytes to update crc */
      //int val;

      do {
        if (s.pending === s.pending_buf_size) {
          if (s.gzhead.hcrc && s.pending > beg) {
            strm.adler = crc32_1(strm.adler, s.pending_buf, s.pending - beg, beg);
          }
          flush_pending(strm);
          beg = s.pending;
          if (s.pending === s.pending_buf_size) {
            val = 1;
            break;
          }
        }
        // JS specific: little magic to add zero terminator to end of string
        if (s.gzindex < s.gzhead.name.length) {
          val = s.gzhead.name.charCodeAt(s.gzindex++) & 0xff;
        } else {
          val = 0;
        }
        put_byte(s, val);
      } while (val !== 0);

      if (s.gzhead.hcrc && s.pending > beg) {
        strm.adler = crc32_1(strm.adler, s.pending_buf, s.pending - beg, beg);
      }
      if (val === 0) {
        s.gzindex = 0;
        s.status = COMMENT_STATE;
      }
    }
    else {
      s.status = COMMENT_STATE;
    }
  }
  if (s.status === COMMENT_STATE) {
    if (s.gzhead.comment/* != Z_NULL*/) {
      beg = s.pending;  /* start of bytes to update crc */
      //int val;

      do {
        if (s.pending === s.pending_buf_size) {
          if (s.gzhead.hcrc && s.pending > beg) {
            strm.adler = crc32_1(strm.adler, s.pending_buf, s.pending - beg, beg);
          }
          flush_pending(strm);
          beg = s.pending;
          if (s.pending === s.pending_buf_size) {
            val = 1;
            break;
          }
        }
        // JS specific: little magic to add zero terminator to end of string
        if (s.gzindex < s.gzhead.comment.length) {
          val = s.gzhead.comment.charCodeAt(s.gzindex++) & 0xff;
        } else {
          val = 0;
        }
        put_byte(s, val);
      } while (val !== 0);

      if (s.gzhead.hcrc && s.pending > beg) {
        strm.adler = crc32_1(strm.adler, s.pending_buf, s.pending - beg, beg);
      }
      if (val === 0) {
        s.status = HCRC_STATE;
      }
    }
    else {
      s.status = HCRC_STATE;
    }
  }
  if (s.status === HCRC_STATE) {
    if (s.gzhead.hcrc) {
      if (s.pending + 2 > s.pending_buf_size) {
        flush_pending(strm);
      }
      if (s.pending + 2 <= s.pending_buf_size) {
        put_byte(s, strm.adler & 0xff);
        put_byte(s, (strm.adler >> 8) & 0xff);
        strm.adler = 0; //crc32(0L, Z_NULL, 0);
        s.status = BUSY_STATE;
      }
    }
    else {
      s.status = BUSY_STATE;
    }
  }
//#endif

  /* Flush as much pending output as possible */
  if (s.pending !== 0) {
    flush_pending(strm);
    if (strm.avail_out === 0) {
      /* Since avail_out is 0, deflate will be called again with
       * more output space, but possibly with both pending and
       * avail_in equal to zero. There won't be anything to do,
       * but this is not an error situation so make sure we
       * return OK instead of BUF_ERROR at next call of deflate:
       */
      s.last_flush = -1;
      return Z_OK;
    }

    /* Make sure there is something to do and avoid duplicate consecutive
     * flushes. For repeated and useless calls with Z_FINISH, we keep
     * returning Z_STREAM_END instead of Z_BUF_ERROR.
     */
  } else if (strm.avail_in === 0 && rank(flush) <= rank(old_flush) &&
    flush !== Z_FINISH) {
    return err(strm, Z_BUF_ERROR);
  }

  /* User must not provide more input after the first FINISH: */
  if (s.status === FINISH_STATE && strm.avail_in !== 0) {
    return err(strm, Z_BUF_ERROR);
  }

  /* Start a new block or continue the current one.
   */
  if (strm.avail_in !== 0 || s.lookahead !== 0 ||
    (flush !== Z_NO_FLUSH && s.status !== FINISH_STATE)) {
    var bstate = (s.strategy === Z_HUFFMAN_ONLY) ? deflate_huff(s, flush) :
      (s.strategy === Z_RLE ? deflate_rle(s, flush) :
        configuration_table[s.level].func(s, flush));

    if (bstate === BS_FINISH_STARTED || bstate === BS_FINISH_DONE) {
      s.status = FINISH_STATE;
    }
    if (bstate === BS_NEED_MORE || bstate === BS_FINISH_STARTED) {
      if (strm.avail_out === 0) {
        s.last_flush = -1;
        /* avoid BUF_ERROR next call, see above */
      }
      return Z_OK;
      /* If flush != Z_NO_FLUSH && avail_out == 0, the next call
       * of deflate should use the same flush parameter to make sure
       * that the flush is complete. So we don't have to output an
       * empty block here, this will be done at next call. This also
       * ensures that for a very small output buffer, we emit at most
       * one empty block.
       */
    }
    if (bstate === BS_BLOCK_DONE) {
      if (flush === Z_PARTIAL_FLUSH) {
        trees._tr_align(s);
      }
      else if (flush !== Z_BLOCK) { /* FULL_FLUSH or SYNC_FLUSH */

        trees._tr_stored_block(s, 0, 0, false);
        /* For a full flush, this empty block will be recognized
         * as a special marker by inflate_sync().
         */
        if (flush === Z_FULL_FLUSH) {
          /*** CLEAR_HASH(s); ***/             /* forget history */
          zero$1(s.head); // Fill with NIL (= 0);

          if (s.lookahead === 0) {
            s.strstart = 0;
            s.block_start = 0;
            s.insert = 0;
          }
        }
      }
      flush_pending(strm);
      if (strm.avail_out === 0) {
        s.last_flush = -1; /* avoid BUF_ERROR at next call, see above */
        return Z_OK;
      }
    }
  }
  //Assert(strm->avail_out > 0, "bug2");
  //if (strm.avail_out <= 0) { throw new Error("bug2");}

  if (flush !== Z_FINISH) { return Z_OK; }
  if (s.wrap <= 0) { return Z_STREAM_END; }

  /* Write the trailer */
  if (s.wrap === 2) {
    put_byte(s, strm.adler & 0xff);
    put_byte(s, (strm.adler >> 8) & 0xff);
    put_byte(s, (strm.adler >> 16) & 0xff);
    put_byte(s, (strm.adler >> 24) & 0xff);
    put_byte(s, strm.total_in & 0xff);
    put_byte(s, (strm.total_in >> 8) & 0xff);
    put_byte(s, (strm.total_in >> 16) & 0xff);
    put_byte(s, (strm.total_in >> 24) & 0xff);
  }
  else
  {
    putShortMSB(s, strm.adler >>> 16);
    putShortMSB(s, strm.adler & 0xffff);
  }

  flush_pending(strm);
  /* If avail_out is zero, the application will call deflate again
   * to flush the rest.
   */
  if (s.wrap > 0) { s.wrap = -s.wrap; }
  /* write the trailer only once! */
  return s.pending !== 0 ? Z_OK : Z_STREAM_END;
}

function deflateEnd(strm) {
  var status;

  if (!strm/*== Z_NULL*/ || !strm.state/*== Z_NULL*/) {
    return Z_STREAM_ERROR;
  }

  status = strm.state.status;
  if (status !== INIT_STATE &&
    status !== EXTRA_STATE &&
    status !== NAME_STATE &&
    status !== COMMENT_STATE &&
    status !== HCRC_STATE &&
    status !== BUSY_STATE &&
    status !== FINISH_STATE
  ) {
    return err(strm, Z_STREAM_ERROR);
  }

  strm.state = null;

  return status === BUSY_STATE ? err(strm, Z_DATA_ERROR) : Z_OK;
}


/* =========================================================================
 * Initializes the compression dictionary from the given byte
 * sequence without producing any compressed output.
 */
function deflateSetDictionary(strm, dictionary) {
  var dictLength = dictionary.length;

  var s;
  var str, n;
  var wrap;
  var avail;
  var next;
  var input;
  var tmpDict;

  if (!strm/*== Z_NULL*/ || !strm.state/*== Z_NULL*/) {
    return Z_STREAM_ERROR;
  }

  s = strm.state;
  wrap = s.wrap;

  if (wrap === 2 || (wrap === 1 && s.status !== INIT_STATE) || s.lookahead) {
    return Z_STREAM_ERROR;
  }

  /* when using zlib wrappers, compute Adler-32 for provided dictionary */
  if (wrap === 1) {
    /* adler32(strm->adler, dictionary, dictLength); */
    strm.adler = adler32_1(strm.adler, dictionary, dictLength, 0);
  }

  s.wrap = 0;   /* avoid computing Adler-32 in read_buf */

  /* if dictionary would fill window, just replace the history */
  if (dictLength >= s.w_size) {
    if (wrap === 0) {            /* already empty otherwise */
      /*** CLEAR_HASH(s); ***/
      zero$1(s.head); // Fill with NIL (= 0);
      s.strstart = 0;
      s.block_start = 0;
      s.insert = 0;
    }
    /* use the tail */
    // dictionary = dictionary.slice(dictLength - s.w_size);
    tmpDict = new common$e.Buf8(s.w_size);
    common$e.arraySet(tmpDict, dictionary, dictLength - s.w_size, s.w_size, 0);
    dictionary = tmpDict;
    dictLength = s.w_size;
  }
  /* insert dictionary into window and hash */
  avail = strm.avail_in;
  next = strm.next_in;
  input = strm.input;
  strm.avail_in = dictLength;
  strm.next_in = 0;
  strm.input = dictionary;
  fill_window(s);
  while (s.lookahead >= MIN_MATCH$1) {
    str = s.strstart;
    n = s.lookahead - (MIN_MATCH$1 - 1);
    do {
      /* UPDATE_HASH(s, s->ins_h, s->window[str + MIN_MATCH-1]); */
      s.ins_h = ((s.ins_h << s.hash_shift) ^ s.window[str + MIN_MATCH$1 - 1]) & s.hash_mask;

      s.prev[str & s.w_mask] = s.head[s.ins_h];

      s.head[s.ins_h] = str;
      str++;
    } while (--n);
    s.strstart = str;
    s.lookahead = MIN_MATCH$1 - 1;
    fill_window(s);
  }
  s.strstart += s.lookahead;
  s.block_start = s.strstart;
  s.insert = s.lookahead;
  s.lookahead = 0;
  s.match_length = s.prev_length = MIN_MATCH$1 - 1;
  s.match_available = 0;
  strm.next_in = next;
  strm.input = input;
  strm.avail_in = avail;
  s.wrap = wrap;
  return Z_OK;
}


var deflateInit_1 = deflateInit;
var deflateInit2_1 = deflateInit2;
var deflateReset_1 = deflateReset;
var deflateResetKeep_1 = deflateResetKeep;
var deflateSetHeader_1 = deflateSetHeader;
var deflate_2 = deflate;
var deflateEnd_1 = deflateEnd;
var deflateSetDictionary_1 = deflateSetDictionary;
var deflateInfo = 'pako deflate (from Nodeca project)';

/* Not implemented
exports.deflateBound = deflateBound;
exports.deflateCopy = deflateCopy;
exports.deflateParams = deflateParams;
exports.deflatePending = deflatePending;
exports.deflatePrime = deflatePrime;
exports.deflateTune = deflateTune;
*/

var deflate_1 = {
	deflateInit: deflateInit_1,
	deflateInit2: deflateInit2_1,
	deflateReset: deflateReset_1,
	deflateResetKeep: deflateResetKeep_1,
	deflateSetHeader: deflateSetHeader_1,
	deflate: deflate_2,
	deflateEnd: deflateEnd_1,
	deflateSetDictionary: deflateSetDictionary_1,
	deflateInfo: deflateInfo
};

// Quick check if we can use fast array to bin string conversion
//
// - apply(Array) can fail on Android 2.2
// - apply(Uint8Array) can fail on iOS 5.1 Safari
//
var STR_APPLY_OK = true;
var STR_APPLY_UIA_OK = true;

try { String.fromCharCode.apply(null, [ 0 ]); } catch (__) { STR_APPLY_OK = false; }
try { String.fromCharCode.apply(null, new Uint8Array(1)); } catch (__) { STR_APPLY_UIA_OK = false; }


// Table with utf8 lengths (calculated by first byte of sequence)
// Note, that 5 & 6-byte values and some 4-byte values can not be represented in JS,
// because max possible codepoint is 0x10ffff
var _utf8len = new common$e.Buf8(256);
for (var q = 0; q < 256; q++) {
  _utf8len[q] = (q >= 252 ? 6 : q >= 248 ? 5 : q >= 240 ? 4 : q >= 224 ? 3 : q >= 192 ? 2 : 1);
}
_utf8len[254] = _utf8len[254] = 1; // Invalid sequence start


// convert string to array (typed, when possible)
var string2buf = function (str) {
  var buf, c, c2, m_pos, i, str_len = str.length, buf_len = 0;

  // count binary size
  for (m_pos = 0; m_pos < str_len; m_pos++) {
    c = str.charCodeAt(m_pos);
    if ((c & 0xfc00) === 0xd800 && (m_pos + 1 < str_len)) {
      c2 = str.charCodeAt(m_pos + 1);
      if ((c2 & 0xfc00) === 0xdc00) {
        c = 0x10000 + ((c - 0xd800) << 10) + (c2 - 0xdc00);
        m_pos++;
      }
    }
    buf_len += c < 0x80 ? 1 : c < 0x800 ? 2 : c < 0x10000 ? 3 : 4;
  }

  // allocate buffer
  buf = new common$e.Buf8(buf_len);

  // convert
  for (i = 0, m_pos = 0; i < buf_len; m_pos++) {
    c = str.charCodeAt(m_pos);
    if ((c & 0xfc00) === 0xd800 && (m_pos + 1 < str_len)) {
      c2 = str.charCodeAt(m_pos + 1);
      if ((c2 & 0xfc00) === 0xdc00) {
        c = 0x10000 + ((c - 0xd800) << 10) + (c2 - 0xdc00);
        m_pos++;
      }
    }
    if (c < 0x80) {
      /* one byte */
      buf[i++] = c;
    } else if (c < 0x800) {
      /* two bytes */
      buf[i++] = 0xC0 | (c >>> 6);
      buf[i++] = 0x80 | (c & 0x3f);
    } else if (c < 0x10000) {
      /* three bytes */
      buf[i++] = 0xE0 | (c >>> 12);
      buf[i++] = 0x80 | (c >>> 6 & 0x3f);
      buf[i++] = 0x80 | (c & 0x3f);
    } else {
      /* four bytes */
      buf[i++] = 0xf0 | (c >>> 18);
      buf[i++] = 0x80 | (c >>> 12 & 0x3f);
      buf[i++] = 0x80 | (c >>> 6 & 0x3f);
      buf[i++] = 0x80 | (c & 0x3f);
    }
  }

  return buf;
};

// Helper (used in 2 places)
function buf2binstring(buf, len) {
  // On Chrome, the arguments in a function call that are allowed is `65534`.
  // If the length of the buffer is smaller than that, we can use this optimization,
  // otherwise we will take a slower path.
  if (len < 65534) {
    if ((buf.subarray && STR_APPLY_UIA_OK) || (!buf.subarray && STR_APPLY_OK)) {
      return String.fromCharCode.apply(null, common$e.shrinkBuf(buf, len));
    }
  }

  var result = '';
  for (var i = 0; i < len; i++) {
    result += String.fromCharCode(buf[i]);
  }
  return result;
}


// Convert byte array to binary string
var buf2binstring_1 = function (buf) {
  return buf2binstring(buf, buf.length);
};


// Convert binary string (typed, when possible)
var binstring2buf = function (str) {
  var buf = new common$e.Buf8(str.length);
  for (var i = 0, len = buf.length; i < len; i++) {
    buf[i] = str.charCodeAt(i);
  }
  return buf;
};


// convert array to string
var buf2string = function (buf, max) {
  var i, out, c, c_len;
  var len = max || buf.length;

  // Reserve max possible length (2 words per char)
  // NB: by unknown reasons, Array is significantly faster for
  //     String.fromCharCode.apply than Uint16Array.
  var utf16buf = new Array(len * 2);

  for (out = 0, i = 0; i < len;) {
    c = buf[i++];
    // quick process ascii
    if (c < 0x80) { utf16buf[out++] = c; continue; }

    c_len = _utf8len[c];
    // skip 5 & 6 byte codes
    if (c_len > 4) { utf16buf[out++] = 0xfffd; i += c_len - 1; continue; }

    // apply mask on first byte
    c &= c_len === 2 ? 0x1f : c_len === 3 ? 0x0f : 0x07;
    // join the rest
    while (c_len > 1 && i < len) {
      c = (c << 6) | (buf[i++] & 0x3f);
      c_len--;
    }

    // terminated by end of string?
    if (c_len > 1) { utf16buf[out++] = 0xfffd; continue; }

    if (c < 0x10000) {
      utf16buf[out++] = c;
    } else {
      c -= 0x10000;
      utf16buf[out++] = 0xd800 | ((c >> 10) & 0x3ff);
      utf16buf[out++] = 0xdc00 | (c & 0x3ff);
    }
  }

  return buf2binstring(utf16buf, out);
};


// Calculate max possible position in utf8 buffer,
// that will not break sequence. If that's not possible
// - (very small limits) return max size as is.
//
// buf[] - utf8 bytes array
// max   - length limit (mandatory);
var utf8border = function (buf, max) {
  var pos;

  max = max || buf.length;
  if (max > buf.length) { max = buf.length; }

  // go back from last position, until start of sequence found
  pos = max - 1;
  while (pos >= 0 && (buf[pos] & 0xC0) === 0x80) { pos--; }

  // Very small and broken sequence,
  // return max, because we should return something anyway.
  if (pos < 0) { return max; }

  // If we came to start of buffer - that means buffer is too small,
  // return max too.
  if (pos === 0) { return max; }

  return (pos + _utf8len[buf[pos]] > max) ? pos : max;
};

var strings = {
	string2buf: string2buf,
	buf2binstring: buf2binstring_1,
	binstring2buf: binstring2buf,
	buf2string: buf2string,
	utf8border: utf8border
};

// (C) 1995-2013 Jean-loup Gailly and Mark Adler
// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented; you must not
//   claim that you wrote the original software. If you use this software
//   in a product, an acknowledgment in the product documentation would be
//   appreciated but is not required.
// 2. Altered source versions must be plainly marked as such, and must not be
//   misrepresented as being the original software.
// 3. This notice may not be removed or altered from any source distribution.

function ZStream() {
  /* next input byte */
  this.input = null; // JS specific, because we have no pointers
  this.next_in = 0;
  /* number of bytes available at input */
  this.avail_in = 0;
  /* total number of input bytes read so far */
  this.total_in = 0;
  /* next output byte should be put there */
  this.output = null; // JS specific, because we have no pointers
  this.next_out = 0;
  /* remaining free space at output */
  this.avail_out = 0;
  /* total number of bytes output so far */
  this.total_out = 0;
  /* last error message, NULL if no error */
  this.msg = ''/*Z_NULL*/;
  /* not visible by applications */
  this.state = null;
  /* best guess about the data type: binary or text */
  this.data_type = 2/*Z_UNKNOWN*/;
  /* adler32 value of the uncompressed data */
  this.adler = 0;
}

var zstream = ZStream;

var toString = Object.prototype.toString;

/* Public constants ==========================================================*/
/* ===========================================================================*/

var Z_NO_FLUSH$1      = 0;
var Z_FINISH$1        = 4;

var Z_OK$1            = 0;
var Z_STREAM_END$1    = 1;
var Z_SYNC_FLUSH    = 2;

var Z_DEFAULT_COMPRESSION$1 = -1;

var Z_DEFAULT_STRATEGY$1    = 0;

var Z_DEFLATED$1  = 8;

/* ===========================================================================*/


/**
 * class Deflate
 *
 * Generic JS-style wrapper for zlib calls. If you don't need
 * streaming behaviour - use more simple functions: [[deflate]],
 * [[deflateRaw]] and [[gzip]].
 **/

/* internal
 * Deflate.chunks -> Array
 *
 * Chunks of output data, if [[Deflate#onData]] not overridden.
 **/

/**
 * Deflate.result -> Uint8Array|Array
 *
 * Compressed result, generated by default [[Deflate#onData]]
 * and [[Deflate#onEnd]] handlers. Filled after you push last chunk
 * (call [[Deflate#push]] with `Z_FINISH` / `true` param)  or if you
 * push a chunk with explicit flush (call [[Deflate#push]] with
 * `Z_SYNC_FLUSH` param).
 **/

/**
 * Deflate.err -> Number
 *
 * Error code after deflate finished. 0 (Z_OK) on success.
 * You will not need it in real life, because deflate errors
 * are possible only on wrong options or bad `onData` / `onEnd`
 * custom handlers.
 **/

/**
 * Deflate.msg -> String
 *
 * Error message, if [[Deflate.err]] != 0
 **/


/**
 * new Deflate(options)
 * - options (Object): zlib deflate options.
 *
 * Creates new deflator instance with specified params. Throws exception
 * on bad params. Supported options:
 *
 * - `level`
 * - `windowBits`
 * - `memLevel`
 * - `strategy`
 * - `dictionary`
 *
 * [http://zlib.net/manual.html#Advanced](http://zlib.net/manual.html#Advanced)
 * for more information on these.
 *
 * Additional options, for internal needs:
 *
 * - `chunkSize` - size of generated data chunks (16K by default)
 * - `raw` (Boolean) - do raw deflate
 * - `gzip` (Boolean) - create gzip wrapper
 * - `to` (String) - if equal to 'string', then result will be "binary string"
 *    (each char code [0..255])
 * - `header` (Object) - custom header for gzip
 *   - `text` (Boolean) - true if compressed data believed to be text
 *   - `time` (Number) - modification time, unix timestamp
 *   - `os` (Number) - operation system code
 *   - `extra` (Array) - array of bytes with extra data (max 65536)
 *   - `name` (String) - file name (binary string)
 *   - `comment` (String) - comment (binary string)
 *   - `hcrc` (Boolean) - true if header crc should be added
 *
 * ##### Example:
 *
 * ```javascript
 * var pako = require('pako')
 *   , chunk1 = Uint8Array([1,2,3,4,5,6,7,8,9])
 *   , chunk2 = Uint8Array([10,11,12,13,14,15,16,17,18,19]);
 *
 * var deflate = new pako.Deflate({ level: 3});
 *
 * deflate.push(chunk1, false);
 * deflate.push(chunk2, true);  // true -> last chunk
 *
 * if (deflate.err) { throw new Error(deflate.err); }
 *
 * console.log(deflate.result);
 * ```
 **/
function Deflate(options) {
  if (!(this instanceof Deflate)) return new Deflate(options);

  this.options = common$e.assign({
    level: Z_DEFAULT_COMPRESSION$1,
    method: Z_DEFLATED$1,
    chunkSize: 16384,
    windowBits: 15,
    memLevel: 8,
    strategy: Z_DEFAULT_STRATEGY$1,
    to: ''
  }, options || {});

  var opt = this.options;

  if (opt.raw && (opt.windowBits > 0)) {
    opt.windowBits = -opt.windowBits;
  }

  else if (opt.gzip && (opt.windowBits > 0) && (opt.windowBits < 16)) {
    opt.windowBits += 16;
  }

  this.err    = 0;      // error code, if happens (0 = Z_OK)
  this.msg    = '';     // error message
  this.ended  = false;  // used to avoid multiple onEnd() calls
  this.chunks = [];     // chunks of compressed data

  this.strm = new zstream();
  this.strm.avail_out = 0;

  var status = deflate_1.deflateInit2(
    this.strm,
    opt.level,
    opt.method,
    opt.windowBits,
    opt.memLevel,
    opt.strategy
  );

  if (status !== Z_OK$1) {
    throw new Error(messages[status]);
  }

  if (opt.header) {
    deflate_1.deflateSetHeader(this.strm, opt.header);
  }

  if (opt.dictionary) {
    var dict;
    // Convert data if needed
    if (typeof opt.dictionary === 'string') {
      // If we need to compress text, change encoding to utf8.
      dict = strings.string2buf(opt.dictionary);
    } else if (toString.call(opt.dictionary) === '[object ArrayBuffer]') {
      dict = new Uint8Array(opt.dictionary);
    } else {
      dict = opt.dictionary;
    }

    status = deflate_1.deflateSetDictionary(this.strm, dict);

    if (status !== Z_OK$1) {
      throw new Error(messages[status]);
    }

    this._dict_set = true;
  }
}

/**
 * Deflate#push(data[, mode]) -> Boolean
 * - data (Uint8Array|Array|ArrayBuffer|String): input data. Strings will be
 *   converted to utf8 byte sequence.
 * - mode (Number|Boolean): 0..6 for corresponding Z_NO_FLUSH..Z_TREE modes.
 *   See constants. Skipped or `false` means Z_NO_FLUSH, `true` means Z_FINISH.
 *
 * Sends input data to deflate pipe, generating [[Deflate#onData]] calls with
 * new compressed chunks. Returns `true` on success. The last data block must have
 * mode Z_FINISH (or `true`). That will flush internal pending buffers and call
 * [[Deflate#onEnd]]. For interim explicit flushes (without ending the stream) you
 * can use mode Z_SYNC_FLUSH, keeping the compression context.
 *
 * On fail call [[Deflate#onEnd]] with error code and return false.
 *
 * We strongly recommend to use `Uint8Array` on input for best speed (output
 * array format is detected automatically). Also, don't skip last param and always
 * use the same type in your code (boolean or number). That will improve JS speed.
 *
 * For regular `Array`-s make sure all elements are [0..255].
 *
 * ##### Example
 *
 * ```javascript
 * push(chunk, false); // push one of data chunks
 * ...
 * push(chunk, true);  // push last chunk
 * ```
 **/
Deflate.prototype.push = function (data, mode) {
  var strm = this.strm;
  var chunkSize = this.options.chunkSize;
  var status, _mode;

  if (this.ended) { return false; }

  _mode = (mode === ~~mode) ? mode : ((mode === true) ? Z_FINISH$1 : Z_NO_FLUSH$1);

  // Convert data if needed
  if (typeof data === 'string') {
    // If we need to compress text, change encoding to utf8.
    strm.input = strings.string2buf(data);
  } else if (toString.call(data) === '[object ArrayBuffer]') {
    strm.input = new Uint8Array(data);
  } else {
    strm.input = data;
  }

  strm.next_in = 0;
  strm.avail_in = strm.input.length;

  do {
    if (strm.avail_out === 0) {
      strm.output = new common$e.Buf8(chunkSize);
      strm.next_out = 0;
      strm.avail_out = chunkSize;
    }
    status = deflate_1.deflate(strm, _mode);    /* no bad return value */

    if (status !== Z_STREAM_END$1 && status !== Z_OK$1) {
      this.onEnd(status);
      this.ended = true;
      return false;
    }
    if (strm.avail_out === 0 || (strm.avail_in === 0 && (_mode === Z_FINISH$1 || _mode === Z_SYNC_FLUSH))) {
      if (this.options.to === 'string') {
        this.onData(strings.buf2binstring(common$e.shrinkBuf(strm.output, strm.next_out)));
      } else {
        this.onData(common$e.shrinkBuf(strm.output, strm.next_out));
      }
    }
  } while ((strm.avail_in > 0 || strm.avail_out === 0) && status !== Z_STREAM_END$1);

  // Finalize on the last chunk.
  if (_mode === Z_FINISH$1) {
    status = deflate_1.deflateEnd(this.strm);
    this.onEnd(status);
    this.ended = true;
    return status === Z_OK$1;
  }

  // callback interim results if Z_SYNC_FLUSH.
  if (_mode === Z_SYNC_FLUSH) {
    this.onEnd(Z_OK$1);
    strm.avail_out = 0;
    return true;
  }

  return true;
};


/**
 * Deflate#onData(chunk) -> Void
 * - chunk (Uint8Array|Array|String): output data. Type of array depends
 *   on js engine support. When string output requested, each chunk
 *   will be string.
 *
 * By default, stores data blocks in `chunks[]` property and glue
 * those in `onEnd`. Override this handler, if you need another behaviour.
 **/
Deflate.prototype.onData = function (chunk) {
  this.chunks.push(chunk);
};


/**
 * Deflate#onEnd(status) -> Void
 * - status (Number): deflate status. 0 (Z_OK) on success,
 *   other if not.
 *
 * Called once after you tell deflate that the input stream is
 * complete (Z_FINISH) or should be flushed (Z_SYNC_FLUSH)
 * or if an error happened. By default - join collected chunks,
 * free memory and fill `results` / `err` properties.
 **/
Deflate.prototype.onEnd = function (status) {
  // On success - join
  if (status === Z_OK$1) {
    if (this.options.to === 'string') {
      this.result = this.chunks.join('');
    } else {
      this.result = common$e.flattenChunks(this.chunks);
    }
  }
  this.chunks = [];
  this.err = status;
  this.msg = this.strm.msg;
};


/**
 * deflate(data[, options]) -> Uint8Array|Array|String
 * - data (Uint8Array|Array|String): input data to compress.
 * - options (Object): zlib deflate options.
 *
 * Compress `data` with deflate algorithm and `options`.
 *
 * Supported options are:
 *
 * - level
 * - windowBits
 * - memLevel
 * - strategy
 * - dictionary
 *
 * [http://zlib.net/manual.html#Advanced](http://zlib.net/manual.html#Advanced)
 * for more information on these.
 *
 * Sugar (options):
 *
 * - `raw` (Boolean) - say that we work with raw stream, if you don't wish to specify
 *   negative windowBits implicitly.
 * - `to` (String) - if equal to 'string', then result will be "binary string"
 *    (each char code [0..255])
 *
 * ##### Example:
 *
 * ```javascript
 * var pako = require('pako')
 *   , data = Uint8Array([1,2,3,4,5,6,7,8,9]);
 *
 * console.log(pako.deflate(data));
 * ```
 **/
function deflate$1(input, options) {
  var deflator = new Deflate(options);

  deflator.push(input, true);

  // That will never happens, if you don't cheat with options :)
  if (deflator.err) { throw deflator.msg || messages[deflator.err]; }

  return deflator.result;
}


/**
 * deflateRaw(data[, options]) -> Uint8Array|Array|String
 * - data (Uint8Array|Array|String): input data to compress.
 * - options (Object): zlib deflate options.
 *
 * The same as [[deflate]], but creates raw data, without wrapper
 * (header and adler32 crc).
 **/
function deflateRaw(input, options) {
  options = options || {};
  options.raw = true;
  return deflate$1(input, options);
}


/**
 * gzip(data[, options]) -> Uint8Array|Array|String
 * - data (Uint8Array|Array|String): input data to compress.
 * - options (Object): zlib deflate options.
 *
 * The same as [[deflate]], but create gzip wrapper instead of
 * deflate one.
 **/
function gzip(input, options) {
  options = options || {};
  options.gzip = true;
  return deflate$1(input, options);
}


var Deflate_1 = Deflate;
var deflate_2$1 = deflate$1;
var deflateRaw_1 = deflateRaw;
var gzip_1 = gzip;

var deflate_1$1 = {
	Deflate: Deflate_1,
	deflate: deflate_2$1,
	deflateRaw: deflateRaw_1,
	gzip: gzip_1
};

// (C) 1995-2013 Jean-loup Gailly and Mark Adler
// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented; you must not
//   claim that you wrote the original software. If you use this software
//   in a product, an acknowledgment in the product documentation would be
//   appreciated but is not required.
// 2. Altered source versions must be plainly marked as such, and must not be
//   misrepresented as being the original software.
// 3. This notice may not be removed or altered from any source distribution.

// See state defs from inflate.js
var BAD = 30;       /* got a data error -- remain here until reset */
var TYPE = 12;      /* i: waiting for type bits, including last-flag bit */

/*
   Decode literal, length, and distance codes and write out the resulting
   literal and match bytes until either not enough input or output is
   available, an end-of-block is encountered, or a data error is encountered.
   When large enough input and output buffers are supplied to inflate(), for
   example, a 16K input buffer and a 64K output buffer, more than 95% of the
   inflate execution time is spent in this routine.

   Entry assumptions:

        state.mode === LEN
        strm.avail_in >= 6
        strm.avail_out >= 258
        start >= strm.avail_out
        state.bits < 8

   On return, state.mode is one of:

        LEN -- ran out of enough output space or enough available input
        TYPE -- reached end of block code, inflate() to interpret next block
        BAD -- error in block data

   Notes:

    - The maximum input bits used by a length/distance pair is 15 bits for the
      length code, 5 bits for the length extra, 15 bits for the distance code,
      and 13 bits for the distance extra.  This totals 48 bits, or six bytes.
      Therefore if strm.avail_in >= 6, then there is enough input to avoid
      checking for available input while decoding.

    - The maximum bytes that a single length/distance pair can output is 258
      bytes, which is the maximum length that can be coded.  inflate_fast()
      requires strm.avail_out >= 258 for each loop to avoid checking for
      output space.
 */
var inffast = function inflate_fast(strm, start) {
  var state;
  var _in;                    /* local strm.input */
  var last;                   /* have enough input while in < last */
  var _out;                   /* local strm.output */
  var beg;                    /* inflate()'s initial strm.output */
  var end;                    /* while out < end, enough space available */
//#ifdef INFLATE_STRICT
  var dmax;                   /* maximum distance from zlib header */
//#endif
  var wsize;                  /* window size or zero if not using window */
  var whave;                  /* valid bytes in the window */
  var wnext;                  /* window write index */
  // Use `s_window` instead `window`, avoid conflict with instrumentation tools
  var s_window;               /* allocated sliding window, if wsize != 0 */
  var hold;                   /* local strm.hold */
  var bits;                   /* local strm.bits */
  var lcode;                  /* local strm.lencode */
  var dcode;                  /* local strm.distcode */
  var lmask;                  /* mask for first level of length codes */
  var dmask;                  /* mask for first level of distance codes */
  var here;                   /* retrieved table entry */
  var op;                     /* code bits, operation, extra bits, or */
                              /*  window position, window bytes to copy */
  var len;                    /* match length, unused bytes */
  var dist;                   /* match distance */
  var from;                   /* where to copy match from */
  var from_source;


  var input, output; // JS specific, because we have no pointers

  /* copy state to local variables */
  state = strm.state;
  //here = state.here;
  _in = strm.next_in;
  input = strm.input;
  last = _in + (strm.avail_in - 5);
  _out = strm.next_out;
  output = strm.output;
  beg = _out - (start - strm.avail_out);
  end = _out + (strm.avail_out - 257);
//#ifdef INFLATE_STRICT
  dmax = state.dmax;
//#endif
  wsize = state.wsize;
  whave = state.whave;
  wnext = state.wnext;
  s_window = state.window;
  hold = state.hold;
  bits = state.bits;
  lcode = state.lencode;
  dcode = state.distcode;
  lmask = (1 << state.lenbits) - 1;
  dmask = (1 << state.distbits) - 1;


  /* decode literals and length/distances until end-of-block or not enough
     input data or output space */

  top:
  do {
    if (bits < 15) {
      hold += input[_in++] << bits;
      bits += 8;
      hold += input[_in++] << bits;
      bits += 8;
    }

    here = lcode[hold & lmask];

    dolen:
    for (;;) { // Goto emulation
      op = here >>> 24/*here.bits*/;
      hold >>>= op;
      bits -= op;
      op = (here >>> 16) & 0xff/*here.op*/;
      if (op === 0) {                          /* literal */
        //Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ?
        //        "inflate:         literal '%c'\n" :
        //        "inflate:         literal 0x%02x\n", here.val));
        output[_out++] = here & 0xffff/*here.val*/;
      }
      else if (op & 16) {                     /* length base */
        len = here & 0xffff/*here.val*/;
        op &= 15;                           /* number of extra bits */
        if (op) {
          if (bits < op) {
            hold += input[_in++] << bits;
            bits += 8;
          }
          len += hold & ((1 << op) - 1);
          hold >>>= op;
          bits -= op;
        }
        //Tracevv((stderr, "inflate:         length %u\n", len));
        if (bits < 15) {
          hold += input[_in++] << bits;
          bits += 8;
          hold += input[_in++] << bits;
          bits += 8;
        }
        here = dcode[hold & dmask];

        dodist:
        for (;;) { // goto emulation
          op = here >>> 24/*here.bits*/;
          hold >>>= op;
          bits -= op;
          op = (here >>> 16) & 0xff/*here.op*/;

          if (op & 16) {                      /* distance base */
            dist = here & 0xffff/*here.val*/;
            op &= 15;                       /* number of extra bits */
            if (bits < op) {
              hold += input[_in++] << bits;
              bits += 8;
              if (bits < op) {
                hold += input[_in++] << bits;
                bits += 8;
              }
            }
            dist += hold & ((1 << op) - 1);
//#ifdef INFLATE_STRICT
            if (dist > dmax) {
              strm.msg = 'invalid distance too far back';
              state.mode = BAD;
              break top;
            }
//#endif
            hold >>>= op;
            bits -= op;
            //Tracevv((stderr, "inflate:         distance %u\n", dist));
            op = _out - beg;                /* max distance in output */
            if (dist > op) {                /* see if copy from window */
              op = dist - op;               /* distance back in window */
              if (op > whave) {
                if (state.sane) {
                  strm.msg = 'invalid distance too far back';
                  state.mode = BAD;
                  break top;
                }

// (!) This block is disabled in zlib defaults,
// don't enable it for binary compatibility
//#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR
//                if (len <= op - whave) {
//                  do {
//                    output[_out++] = 0;
//                  } while (--len);
//                  continue top;
//                }
//                len -= op - whave;
//                do {
//                  output[_out++] = 0;
//                } while (--op > whave);
//                if (op === 0) {
//                  from = _out - dist;
//                  do {
//                    output[_out++] = output[from++];
//                  } while (--len);
//                  continue top;
//                }
//#endif
              }
              from = 0; // window index
              from_source = s_window;
              if (wnext === 0) {           /* very common case */
                from += wsize - op;
                if (op < len) {         /* some from window */
                  len -= op;
                  do {
                    output[_out++] = s_window[from++];
                  } while (--op);
                  from = _out - dist;  /* rest from output */
                  from_source = output;
                }
              }
              else if (wnext < op) {      /* wrap around window */
                from += wsize + wnext - op;
                op -= wnext;
                if (op < len) {         /* some from end of window */
                  len -= op;
                  do {
                    output[_out++] = s_window[from++];
                  } while (--op);
                  from = 0;
                  if (wnext < len) {  /* some from start of window */
                    op = wnext;
                    len -= op;
                    do {
                      output[_out++] = s_window[from++];
                    } while (--op);
                    from = _out - dist;      /* rest from output */
                    from_source = output;
                  }
                }
              }
              else {                      /* contiguous in window */
                from += wnext - op;
                if (op < len) {         /* some from window */
                  len -= op;
                  do {
                    output[_out++] = s_window[from++];
                  } while (--op);
                  from = _out - dist;  /* rest from output */
                  from_source = output;
                }
              }
              while (len > 2) {
                output[_out++] = from_source[from++];
                output[_out++] = from_source[from++];
                output[_out++] = from_source[from++];
                len -= 3;
              }
              if (len) {
                output[_out++] = from_source[from++];
                if (len > 1) {
                  output[_out++] = from_source[from++];
                }
              }
            }
            else {
              from = _out - dist;          /* copy direct from output */
              do {                        /* minimum length is three */
                output[_out++] = output[from++];
                output[_out++] = output[from++];
                output[_out++] = output[from++];
                len -= 3;
              } while (len > 2);
              if (len) {
                output[_out++] = output[from++];
                if (len > 1) {
                  output[_out++] = output[from++];
                }
              }
            }
          }
          else if ((op & 64) === 0) {          /* 2nd level distance code */
            here = dcode[(here & 0xffff)/*here.val*/ + (hold & ((1 << op) - 1))];
            continue dodist;
          }
          else {
            strm.msg = 'invalid distance code';
            state.mode = BAD;
            break top;
          }

          break; // need to emulate goto via "continue"
        }
      }
      else if ((op & 64) === 0) {              /* 2nd level length code */
        here = lcode[(here & 0xffff)/*here.val*/ + (hold & ((1 << op) - 1))];
        continue dolen;
      }
      else if (op & 32) {                     /* end-of-block */
        //Tracevv((stderr, "inflate:         end of block\n"));
        state.mode = TYPE;
        break top;
      }
      else {
        strm.msg = 'invalid literal/length code';
        state.mode = BAD;
        break top;
      }

      break; // need to emulate goto via "continue"
    }
  } while (_in < last && _out < end);

  /* return unused bytes (on entry, bits < 8, so in won't go too far back) */
  len = bits >> 3;
  _in -= len;
  bits -= len << 3;
  hold &= (1 << bits) - 1;

  /* update state and return */
  strm.next_in = _in;
  strm.next_out = _out;
  strm.avail_in = (_in < last ? 5 + (last - _in) : 5 - (_in - last));
  strm.avail_out = (_out < end ? 257 + (end - _out) : 257 - (_out - end));
  state.hold = hold;
  state.bits = bits;
  return;
};

// (C) 1995-2013 Jean-loup Gailly and Mark Adler
// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented; you must not
//   claim that you wrote the original software. If you use this software
//   in a product, an acknowledgment in the product documentation would be
//   appreciated but is not required.
// 2. Altered source versions must be plainly marked as such, and must not be
//   misrepresented as being the original software.
// 3. This notice may not be removed or altered from any source distribution.



var MAXBITS = 15;
var ENOUGH_LENS = 852;
var ENOUGH_DISTS = 592;
//var ENOUGH = (ENOUGH_LENS+ENOUGH_DISTS);

var CODES = 0;
var LENS = 1;
var DISTS = 2;

var lbase = [ /* Length codes 257..285 base */
  3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
  35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0
];

var lext = [ /* Length codes 257..285 extra */
  16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18,
  19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 72, 78
];

var dbase = [ /* Distance codes 0..29 base */
  1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
  257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
  8193, 12289, 16385, 24577, 0, 0
];

var dext = [ /* Distance codes 0..29 extra */
  16, 16, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22,
  23, 23, 24, 24, 25, 25, 26, 26, 27, 27,
  28, 28, 29, 29, 64, 64
];

var inftrees = function inflate_table(type, lens, lens_index, codes, table, table_index, work, opts)
{
  var bits = opts.bits;
      //here = opts.here; /* table entry for duplication */

  var len = 0;               /* a code's length in bits */
  var sym = 0;               /* index of code symbols */
  var min = 0, max = 0;          /* minimum and maximum code lengths */
  var root = 0;              /* number of index bits for root table */
  var curr = 0;              /* number of index bits for current table */
  var drop = 0;              /* code bits to drop for sub-table */
  var left = 0;                   /* number of prefix codes available */
  var used = 0;              /* code entries in table used */
  var huff = 0;              /* Huffman code */
  var incr;              /* for incrementing code, index */
  var fill;              /* index for replicating entries */
  var low;               /* low bits for current root entry */
  var mask;              /* mask for low root bits */
  var next;             /* next available space in table */
  var base = null;     /* base value table to use */
  var base_index = 0;
//  var shoextra;    /* extra bits table to use */
  var end;                    /* use base and extra for symbol > end */
  var count = new common$e.Buf16(MAXBITS + 1); //[MAXBITS+1];    /* number of codes of each length */
  var offs = new common$e.Buf16(MAXBITS + 1); //[MAXBITS+1];     /* offsets in table for each length */
  var extra = null;
  var extra_index = 0;

  var here_bits, here_op, here_val;

  /*
   Process a set of code lengths to create a canonical Huffman code.  The
   code lengths are lens[0..codes-1].  Each length corresponds to the
   symbols 0..codes-1.  The Huffman code is generated by first sorting the
   symbols by length from short to long, and retaining the symbol order
   for codes with equal lengths.  Then the code starts with all zero bits
   for the first code of the shortest length, and the codes are integer
   increments for the same length, and zeros are appended as the length
   increases.  For the deflate format, these bits are stored backwards
   from their more natural integer increment ordering, and so when the
   decoding tables are built in the large loop below, the integer codes
   are incremented backwards.

   This routine assumes, but does not check, that all of the entries in
   lens[] are in the range 0..MAXBITS.  The caller must assure this.
   1..MAXBITS is interpreted as that code length.  zero means that that
   symbol does not occur in this code.

   The codes are sorted by computing a count of codes for each length,
   creating from that a table of starting indices for each length in the
   sorted table, and then entering the symbols in order in the sorted
   table.  The sorted table is work[], with that space being provided by
   the caller.

   The length counts are used for other purposes as well, i.e. finding
   the minimum and maximum length codes, determining if there are any
   codes at all, checking for a valid set of lengths, and looking ahead
   at length counts to determine sub-table sizes when building the
   decoding tables.
   */

  /* accumulate lengths for codes (assumes lens[] all in 0..MAXBITS) */
  for (len = 0; len <= MAXBITS; len++) {
    count[len] = 0;
  }
  for (sym = 0; sym < codes; sym++) {
    count[lens[lens_index + sym]]++;
  }

  /* bound code lengths, force root to be within code lengths */
  root = bits;
  for (max = MAXBITS; max >= 1; max--) {
    if (count[max] !== 0) { break; }
  }
  if (root > max) {
    root = max;
  }
  if (max === 0) {                     /* no symbols to code at all */
    //table.op[opts.table_index] = 64;  //here.op = (var char)64;    /* invalid code marker */
    //table.bits[opts.table_index] = 1;   //here.bits = (var char)1;
    //table.val[opts.table_index++] = 0;   //here.val = (var short)0;
    table[table_index++] = (1 << 24) | (64 << 16) | 0;


    //table.op[opts.table_index] = 64;
    //table.bits[opts.table_index] = 1;
    //table.val[opts.table_index++] = 0;
    table[table_index++] = (1 << 24) | (64 << 16) | 0;

    opts.bits = 1;
    return 0;     /* no symbols, but wait for decoding to report error */
  }
  for (min = 1; min < max; min++) {
    if (count[min] !== 0) { break; }
  }
  if (root < min) {
    root = min;
  }

  /* check for an over-subscribed or incomplete set of lengths */
  left = 1;
  for (len = 1; len <= MAXBITS; len++) {
    left <<= 1;
    left -= count[len];
    if (left < 0) {
      return -1;
    }        /* over-subscribed */
  }
  if (left > 0 && (type === CODES || max !== 1)) {
    return -1;                      /* incomplete set */
  }

  /* generate offsets into symbol table for each length for sorting */
  offs[1] = 0;
  for (len = 1; len < MAXBITS; len++) {
    offs[len + 1] = offs[len] + count[len];
  }

  /* sort symbols by length, by symbol order within each length */
  for (sym = 0; sym < codes; sym++) {
    if (lens[lens_index + sym] !== 0) {
      work[offs[lens[lens_index + sym]]++] = sym;
    }
  }

  /*
   Create and fill in decoding tables.  In this loop, the table being
   filled is at next and has curr index bits.  The code being used is huff
   with length len.  That code is converted to an index by dropping drop
   bits off of the bottom.  For codes where len is less than drop + curr,
   those top drop + curr - len bits are incremented through all values to
   fill the table with replicated entries.

   root is the number of index bits for the root table.  When len exceeds
   root, sub-tables are created pointed to by the root entry with an index
   of the low root bits of huff.  This is saved in low to check for when a
   new sub-table should be started.  drop is zero when the root table is
   being filled, and drop is root when sub-tables are being filled.

   When a new sub-table is needed, it is necessary to look ahead in the
   code lengths to determine what size sub-table is needed.  The length
   counts are used for this, and so count[] is decremented as codes are
   entered in the tables.

   used keeps track of how many table entries have been allocated from the
   provided *table space.  It is checked for LENS and DIST tables against
   the constants ENOUGH_LENS and ENOUGH_DISTS to guard against changes in
   the initial root table size constants.  See the comments in inftrees.h
   for more information.

   sym increments through all symbols, and the loop terminates when
   all codes of length max, i.e. all codes, have been processed.  This
   routine permits incomplete codes, so another loop after this one fills
   in the rest of the decoding tables with invalid code markers.
   */

  /* set up for code type */
  // poor man optimization - use if-else instead of switch,
  // to avoid deopts in old v8
  if (type === CODES) {
    base = extra = work;    /* dummy value--not used */
    end = 19;

  } else if (type === LENS) {
    base = lbase;
    base_index -= 257;
    extra = lext;
    extra_index -= 257;
    end = 256;

  } else {                    /* DISTS */
    base = dbase;
    extra = dext;
    end = -1;
  }

  /* initialize opts for loop */
  huff = 0;                   /* starting code */
  sym = 0;                    /* starting code symbol */
  len = min;                  /* starting code length */
  next = table_index;              /* current table to fill in */
  curr = root;                /* current table index bits */
  drop = 0;                   /* current bits to drop from code for index */
  low = -1;                   /* trigger new sub-table when len > root */
  used = 1 << root;          /* use root table entries */
  mask = used - 1;            /* mask for comparing low */

  /* check available table space */
  if ((type === LENS && used > ENOUGH_LENS) ||
    (type === DISTS && used > ENOUGH_DISTS)) {
    return 1;
  }

  /* process all codes and make table entries */
  for (;;) {
    /* create table entry */
    here_bits = len - drop;
    if (work[sym] < end) {
      here_op = 0;
      here_val = work[sym];
    }
    else if (work[sym] > end) {
      here_op = extra[extra_index + work[sym]];
      here_val = base[base_index + work[sym]];
    }
    else {
      here_op = 32 + 64;         /* end of block */
      here_val = 0;
    }

    /* replicate for those indices with low len bits equal to huff */
    incr = 1 << (len - drop);
    fill = 1 << curr;
    min = fill;                 /* save offset to next table */
    do {
      fill -= incr;
      table[next + (huff >> drop) + fill] = (here_bits << 24) | (here_op << 16) | here_val |0;
    } while (fill !== 0);

    /* backwards increment the len-bit code huff */
    incr = 1 << (len - 1);
    while (huff & incr) {
      incr >>= 1;
    }
    if (incr !== 0) {
      huff &= incr - 1;
      huff += incr;
    } else {
      huff = 0;
    }

    /* go to next symbol, update count, len */
    sym++;
    if (--count[len] === 0) {
      if (len === max) { break; }
      len = lens[lens_index + work[sym]];
    }

    /* create new sub-table if needed */
    if (len > root && (huff & mask) !== low) {
      /* if first time, transition to sub-tables */
      if (drop === 0) {
        drop = root;
      }

      /* increment past last table */
      next += min;            /* here min is 1 << curr */

      /* determine length of next table */
      curr = len - drop;
      left = 1 << curr;
      while (curr + drop < max) {
        left -= count[curr + drop];
        if (left <= 0) { break; }
        curr++;
        left <<= 1;
      }

      /* check for enough space */
      used += 1 << curr;
      if ((type === LENS && used > ENOUGH_LENS) ||
        (type === DISTS && used > ENOUGH_DISTS)) {
        return 1;
      }

      /* point entry in root table to sub-table */
      low = huff & mask;
      /*table.op[low] = curr;
      table.bits[low] = root;
      table.val[low] = next - opts.table_index;*/
      table[low] = (root << 24) | (curr << 16) | (next - table_index) |0;
    }
  }

  /* fill in remaining table entry if code is incomplete (guaranteed to have
   at most one remaining entry, since if the code is incomplete, the
   maximum code length that was allowed to get this far is one bit) */
  if (huff !== 0) {
    //table.op[next + huff] = 64;            /* invalid code marker */
    //table.bits[next + huff] = len - drop;
    //table.val[next + huff] = 0;
    table[next + huff] = ((len - drop) << 24) | (64 << 16) |0;
  }

  /* set return parameters */
  //opts.table_index += used;
  opts.bits = root;
  return 0;
};

// (C) 1995-2013 Jean-loup Gailly and Mark Adler
// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented; you must not
//   claim that you wrote the original software. If you use this software
//   in a product, an acknowledgment in the product documentation would be
//   appreciated but is not required.
// 2. Altered source versions must be plainly marked as such, and must not be
//   misrepresented as being the original software.
// 3. This notice may not be removed or altered from any source distribution.







var CODES$1 = 0;
var LENS$1 = 1;
var DISTS$1 = 2;

/* Public constants ==========================================================*/
/* ===========================================================================*/


/* Allowed flush values; see deflate() and inflate() below for details */
//var Z_NO_FLUSH      = 0;
//var Z_PARTIAL_FLUSH = 1;
//var Z_SYNC_FLUSH    = 2;
//var Z_FULL_FLUSH    = 3;
var Z_FINISH$2        = 4;
var Z_BLOCK$1         = 5;
var Z_TREES         = 6;


/* Return codes for the compression/decompression functions. Negative values
 * are errors, positive values are used for special but normal events.
 */
var Z_OK$2            = 0;
var Z_STREAM_END$2    = 1;
var Z_NEED_DICT     = 2;
//var Z_ERRNO         = -1;
var Z_STREAM_ERROR$1  = -2;
var Z_DATA_ERROR$1    = -3;
var Z_MEM_ERROR     = -4;
var Z_BUF_ERROR$1     = -5;
//var Z_VERSION_ERROR = -6;

/* The deflate compression method */
var Z_DEFLATED$2  = 8;


/* STATES ====================================================================*/
/* ===========================================================================*/


var    HEAD = 1;       /* i: waiting for magic header */
var    FLAGS = 2;      /* i: waiting for method and flags (gzip) */
var    TIME = 3;       /* i: waiting for modification time (gzip) */
var    OS = 4;         /* i: waiting for extra flags and operating system (gzip) */
var    EXLEN = 5;      /* i: waiting for extra length (gzip) */
var    EXTRA = 6;      /* i: waiting for extra bytes (gzip) */
var    NAME = 7;       /* i: waiting for end of file name (gzip) */
var    COMMENT = 8;    /* i: waiting for end of comment (gzip) */
var    HCRC = 9;       /* i: waiting for header crc (gzip) */
var    DICTID = 10;    /* i: waiting for dictionary check value */
var    DICT = 11;      /* waiting for inflateSetDictionary() call */
var        TYPE$1 = 12;      /* i: waiting for type bits, including last-flag bit */
var        TYPEDO = 13;    /* i: same, but skip check to exit inflate on new block */
var        STORED = 14;    /* i: waiting for stored size (length and complement) */
var        COPY_ = 15;     /* i/o: same as COPY below, but only first time in */
var        COPY = 16;      /* i/o: waiting for input or output to copy stored block */
var        TABLE = 17;     /* i: waiting for dynamic block table lengths */
var        LENLENS = 18;   /* i: waiting for code length code lengths */
var        CODELENS = 19;  /* i: waiting for length/lit and distance code lengths */
var            LEN_ = 20;      /* i: same as LEN below, but only first time in */
var            LEN = 21;       /* i: waiting for length/lit/eob code */
var            LENEXT = 22;    /* i: waiting for length extra bits */
var            DIST = 23;      /* i: waiting for distance code */
var            DISTEXT = 24;   /* i: waiting for distance extra bits */
var            MATCH = 25;     /* o: waiting for output space to copy string */
var            LIT = 26;       /* o: waiting for output space to write literal */
var    CHECK = 27;     /* i: waiting for 32-bit check value */
var    LENGTH = 28;    /* i: waiting for 32-bit length (gzip) */
var    DONE = 29;      /* finished check, done -- remain here until reset */
var    BAD$1 = 30;       /* got a data error -- remain here until reset */
var    MEM = 31;       /* got an inflate() memory error -- remain here until reset */
var    SYNC = 32;      /* looking for synchronization bytes to restart inflate() */

/* ===========================================================================*/



var ENOUGH_LENS$1 = 852;
var ENOUGH_DISTS$1 = 592;
//var ENOUGH =  (ENOUGH_LENS+ENOUGH_DISTS);

var MAX_WBITS$1 = 15;
/* 32K LZ77 window */
var DEF_WBITS = MAX_WBITS$1;


function zswap32(q) {
  return  (((q >>> 24) & 0xff) +
          ((q >>> 8) & 0xff00) +
          ((q & 0xff00) << 8) +
          ((q & 0xff) << 24));
}


function InflateState() {
  this.mode = 0;             /* current inflate mode */
  this.last = false;          /* true if processing last block */
  this.wrap = 0;              /* bit 0 true for zlib, bit 1 true for gzip */
  this.havedict = false;      /* true if dictionary provided */
  this.flags = 0;             /* gzip header method and flags (0 if zlib) */
  this.dmax = 0;              /* zlib header max distance (INFLATE_STRICT) */
  this.check = 0;             /* protected copy of check value */
  this.total = 0;             /* protected copy of output count */
  // TODO: may be {}
  this.head = null;           /* where to save gzip header information */

  /* sliding window */
  this.wbits = 0;             /* log base 2 of requested window size */
  this.wsize = 0;             /* window size or zero if not using window */
  this.whave = 0;             /* valid bytes in the window */
  this.wnext = 0;             /* window write index */
  this.window = null;         /* allocated sliding window, if needed */

  /* bit accumulator */
  this.hold = 0;              /* input bit accumulator */
  this.bits = 0;              /* number of bits in "in" */

  /* for string and stored block copying */
  this.length = 0;            /* literal or length of data to copy */
  this.offset = 0;            /* distance back to copy string from */

  /* for table and code decoding */
  this.extra = 0;             /* extra bits needed */

  /* fixed and dynamic code tables */
  this.lencode = null;          /* starting table for length/literal codes */
  this.distcode = null;         /* starting table for distance codes */
  this.lenbits = 0;           /* index bits for lencode */
  this.distbits = 0;          /* index bits for distcode */

  /* dynamic table building */
  this.ncode = 0;             /* number of code length code lengths */
  this.nlen = 0;              /* number of length code lengths */
  this.ndist = 0;             /* number of distance code lengths */
  this.have = 0;              /* number of code lengths in lens[] */
  this.next = null;              /* next available space in codes[] */

  this.lens = new common$e.Buf16(320); /* temporary storage for code lengths */
  this.work = new common$e.Buf16(288); /* work area for code table building */

  /*
   because we don't have pointers in js, we use lencode and distcode directly
   as buffers so we don't need codes
  */
  //this.codes = new utils.Buf32(ENOUGH);       /* space for code tables */
  this.lendyn = null;              /* dynamic table for length/literal codes (JS specific) */
  this.distdyn = null;             /* dynamic table for distance codes (JS specific) */
  this.sane = 0;                   /* if false, allow invalid distance too far */
  this.back = 0;                   /* bits back of last unprocessed length/lit */
  this.was = 0;                    /* initial length of match */
}

function inflateResetKeep(strm) {
  var state;

  if (!strm || !strm.state) { return Z_STREAM_ERROR$1; }
  state = strm.state;
  strm.total_in = strm.total_out = state.total = 0;
  strm.msg = ''; /*Z_NULL*/
  if (state.wrap) {       /* to support ill-conceived Java test suite */
    strm.adler = state.wrap & 1;
  }
  state.mode = HEAD;
  state.last = 0;
  state.havedict = 0;
  state.dmax = 32768;
  state.head = null/*Z_NULL*/;
  state.hold = 0;
  state.bits = 0;
  //state.lencode = state.distcode = state.next = state.codes;
  state.lencode = state.lendyn = new common$e.Buf32(ENOUGH_LENS$1);
  state.distcode = state.distdyn = new common$e.Buf32(ENOUGH_DISTS$1);

  state.sane = 1;
  state.back = -1;
  //Tracev((stderr, "inflate: reset\n"));
  return Z_OK$2;
}

function inflateReset(strm) {
  var state;

  if (!strm || !strm.state) { return Z_STREAM_ERROR$1; }
  state = strm.state;
  state.wsize = 0;
  state.whave = 0;
  state.wnext = 0;
  return inflateResetKeep(strm);

}

function inflateReset2(strm, windowBits) {
  var wrap;
  var state;

  /* get the state */
  if (!strm || !strm.state) { return Z_STREAM_ERROR$1; }
  state = strm.state;

  /* extract wrap request from windowBits parameter */
  if (windowBits < 0) {
    wrap = 0;
    windowBits = -windowBits;
  }
  else {
    wrap = (windowBits >> 4) + 1;
    if (windowBits < 48) {
      windowBits &= 15;
    }
  }

  /* set number of window bits, free window if different */
  if (windowBits && (windowBits < 8 || windowBits > 15)) {
    return Z_STREAM_ERROR$1;
  }
  if (state.window !== null && state.wbits !== windowBits) {
    state.window = null;
  }

  /* update state and reset the rest of it */
  state.wrap = wrap;
  state.wbits = windowBits;
  return inflateReset(strm);
}

function inflateInit2(strm, windowBits) {
  var ret;
  var state;

  if (!strm) { return Z_STREAM_ERROR$1; }
  //strm.msg = Z_NULL;                 /* in case we return an error */

  state = new InflateState();

  //if (state === Z_NULL) return Z_MEM_ERROR;
  //Tracev((stderr, "inflate: allocated\n"));
  strm.state = state;
  state.window = null/*Z_NULL*/;
  ret = inflateReset2(strm, windowBits);
  if (ret !== Z_OK$2) {
    strm.state = null/*Z_NULL*/;
  }
  return ret;
}

function inflateInit(strm) {
  return inflateInit2(strm, DEF_WBITS);
}


/*
 Return state with length and distance decoding tables and index sizes set to
 fixed code decoding.  Normally this returns fixed tables from inffixed.h.
 If BUILDFIXED is defined, then instead this routine builds the tables the
 first time it's called, and returns those tables the first time and
 thereafter.  This reduces the size of the code by about 2K bytes, in
 exchange for a little execution time.  However, BUILDFIXED should not be
 used for threaded applications, since the rewriting of the tables and virgin
 may not be thread-safe.
 */
var virgin = true;

var lenfix, distfix; // We have no pointers in JS, so keep tables separate

function fixedtables(state) {
  /* build fixed huffman tables if first call (may not be thread safe) */
  if (virgin) {
    var sym;

    lenfix = new common$e.Buf32(512);
    distfix = new common$e.Buf32(32);

    /* literal/length table */
    sym = 0;
    while (sym < 144) { state.lens[sym++] = 8; }
    while (sym < 256) { state.lens[sym++] = 9; }
    while (sym < 280) { state.lens[sym++] = 7; }
    while (sym < 288) { state.lens[sym++] = 8; }

    inftrees(LENS$1,  state.lens, 0, 288, lenfix,   0, state.work, { bits: 9 });

    /* distance table */
    sym = 0;
    while (sym < 32) { state.lens[sym++] = 5; }

    inftrees(DISTS$1, state.lens, 0, 32,   distfix, 0, state.work, { bits: 5 });

    /* do this just once */
    virgin = false;
  }

  state.lencode = lenfix;
  state.lenbits = 9;
  state.distcode = distfix;
  state.distbits = 5;
}


/*
 Update the window with the last wsize (normally 32K) bytes written before
 returning.  If window does not exist yet, create it.  This is only called
 when a window is already in use, or when output has been written during this
 inflate call, but the end of the deflate stream has not been reached yet.
 It is also called to create a window for dictionary data when a dictionary
 is loaded.

 Providing output buffers larger than 32K to inflate() should provide a speed
 advantage, since only the last 32K of output is copied to the sliding window
 upon return from inflate(), and since all distances after the first 32K of
 output will fall in the output data, making match copies simpler and faster.
 The advantage may be dependent on the size of the processor's data caches.
 */
function updatewindow(strm, src, end, copy) {
  var dist;
  var state = strm.state;

  /* if it hasn't been done already, allocate space for the window */
  if (state.window === null) {
    state.wsize = 1 << state.wbits;
    state.wnext = 0;
    state.whave = 0;

    state.window = new common$e.Buf8(state.wsize);
  }

  /* copy state->wsize or less output bytes into the circular window */
  if (copy >= state.wsize) {
    common$e.arraySet(state.window, src, end - state.wsize, state.wsize, 0);
    state.wnext = 0;
    state.whave = state.wsize;
  }
  else {
    dist = state.wsize - state.wnext;
    if (dist > copy) {
      dist = copy;
    }
    //zmemcpy(state->window + state->wnext, end - copy, dist);
    common$e.arraySet(state.window, src, end - copy, dist, state.wnext);
    copy -= dist;
    if (copy) {
      //zmemcpy(state->window, end - copy, copy);
      common$e.arraySet(state.window, src, end - copy, copy, 0);
      state.wnext = copy;
      state.whave = state.wsize;
    }
    else {
      state.wnext += dist;
      if (state.wnext === state.wsize) { state.wnext = 0; }
      if (state.whave < state.wsize) { state.whave += dist; }
    }
  }
  return 0;
}

function inflate(strm, flush) {
  var state;
  var input, output;          // input/output buffers
  var next;                   /* next input INDEX */
  var put;                    /* next output INDEX */
  var have, left;             /* available input and output */
  var hold;                   /* bit buffer */
  var bits;                   /* bits in bit buffer */
  var _in, _out;              /* save starting available input and output */
  var copy;                   /* number of stored or match bytes to copy */
  var from;                   /* where to copy match bytes from */
  var from_source;
  var here = 0;               /* current decoding table entry */
  var here_bits, here_op, here_val; // paked "here" denormalized (JS specific)
  //var last;                   /* parent table entry */
  var last_bits, last_op, last_val; // paked "last" denormalized (JS specific)
  var len;                    /* length to copy for repeats, bits to drop */
  var ret;                    /* return code */
  var hbuf = new common$e.Buf8(4);    /* buffer for gzip header crc calculation */
  var opts;

  var n; // temporary var for NEED_BITS

  var order = /* permutation of code lengths */
    [ 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 ];


  if (!strm || !strm.state || !strm.output ||
      (!strm.input && strm.avail_in !== 0)) {
    return Z_STREAM_ERROR$1;
  }

  state = strm.state;
  if (state.mode === TYPE$1) { state.mode = TYPEDO; }    /* skip check */


  //--- LOAD() ---
  put = strm.next_out;
  output = strm.output;
  left = strm.avail_out;
  next = strm.next_in;
  input = strm.input;
  have = strm.avail_in;
  hold = state.hold;
  bits = state.bits;
  //---

  _in = have;
  _out = left;
  ret = Z_OK$2;

  inf_leave: // goto emulation
  for (;;) {
    switch (state.mode) {
      case HEAD:
        if (state.wrap === 0) {
          state.mode = TYPEDO;
          break;
        }
        //=== NEEDBITS(16);
        while (bits < 16) {
          if (have === 0) { break inf_leave; }
          have--;
          hold += input[next++] << bits;
          bits += 8;
        }
        //===//
        if ((state.wrap & 2) && hold === 0x8b1f) {  /* gzip header */
          state.check = 0/*crc32(0L, Z_NULL, 0)*/;
          //=== CRC2(state.check, hold);
          hbuf[0] = hold & 0xff;
          hbuf[1] = (hold >>> 8) & 0xff;
          state.check = crc32_1(state.check, hbuf, 2, 0);
          //===//

          //=== INITBITS();
          hold = 0;
          bits = 0;
          //===//
          state.mode = FLAGS;
          break;
        }
        state.flags = 0;           /* expect zlib header */
        if (state.head) {
          state.head.done = false;
        }
        if (!(state.wrap & 1) ||   /* check if zlib header allowed */
          (((hold & 0xff)/*BITS(8)*/ << 8) + (hold >> 8)) % 31) {
          strm.msg = 'incorrect header check';
          state.mode = BAD$1;
          break;
        }
        if ((hold & 0x0f)/*BITS(4)*/ !== Z_DEFLATED$2) {
          strm.msg = 'unknown compression method';
          state.mode = BAD$1;
          break;
        }
        //--- DROPBITS(4) ---//
        hold >>>= 4;
        bits -= 4;
        //---//
        len = (hold & 0x0f)/*BITS(4)*/ + 8;
        if (state.wbits === 0) {
          state.wbits = len;
        }
        else if (len > state.wbits) {
          strm.msg = 'invalid window size';
          state.mode = BAD$1;
          break;
        }
        state.dmax = 1 << len;
        //Tracev((stderr, "inflate:   zlib header ok\n"));
        strm.adler = state.check = 1/*adler32(0L, Z_NULL, 0)*/;
        state.mode = hold & 0x200 ? DICTID : TYPE$1;
        //=== INITBITS();
        hold = 0;
        bits = 0;
        //===//
        break;
      case FLAGS:
        //=== NEEDBITS(16); */
        while (bits < 16) {
          if (have === 0) { break inf_leave; }
          have--;
          hold += input[next++] << bits;
          bits += 8;
        }
        //===//
        state.flags = hold;
        if ((state.flags & 0xff) !== Z_DEFLATED$2) {
          strm.msg = 'unknown compression method';
          state.mode = BAD$1;
          break;
        }
        if (state.flags & 0xe000) {
          strm.msg = 'unknown header flags set';
          state.mode = BAD$1;
          break;
        }
        if (state.head) {
          state.head.text = ((hold >> 8) & 1);
        }
        if (state.flags & 0x0200) {
          //=== CRC2(state.check, hold);
          hbuf[0] = hold & 0xff;
          hbuf[1] = (hold >>> 8) & 0xff;
          state.check = crc32_1(state.check, hbuf, 2, 0);
          //===//
        }
        //=== INITBITS();
        hold = 0;
        bits = 0;
        //===//
        state.mode = TIME;
        /* falls through */
      case TIME:
        //=== NEEDBITS(32); */
        while (bits < 32) {
          if (have === 0) { break inf_leave; }
          have--;
          hold += input[next++] << bits;
          bits += 8;
        }
        //===//
        if (state.head) {
          state.head.time = hold;
        }
        if (state.flags & 0x0200) {
          //=== CRC4(state.check, hold)
          hbuf[0] = hold & 0xff;
          hbuf[1] = (hold >>> 8) & 0xff;
          hbuf[2] = (hold >>> 16) & 0xff;
          hbuf[3] = (hold >>> 24) & 0xff;
          state.check = crc32_1(state.check, hbuf, 4, 0);
          //===
        }
        //=== INITBITS();
        hold = 0;
        bits = 0;
        //===//
        state.mode = OS;
        /* falls through */
      case OS:
        //=== NEEDBITS(16); */
        while (bits < 16) {
          if (have === 0) { break inf_leave; }
          have--;
          hold += input[next++] << bits;
          bits += 8;
        }
        //===//
        if (state.head) {
          state.head.xflags = (hold & 0xff);
          state.head.os = (hold >> 8);
        }
        if (state.flags & 0x0200) {
          //=== CRC2(state.check, hold);
          hbuf[0] = hold & 0xff;
          hbuf[1] = (hold >>> 8) & 0xff;
          state.check = crc32_1(state.check, hbuf, 2, 0);
          //===//
        }
        //=== INITBITS();
        hold = 0;
        bits = 0;
        //===//
        state.mode = EXLEN;
        /* falls through */
      case EXLEN:
        if (state.flags & 0x0400) {
          //=== NEEDBITS(16); */
          while (bits < 16) {
            if (have === 0) { break inf_leave; }
            have--;
            hold += input[next++] << bits;
            bits += 8;
          }
          //===//
          state.length = hold;
          if (state.head) {
            state.head.extra_len = hold;
          }
          if (state.flags & 0x0200) {
            //=== CRC2(state.check, hold);
            hbuf[0] = hold & 0xff;
            hbuf[1] = (hold >>> 8) & 0xff;
            state.check = crc32_1(state.check, hbuf, 2, 0);
            //===//
          }
          //=== INITBITS();
          hold = 0;
          bits = 0;
          //===//
        }
        else if (state.head) {
          state.head.extra = null/*Z_NULL*/;
        }
        state.mode = EXTRA;
        /* falls through */
      case EXTRA:
        if (state.flags & 0x0400) {
          copy = state.length;
          if (copy > have) { copy = have; }
          if (copy) {
            if (state.head) {
              len = state.head.extra_len - state.length;
              if (!state.head.extra) {
                // Use untyped array for more convenient processing later
                state.head.extra = new Array(state.head.extra_len);
              }
              common$e.arraySet(
                state.head.extra,
                input,
                next,
                // extra field is limited to 65536 bytes
                // - no need for additional size check
                copy,
                /*len + copy > state.head.extra_max - len ? state.head.extra_max : copy,*/
                len
              );
              //zmemcpy(state.head.extra + len, next,
              //        len + copy > state.head.extra_max ?
              //        state.head.extra_max - len : copy);
            }
            if (state.flags & 0x0200) {
              state.check = crc32_1(state.check, input, copy, next);
            }
            have -= copy;
            next += copy;
            state.length -= copy;
          }
          if (state.length) { break inf_leave; }
        }
        state.length = 0;
        state.mode = NAME;
        /* falls through */
      case NAME:
        if (state.flags & 0x0800) {
          if (have === 0) { break inf_leave; }
          copy = 0;
          do {
            // TODO: 2 or 1 bytes?
            len = input[next + copy++];
            /* use constant limit because in js we should not preallocate memory */
            if (state.head && len &&
                (state.length < 65536 /*state.head.name_max*/)) {
              state.head.name += String.fromCharCode(len);
            }
          } while (len && copy < have);

          if (state.flags & 0x0200) {
            state.check = crc32_1(state.check, input, copy, next);
          }
          have -= copy;
          next += copy;
          if (len) { break inf_leave; }
        }
        else if (state.head) {
          state.head.name = null;
        }
        state.length = 0;
        state.mode = COMMENT;
        /* falls through */
      case COMMENT:
        if (state.flags & 0x1000) {
          if (have === 0) { break inf_leave; }
          copy = 0;
          do {
            len = input[next + copy++];
            /* use constant limit because in js we should not preallocate memory */
            if (state.head && len &&
                (state.length < 65536 /*state.head.comm_max*/)) {
              state.head.comment += String.fromCharCode(len);
            }
          } while (len && copy < have);
          if (state.flags & 0x0200) {
            state.check = crc32_1(state.check, input, copy, next);
          }
          have -= copy;
          next += copy;
          if (len) { break inf_leave; }
        }
        else if (state.head) {
          state.head.comment = null;
        }
        state.mode = HCRC;
        /* falls through */
      case HCRC:
        if (state.flags & 0x0200) {
          //=== NEEDBITS(16); */
          while (bits < 16) {
            if (have === 0) { break inf_leave; }
            have--;
            hold += input[next++] << bits;
            bits += 8;
          }
          //===//
          if (hold !== (state.check & 0xffff)) {
            strm.msg = 'header crc mismatch';
            state.mode = BAD$1;
            break;
          }
          //=== INITBITS();
          hold = 0;
          bits = 0;
          //===//
        }
        if (state.head) {
          state.head.hcrc = ((state.flags >> 9) & 1);
          state.head.done = true;
        }
        strm.adler = state.check = 0;
        state.mode = TYPE$1;
        break;
      case DICTID:
        //=== NEEDBITS(32); */
        while (bits < 32) {
          if (have === 0) { break inf_leave; }
          have--;
          hold += input[next++] << bits;
          bits += 8;
        }
        //===//
        strm.adler = state.check = zswap32(hold);
        //=== INITBITS();
        hold = 0;
        bits = 0;
        //===//
        state.mode = DICT;
        /* falls through */
      case DICT:
        if (state.havedict === 0) {
          //--- RESTORE() ---
          strm.next_out = put;
          strm.avail_out = left;
          strm.next_in = next;
          strm.avail_in = have;
          state.hold = hold;
          state.bits = bits;
          //---
          return Z_NEED_DICT;
        }
        strm.adler = state.check = 1/*adler32(0L, Z_NULL, 0)*/;
        state.mode = TYPE$1;
        /* falls through */
      case TYPE$1:
        if (flush === Z_BLOCK$1 || flush === Z_TREES) { break inf_leave; }
        /* falls through */
      case TYPEDO:
        if (state.last) {
          //--- BYTEBITS() ---//
          hold >>>= bits & 7;
          bits -= bits & 7;
          //---//
          state.mode = CHECK;
          break;
        }
        //=== NEEDBITS(3); */
        while (bits < 3) {
          if (have === 0) { break inf_leave; }
          have--;
          hold += input[next++] << bits;
          bits += 8;
        }
        //===//
        state.last = (hold & 0x01)/*BITS(1)*/;
        //--- DROPBITS(1) ---//
        hold >>>= 1;
        bits -= 1;
        //---//

        switch ((hold & 0x03)/*BITS(2)*/) {
          case 0:                             /* stored block */
            //Tracev((stderr, "inflate:     stored block%s\n",
            //        state.last ? " (last)" : ""));
            state.mode = STORED;
            break;
          case 1:                             /* fixed block */
            fixedtables(state);
            //Tracev((stderr, "inflate:     fixed codes block%s\n",
            //        state.last ? " (last)" : ""));
            state.mode = LEN_;             /* decode codes */
            if (flush === Z_TREES) {
              //--- DROPBITS(2) ---//
              hold >>>= 2;
              bits -= 2;
              //---//
              break inf_leave;
            }
            break;
          case 2:                             /* dynamic block */
            //Tracev((stderr, "inflate:     dynamic codes block%s\n",
            //        state.last ? " (last)" : ""));
            state.mode = TABLE;
            break;
          case 3:
            strm.msg = 'invalid block type';
            state.mode = BAD$1;
        }
        //--- DROPBITS(2) ---//
        hold >>>= 2;
        bits -= 2;
        //---//
        break;
      case STORED:
        //--- BYTEBITS() ---// /* go to byte boundary */
        hold >>>= bits & 7;
        bits -= bits & 7;
        //---//
        //=== NEEDBITS(32); */
        while (bits < 32) {
          if (have === 0) { break inf_leave; }
          have--;
          hold += input[next++] << bits;
          bits += 8;
        }
        //===//
        if ((hold & 0xffff) !== ((hold >>> 16) ^ 0xffff)) {
          strm.msg = 'invalid stored block lengths';
          state.mode = BAD$1;
          break;
        }
        state.length = hold & 0xffff;
        //Tracev((stderr, "inflate:       stored length %u\n",
        //        state.length));
        //=== INITBITS();
        hold = 0;
        bits = 0;
        //===//
        state.mode = COPY_;
        if (flush === Z_TREES) { break inf_leave; }
        /* falls through */
      case COPY_:
        state.mode = COPY;
        /* falls through */
      case COPY:
        copy = state.length;
        if (copy) {
          if (copy > have) { copy = have; }
          if (copy > left) { copy = left; }
          if (copy === 0) { break inf_leave; }
          //--- zmemcpy(put, next, copy); ---
          common$e.arraySet(output, input, next, copy, put);
          //---//
          have -= copy;
          next += copy;
          left -= copy;
          put += copy;
          state.length -= copy;
          break;
        }
        //Tracev((stderr, "inflate:       stored end\n"));
        state.mode = TYPE$1;
        break;
      case TABLE:
        //=== NEEDBITS(14); */
        while (bits < 14) {
          if (have === 0) { break inf_leave; }
          have--;
          hold += input[next++] << bits;
          bits += 8;
        }
        //===//
        state.nlen = (hold & 0x1f)/*BITS(5)*/ + 257;
        //--- DROPBITS(5) ---//
        hold >>>= 5;
        bits -= 5;
        //---//
        state.ndist = (hold & 0x1f)/*BITS(5)*/ + 1;
        //--- DROPBITS(5) ---//
        hold >>>= 5;
        bits -= 5;
        //---//
        state.ncode = (hold & 0x0f)/*BITS(4)*/ + 4;
        //--- DROPBITS(4) ---//
        hold >>>= 4;
        bits -= 4;
        //---//
//#ifndef PKZIP_BUG_WORKAROUND
        if (state.nlen > 286 || state.ndist > 30) {
          strm.msg = 'too many length or distance symbols';
          state.mode = BAD$1;
          break;
        }
//#endif
        //Tracev((stderr, "inflate:       table sizes ok\n"));
        state.have = 0;
        state.mode = LENLENS;
        /* falls through */
      case LENLENS:
        while (state.have < state.ncode) {
          //=== NEEDBITS(3);
          while (bits < 3) {
            if (have === 0) { break inf_leave; }
            have--;
            hold += input[next++] << bits;
            bits += 8;
          }
          //===//
          state.lens[order[state.have++]] = (hold & 0x07);//BITS(3);
          //--- DROPBITS(3) ---//
          hold >>>= 3;
          bits -= 3;
          //---//
        }
        while (state.have < 19) {
          state.lens[order[state.have++]] = 0;
        }
        // We have separate tables & no pointers. 2 commented lines below not needed.
        //state.next = state.codes;
        //state.lencode = state.next;
        // Switch to use dynamic table
        state.lencode = state.lendyn;
        state.lenbits = 7;

        opts = { bits: state.lenbits };
        ret = inftrees(CODES$1, state.lens, 0, 19, state.lencode, 0, state.work, opts);
        state.lenbits = opts.bits;

        if (ret) {
          strm.msg = 'invalid code lengths set';
          state.mode = BAD$1;
          break;
        }
        //Tracev((stderr, "inflate:       code lengths ok\n"));
        state.have = 0;
        state.mode = CODELENS;
        /* falls through */
      case CODELENS:
        while (state.have < state.nlen + state.ndist) {
          for (;;) {
            here = state.lencode[hold & ((1 << state.lenbits) - 1)];/*BITS(state.lenbits)*/
            here_bits = here >>> 24;
            here_op = (here >>> 16) & 0xff;
            here_val = here & 0xffff;

            if ((here_bits) <= bits) { break; }
            //--- PULLBYTE() ---//
            if (have === 0) { break inf_leave; }
            have--;
            hold += input[next++] << bits;
            bits += 8;
            //---//
          }
          if (here_val < 16) {
            //--- DROPBITS(here.bits) ---//
            hold >>>= here_bits;
            bits -= here_bits;
            //---//
            state.lens[state.have++] = here_val;
          }
          else {
            if (here_val === 16) {
              //=== NEEDBITS(here.bits + 2);
              n = here_bits + 2;
              while (bits < n) {
                if (have === 0) { break inf_leave; }
                have--;
                hold += input[next++] << bits;
                bits += 8;
              }
              //===//
              //--- DROPBITS(here.bits) ---//
              hold >>>= here_bits;
              bits -= here_bits;
              //---//
              if (state.have === 0) {
                strm.msg = 'invalid bit length repeat';
                state.mode = BAD$1;
                break;
              }
              len = state.lens[state.have - 1];
              copy = 3 + (hold & 0x03);//BITS(2);
              //--- DROPBITS(2) ---//
              hold >>>= 2;
              bits -= 2;
              //---//
            }
            else if (here_val === 17) {
              //=== NEEDBITS(here.bits + 3);
              n = here_bits + 3;
              while (bits < n) {
                if (have === 0) { break inf_leave; }
                have--;
                hold += input[next++] << bits;
                bits += 8;
              }
              //===//
              //--- DROPBITS(here.bits) ---//
              hold >>>= here_bits;
              bits -= here_bits;
              //---//
              len = 0;
              copy = 3 + (hold & 0x07);//BITS(3);
              //--- DROPBITS(3) ---//
              hold >>>= 3;
              bits -= 3;
              //---//
            }
            else {
              //=== NEEDBITS(here.bits + 7);
              n = here_bits + 7;
              while (bits < n) {
                if (have === 0) { break inf_leave; }
                have--;
                hold += input[next++] << bits;
                bits += 8;
              }
              //===//
              //--- DROPBITS(here.bits) ---//
              hold >>>= here_bits;
              bits -= here_bits;
              //---//
              len = 0;
              copy = 11 + (hold & 0x7f);//BITS(7);
              //--- DROPBITS(7) ---//
              hold >>>= 7;
              bits -= 7;
              //---//
            }
            if (state.have + copy > state.nlen + state.ndist) {
              strm.msg = 'invalid bit length repeat';
              state.mode = BAD$1;
              break;
            }
            while (copy--) {
              state.lens[state.have++] = len;
            }
          }
        }

        /* handle error breaks in while */
        if (state.mode === BAD$1) { break; }

        /* check for end-of-block code (better have one) */
        if (state.lens[256] === 0) {
          strm.msg = 'invalid code -- missing end-of-block';
          state.mode = BAD$1;
          break;
        }

        /* build code tables -- note: do not change the lenbits or distbits
           values here (9 and 6) without reading the comments in inftrees.h
           concerning the ENOUGH constants, which depend on those values */
        state.lenbits = 9;

        opts = { bits: state.lenbits };
        ret = inftrees(LENS$1, state.lens, 0, state.nlen, state.lencode, 0, state.work, opts);
        // We have separate tables & no pointers. 2 commented lines below not needed.
        // state.next_index = opts.table_index;
        state.lenbits = opts.bits;
        // state.lencode = state.next;

        if (ret) {
          strm.msg = 'invalid literal/lengths set';
          state.mode = BAD$1;
          break;
        }

        state.distbits = 6;
        //state.distcode.copy(state.codes);
        // Switch to use dynamic table
        state.distcode = state.distdyn;
        opts = { bits: state.distbits };
        ret = inftrees(DISTS$1, state.lens, state.nlen, state.ndist, state.distcode, 0, state.work, opts);
        // We have separate tables & no pointers. 2 commented lines below not needed.
        // state.next_index = opts.table_index;
        state.distbits = opts.bits;
        // state.distcode = state.next;

        if (ret) {
          strm.msg = 'invalid distances set';
          state.mode = BAD$1;
          break;
        }
        //Tracev((stderr, 'inflate:       codes ok\n'));
        state.mode = LEN_;
        if (flush === Z_TREES) { break inf_leave; }
        /* falls through */
      case LEN_:
        state.mode = LEN;
        /* falls through */
      case LEN:
        if (have >= 6 && left >= 258) {
          //--- RESTORE() ---
          strm.next_out = put;
          strm.avail_out = left;
          strm.next_in = next;
          strm.avail_in = have;
          state.hold = hold;
          state.bits = bits;
          //---
          inffast(strm, _out);
          //--- LOAD() ---
          put = strm.next_out;
          output = strm.output;
          left = strm.avail_out;
          next = strm.next_in;
          input = strm.input;
          have = strm.avail_in;
          hold = state.hold;
          bits = state.bits;
          //---

          if (state.mode === TYPE$1) {
            state.back = -1;
          }
          break;
        }
        state.back = 0;
        for (;;) {
          here = state.lencode[hold & ((1 << state.lenbits) - 1)];  /*BITS(state.lenbits)*/
          here_bits = here >>> 24;
          here_op = (here >>> 16) & 0xff;
          here_val = here & 0xffff;

          if (here_bits <= bits) { break; }
          //--- PULLBYTE() ---//
          if (have === 0) { break inf_leave; }
          have--;
          hold += input[next++] << bits;
          bits += 8;
          //---//
        }
        if (here_op && (here_op & 0xf0) === 0) {
          last_bits = here_bits;
          last_op = here_op;
          last_val = here_val;
          for (;;) {
            here = state.lencode[last_val +
                    ((hold & ((1 << (last_bits + last_op)) - 1))/*BITS(last.bits + last.op)*/ >> last_bits)];
            here_bits = here >>> 24;
            here_op = (here >>> 16) & 0xff;
            here_val = here & 0xffff;

            if ((last_bits + here_bits) <= bits) { break; }
            //--- PULLBYTE() ---//
            if (have === 0) { break inf_leave; }
            have--;
            hold += input[next++] << bits;
            bits += 8;
            //---//
          }
          //--- DROPBITS(last.bits) ---//
          hold >>>= last_bits;
          bits -= last_bits;
          //---//
          state.back += last_bits;
        }
        //--- DROPBITS(here.bits) ---//
        hold >>>= here_bits;
        bits -= here_bits;
        //---//
        state.back += here_bits;
        state.length = here_val;
        if (here_op === 0) {
          //Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ?
          //        "inflate:         literal '%c'\n" :
          //        "inflate:         literal 0x%02x\n", here.val));
          state.mode = LIT;
          break;
        }
        if (here_op & 32) {
          //Tracevv((stderr, "inflate:         end of block\n"));
          state.back = -1;
          state.mode = TYPE$1;
          break;
        }
        if (here_op & 64) {
          strm.msg = 'invalid literal/length code';
          state.mode = BAD$1;
          break;
        }
        state.extra = here_op & 15;
        state.mode = LENEXT;
        /* falls through */
      case LENEXT:
        if (state.extra) {
          //=== NEEDBITS(state.extra);
          n = state.extra;
          while (bits < n) {
            if (have === 0) { break inf_leave; }
            have--;
            hold += input[next++] << bits;
            bits += 8;
          }
          //===//
          state.length += hold & ((1 << state.extra) - 1)/*BITS(state.extra)*/;
          //--- DROPBITS(state.extra) ---//
          hold >>>= state.extra;
          bits -= state.extra;
          //---//
          state.back += state.extra;
        }
        //Tracevv((stderr, "inflate:         length %u\n", state.length));
        state.was = state.length;
        state.mode = DIST;
        /* falls through */
      case DIST:
        for (;;) {
          here = state.distcode[hold & ((1 << state.distbits) - 1)];/*BITS(state.distbits)*/
          here_bits = here >>> 24;
          here_op = (here >>> 16) & 0xff;
          here_val = here & 0xffff;

          if ((here_bits) <= bits) { break; }
          //--- PULLBYTE() ---//
          if (have === 0) { break inf_leave; }
          have--;
          hold += input[next++] << bits;
          bits += 8;
          //---//
        }
        if ((here_op & 0xf0) === 0) {
          last_bits = here_bits;
          last_op = here_op;
          last_val = here_val;
          for (;;) {
            here = state.distcode[last_val +
                    ((hold & ((1 << (last_bits + last_op)) - 1))/*BITS(last.bits + last.op)*/ >> last_bits)];
            here_bits = here >>> 24;
            here_op = (here >>> 16) & 0xff;
            here_val = here & 0xffff;

            if ((last_bits + here_bits) <= bits) { break; }
            //--- PULLBYTE() ---//
            if (have === 0) { break inf_leave; }
            have--;
            hold += input[next++] << bits;
            bits += 8;
            //---//
          }
          //--- DROPBITS(last.bits) ---//
          hold >>>= last_bits;
          bits -= last_bits;
          //---//
          state.back += last_bits;
        }
        //--- DROPBITS(here.bits) ---//
        hold >>>= here_bits;
        bits -= here_bits;
        //---//
        state.back += here_bits;
        if (here_op & 64) {
          strm.msg = 'invalid distance code';
          state.mode = BAD$1;
          break;
        }
        state.offset = here_val;
        state.extra = (here_op) & 15;
        state.mode = DISTEXT;
        /* falls through */
      case DISTEXT:
        if (state.extra) {
          //=== NEEDBITS(state.extra);
          n = state.extra;
          while (bits < n) {
            if (have === 0) { break inf_leave; }
            have--;
            hold += input[next++] << bits;
            bits += 8;
          }
          //===//
          state.offset += hold & ((1 << state.extra) - 1)/*BITS(state.extra)*/;
          //--- DROPBITS(state.extra) ---//
          hold >>>= state.extra;
          bits -= state.extra;
          //---//
          state.back += state.extra;
        }
//#ifdef INFLATE_STRICT
        if (state.offset > state.dmax) {
          strm.msg = 'invalid distance too far back';
          state.mode = BAD$1;
          break;
        }
//#endif
        //Tracevv((stderr, "inflate:         distance %u\n", state.offset));
        state.mode = MATCH;
        /* falls through */
      case MATCH:
        if (left === 0) { break inf_leave; }
        copy = _out - left;
        if (state.offset > copy) {         /* copy from window */
          copy = state.offset - copy;
          if (copy > state.whave) {
            if (state.sane) {
              strm.msg = 'invalid distance too far back';
              state.mode = BAD$1;
              break;
            }
// (!) This block is disabled in zlib defaults,
// don't enable it for binary compatibility
//#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR
//          Trace((stderr, "inflate.c too far\n"));
//          copy -= state.whave;
//          if (copy > state.length) { copy = state.length; }
//          if (copy > left) { copy = left; }
//          left -= copy;
//          state.length -= copy;
//          do {
//            output[put++] = 0;
//          } while (--copy);
//          if (state.length === 0) { state.mode = LEN; }
//          break;
//#endif
          }
          if (copy > state.wnext) {
            copy -= state.wnext;
            from = state.wsize - copy;
          }
          else {
            from = state.wnext - copy;
          }
          if (copy > state.length) { copy = state.length; }
          from_source = state.window;
        }
        else {                              /* copy from output */
          from_source = output;
          from = put - state.offset;
          copy = state.length;
        }
        if (copy > left) { copy = left; }
        left -= copy;
        state.length -= copy;
        do {
          output[put++] = from_source[from++];
        } while (--copy);
        if (state.length === 0) { state.mode = LEN; }
        break;
      case LIT:
        if (left === 0) { break inf_leave; }
        output[put++] = state.length;
        left--;
        state.mode = LEN;
        break;
      case CHECK:
        if (state.wrap) {
          //=== NEEDBITS(32);
          while (bits < 32) {
            if (have === 0) { break inf_leave; }
            have--;
            // Use '|' instead of '+' to make sure that result is signed
            hold |= input[next++] << bits;
            bits += 8;
          }
          //===//
          _out -= left;
          strm.total_out += _out;
          state.total += _out;
          if (_out) {
            strm.adler = state.check =
                /*UPDATE(state.check, put - _out, _out);*/
                (state.flags ? crc32_1(state.check, output, _out, put - _out) : adler32_1(state.check, output, _out, put - _out));

          }
          _out = left;
          // NB: crc32 stored as signed 32-bit int, zswap32 returns signed too
          if ((state.flags ? hold : zswap32(hold)) !== state.check) {
            strm.msg = 'incorrect data check';
            state.mode = BAD$1;
            break;
          }
          //=== INITBITS();
          hold = 0;
          bits = 0;
          //===//
          //Tracev((stderr, "inflate:   check matches trailer\n"));
        }
        state.mode = LENGTH;
        /* falls through */
      case LENGTH:
        if (state.wrap && state.flags) {
          //=== NEEDBITS(32);
          while (bits < 32) {
            if (have === 0) { break inf_leave; }
            have--;
            hold += input[next++] << bits;
            bits += 8;
          }
          //===//
          if (hold !== (state.total & 0xffffffff)) {
            strm.msg = 'incorrect length check';
            state.mode = BAD$1;
            break;
          }
          //=== INITBITS();
          hold = 0;
          bits = 0;
          //===//
          //Tracev((stderr, "inflate:   length matches trailer\n"));
        }
        state.mode = DONE;
        /* falls through */
      case DONE:
        ret = Z_STREAM_END$2;
        break inf_leave;
      case BAD$1:
        ret = Z_DATA_ERROR$1;
        break inf_leave;
      case MEM:
        return Z_MEM_ERROR;
      case SYNC:
        /* falls through */
      default:
        return Z_STREAM_ERROR$1;
    }
  }

  // inf_leave <- here is real place for "goto inf_leave", emulated via "break inf_leave"

  /*
     Return from inflate(), updating the total counts and the check value.
     If there was no progress during the inflate() call, return a buffer
     error.  Call updatewindow() to create and/or update the window state.
     Note: a memory error from inflate() is non-recoverable.
   */

  //--- RESTORE() ---
  strm.next_out = put;
  strm.avail_out = left;
  strm.next_in = next;
  strm.avail_in = have;
  state.hold = hold;
  state.bits = bits;
  //---

  if (state.wsize || (_out !== strm.avail_out && state.mode < BAD$1 &&
                      (state.mode < CHECK || flush !== Z_FINISH$2))) {
    if (updatewindow(strm, strm.output, strm.next_out, _out - strm.avail_out)) ;
  }
  _in -= strm.avail_in;
  _out -= strm.avail_out;
  strm.total_in += _in;
  strm.total_out += _out;
  state.total += _out;
  if (state.wrap && _out) {
    strm.adler = state.check = /*UPDATE(state.check, strm.next_out - _out, _out);*/
      (state.flags ? crc32_1(state.check, output, _out, strm.next_out - _out) : adler32_1(state.check, output, _out, strm.next_out - _out));
  }
  strm.data_type = state.bits + (state.last ? 64 : 0) +
                    (state.mode === TYPE$1 ? 128 : 0) +
                    (state.mode === LEN_ || state.mode === COPY_ ? 256 : 0);
  if (((_in === 0 && _out === 0) || flush === Z_FINISH$2) && ret === Z_OK$2) {
    ret = Z_BUF_ERROR$1;
  }
  return ret;
}

function inflateEnd(strm) {

  if (!strm || !strm.state /*|| strm->zfree == (free_func)0*/) {
    return Z_STREAM_ERROR$1;
  }

  var state = strm.state;
  if (state.window) {
    state.window = null;
  }
  strm.state = null;
  return Z_OK$2;
}

function inflateGetHeader(strm, head) {
  var state;

  /* check state */
  if (!strm || !strm.state) { return Z_STREAM_ERROR$1; }
  state = strm.state;
  if ((state.wrap & 2) === 0) { return Z_STREAM_ERROR$1; }

  /* save header structure */
  state.head = head;
  head.done = false;
  return Z_OK$2;
}

function inflateSetDictionary(strm, dictionary) {
  var dictLength = dictionary.length;

  var state;
  var dictid;
  var ret;

  /* check state */
  if (!strm /* == Z_NULL */ || !strm.state /* == Z_NULL */) { return Z_STREAM_ERROR$1; }
  state = strm.state;

  if (state.wrap !== 0 && state.mode !== DICT) {
    return Z_STREAM_ERROR$1;
  }

  /* check for correct dictionary identifier */
  if (state.mode === DICT) {
    dictid = 1; /* adler32(0, null, 0)*/
    /* dictid = adler32(dictid, dictionary, dictLength); */
    dictid = adler32_1(dictid, dictionary, dictLength, 0);
    if (dictid !== state.check) {
      return Z_DATA_ERROR$1;
    }
  }
  /* copy dictionary to window using updatewindow(), which will amend the
   existing dictionary if appropriate */
  ret = updatewindow(strm, dictionary, dictLength, dictLength);
  if (ret) {
    state.mode = MEM;
    return Z_MEM_ERROR;
  }
  state.havedict = 1;
  // Tracev((stderr, "inflate:   dictionary set\n"));
  return Z_OK$2;
}

var inflateReset_1 = inflateReset;
var inflateReset2_1 = inflateReset2;
var inflateResetKeep_1 = inflateResetKeep;
var inflateInit_1 = inflateInit;
var inflateInit2_1 = inflateInit2;
var inflate_2 = inflate;
var inflateEnd_1 = inflateEnd;
var inflateGetHeader_1 = inflateGetHeader;
var inflateSetDictionary_1 = inflateSetDictionary;
var inflateInfo = 'pako inflate (from Nodeca project)';

/* Not implemented
exports.inflateCopy = inflateCopy;
exports.inflateGetDictionary = inflateGetDictionary;
exports.inflateMark = inflateMark;
exports.inflatePrime = inflatePrime;
exports.inflateSync = inflateSync;
exports.inflateSyncPoint = inflateSyncPoint;
exports.inflateUndermine = inflateUndermine;
*/

var inflate_1 = {
	inflateReset: inflateReset_1,
	inflateReset2: inflateReset2_1,
	inflateResetKeep: inflateResetKeep_1,
	inflateInit: inflateInit_1,
	inflateInit2: inflateInit2_1,
	inflate: inflate_2,
	inflateEnd: inflateEnd_1,
	inflateGetHeader: inflateGetHeader_1,
	inflateSetDictionary: inflateSetDictionary_1,
	inflateInfo: inflateInfo
};

// (C) 1995-2013 Jean-loup Gailly and Mark Adler
// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented; you must not
//   claim that you wrote the original software. If you use this software
//   in a product, an acknowledgment in the product documentation would be
//   appreciated but is not required.
// 2. Altered source versions must be plainly marked as such, and must not be
//   misrepresented as being the original software.
// 3. This notice may not be removed or altered from any source distribution.

var constants$1 = {

  /* Allowed flush values; see deflate() and inflate() below for details */
  Z_NO_FLUSH:         0,
  Z_PARTIAL_FLUSH:    1,
  Z_SYNC_FLUSH:       2,
  Z_FULL_FLUSH:       3,
  Z_FINISH:           4,
  Z_BLOCK:            5,
  Z_TREES:            6,

  /* Return codes for the compression/decompression functions. Negative values
  * are errors, positive values are used for special but normal events.
  */
  Z_OK:               0,
  Z_STREAM_END:       1,
  Z_NEED_DICT:        2,
  Z_ERRNO:           -1,
  Z_STREAM_ERROR:    -2,
  Z_DATA_ERROR:      -3,
  //Z_MEM_ERROR:     -4,
  Z_BUF_ERROR:       -5,
  //Z_VERSION_ERROR: -6,

  /* compression levels */
  Z_NO_COMPRESSION:         0,
  Z_BEST_SPEED:             1,
  Z_BEST_COMPRESSION:       9,
  Z_DEFAULT_COMPRESSION:   -1,


  Z_FILTERED:               1,
  Z_HUFFMAN_ONLY:           2,
  Z_RLE:                    3,
  Z_FIXED:                  4,
  Z_DEFAULT_STRATEGY:       0,

  /* Possible values of the data_type field (though see inflate()) */
  Z_BINARY:                 0,
  Z_TEXT:                   1,
  //Z_ASCII:                1, // = Z_TEXT (deprecated)
  Z_UNKNOWN:                2,

  /* The deflate compression method */
  Z_DEFLATED:               8
  //Z_NULL:                 null // Use -1 or null inline, depending on var type
};

// (C) 1995-2013 Jean-loup Gailly and Mark Adler
// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented; you must not
//   claim that you wrote the original software. If you use this software
//   in a product, an acknowledgment in the product documentation would be
//   appreciated but is not required.
// 2. Altered source versions must be plainly marked as such, and must not be
//   misrepresented as being the original software.
// 3. This notice may not be removed or altered from any source distribution.

function GZheader() {
  /* true if compressed data believed to be text */
  this.text       = 0;
  /* modification time */
  this.time       = 0;
  /* extra flags (not used when writing a gzip file) */
  this.xflags     = 0;
  /* operating system */
  this.os         = 0;
  /* pointer to extra field or Z_NULL if none */
  this.extra      = null;
  /* extra field length (valid if extra != Z_NULL) */
  this.extra_len  = 0; // Actually, we don't need it in JS,
                       // but leave for few code modifications

  //
  // Setup limits is not necessary because in js we should not preallocate memory
  // for inflate use constant limit in 65536 bytes
  //

  /* space at extra (only when reading header) */
  // this.extra_max  = 0;
  /* pointer to zero-terminated file name or Z_NULL */
  this.name       = '';
  /* space at name (only when reading header) */
  // this.name_max   = 0;
  /* pointer to zero-terminated comment or Z_NULL */
  this.comment    = '';
  /* space at comment (only when reading header) */
  // this.comm_max   = 0;
  /* true if there was or will be a header crc */
  this.hcrc       = 0;
  /* true when done reading gzip header (not used when writing a gzip file) */
  this.done       = false;
}

var gzheader = GZheader;

var toString$1 = Object.prototype.toString;

/**
 * class Inflate
 *
 * Generic JS-style wrapper for zlib calls. If you don't need
 * streaming behaviour - use more simple functions: [[inflate]]
 * and [[inflateRaw]].
 **/

/* internal
 * inflate.chunks -> Array
 *
 * Chunks of output data, if [[Inflate#onData]] not overridden.
 **/

/**
 * Inflate.result -> Uint8Array|Array|String
 *
 * Uncompressed result, generated by default [[Inflate#onData]]
 * and [[Inflate#onEnd]] handlers. Filled after you push last chunk
 * (call [[Inflate#push]] with `Z_FINISH` / `true` param) or if you
 * push a chunk with explicit flush (call [[Inflate#push]] with
 * `Z_SYNC_FLUSH` param).
 **/

/**
 * Inflate.err -> Number
 *
 * Error code after inflate finished. 0 (Z_OK) on success.
 * Should be checked if broken data possible.
 **/

/**
 * Inflate.msg -> String
 *
 * Error message, if [[Inflate.err]] != 0
 **/


/**
 * new Inflate(options)
 * - options (Object): zlib inflate options.
 *
 * Creates new inflator instance with specified params. Throws exception
 * on bad params. Supported options:
 *
 * - `windowBits`
 * - `dictionary`
 *
 * [http://zlib.net/manual.html#Advanced](http://zlib.net/manual.html#Advanced)
 * for more information on these.
 *
 * Additional options, for internal needs:
 *
 * - `chunkSize` - size of generated data chunks (16K by default)
 * - `raw` (Boolean) - do raw inflate
 * - `to` (String) - if equal to 'string', then result will be converted
 *   from utf8 to utf16 (javascript) string. When string output requested,
 *   chunk length can differ from `chunkSize`, depending on content.
 *
 * By default, when no options set, autodetect deflate/gzip data format via
 * wrapper header.
 *
 * ##### Example:
 *
 * ```javascript
 * var pako = require('pako')
 *   , chunk1 = Uint8Array([1,2,3,4,5,6,7,8,9])
 *   , chunk2 = Uint8Array([10,11,12,13,14,15,16,17,18,19]);
 *
 * var inflate = new pako.Inflate({ level: 3});
 *
 * inflate.push(chunk1, false);
 * inflate.push(chunk2, true);  // true -> last chunk
 *
 * if (inflate.err) { throw new Error(inflate.err); }
 *
 * console.log(inflate.result);
 * ```
 **/
function Inflate(options) {
  if (!(this instanceof Inflate)) return new Inflate(options);

  this.options = common$e.assign({
    chunkSize: 16384,
    windowBits: 0,
    to: ''
  }, options || {});

  var opt = this.options;

  // Force window size for `raw` data, if not set directly,
  // because we have no header for autodetect.
  if (opt.raw && (opt.windowBits >= 0) && (opt.windowBits < 16)) {
    opt.windowBits = -opt.windowBits;
    if (opt.windowBits === 0) { opt.windowBits = -15; }
  }

  // If `windowBits` not defined (and mode not raw) - set autodetect flag for gzip/deflate
  if ((opt.windowBits >= 0) && (opt.windowBits < 16) &&
      !(options && options.windowBits)) {
    opt.windowBits += 32;
  }

  // Gzip header has no info about windows size, we can do autodetect only
  // for deflate. So, if window size not set, force it to max when gzip possible
  if ((opt.windowBits > 15) && (opt.windowBits < 48)) {
    // bit 3 (16) -> gzipped data
    // bit 4 (32) -> autodetect gzip/deflate
    if ((opt.windowBits & 15) === 0) {
      opt.windowBits |= 15;
    }
  }

  this.err    = 0;      // error code, if happens (0 = Z_OK)
  this.msg    = '';     // error message
  this.ended  = false;  // used to avoid multiple onEnd() calls
  this.chunks = [];     // chunks of compressed data

  this.strm   = new zstream();
  this.strm.avail_out = 0;

  var status  = inflate_1.inflateInit2(
    this.strm,
    opt.windowBits
  );

  if (status !== constants$1.Z_OK) {
    throw new Error(messages[status]);
  }

  this.header = new gzheader();

  inflate_1.inflateGetHeader(this.strm, this.header);

  // Setup dictionary
  if (opt.dictionary) {
    // Convert data if needed
    if (typeof opt.dictionary === 'string') {
      opt.dictionary = strings.string2buf(opt.dictionary);
    } else if (toString$1.call(opt.dictionary) === '[object ArrayBuffer]') {
      opt.dictionary = new Uint8Array(opt.dictionary);
    }
    if (opt.raw) { //In raw mode we need to set the dictionary early
      status = inflate_1.inflateSetDictionary(this.strm, opt.dictionary);
      if (status !== constants$1.Z_OK) {
        throw new Error(messages[status]);
      }
    }
  }
}

/**
 * Inflate#push(data[, mode]) -> Boolean
 * - data (Uint8Array|Array|ArrayBuffer|String): input data
 * - mode (Number|Boolean): 0..6 for corresponding Z_NO_FLUSH..Z_TREE modes.
 *   See constants. Skipped or `false` means Z_NO_FLUSH, `true` means Z_FINISH.
 *
 * Sends input data to inflate pipe, generating [[Inflate#onData]] calls with
 * new output chunks. Returns `true` on success. The last data block must have
 * mode Z_FINISH (or `true`). That will flush internal pending buffers and call
 * [[Inflate#onEnd]]. For interim explicit flushes (without ending the stream) you
 * can use mode Z_SYNC_FLUSH, keeping the decompression context.
 *
 * On fail call [[Inflate#onEnd]] with error code and return false.
 *
 * We strongly recommend to use `Uint8Array` on input for best speed (output
 * format is detected automatically). Also, don't skip last param and always
 * use the same type in your code (boolean or number). That will improve JS speed.
 *
 * For regular `Array`-s make sure all elements are [0..255].
 *
 * ##### Example
 *
 * ```javascript
 * push(chunk, false); // push one of data chunks
 * ...
 * push(chunk, true);  // push last chunk
 * ```
 **/
Inflate.prototype.push = function (data, mode) {
  var strm = this.strm;
  var chunkSize = this.options.chunkSize;
  var dictionary = this.options.dictionary;
  var status, _mode;
  var next_out_utf8, tail, utf8str;

  // Flag to properly process Z_BUF_ERROR on testing inflate call
  // when we check that all output data was flushed.
  var allowBufError = false;

  if (this.ended) { return false; }
  _mode = (mode === ~~mode) ? mode : ((mode === true) ? constants$1.Z_FINISH : constants$1.Z_NO_FLUSH);

  // Convert data if needed
  if (typeof data === 'string') {
    // Only binary strings can be decompressed on practice
    strm.input = strings.binstring2buf(data);
  } else if (toString$1.call(data) === '[object ArrayBuffer]') {
    strm.input = new Uint8Array(data);
  } else {
    strm.input = data;
  }

  strm.next_in = 0;
  strm.avail_in = strm.input.length;

  do {
    if (strm.avail_out === 0) {
      strm.output = new common$e.Buf8(chunkSize);
      strm.next_out = 0;
      strm.avail_out = chunkSize;
    }

    status = inflate_1.inflate(strm, constants$1.Z_NO_FLUSH);    /* no bad return value */

    if (status === constants$1.Z_NEED_DICT && dictionary) {
      status = inflate_1.inflateSetDictionary(this.strm, dictionary);
    }

    if (status === constants$1.Z_BUF_ERROR && allowBufError === true) {
      status = constants$1.Z_OK;
      allowBufError = false;
    }

    if (status !== constants$1.Z_STREAM_END && status !== constants$1.Z_OK) {
      this.onEnd(status);
      this.ended = true;
      return false;
    }

    if (strm.next_out) {
      if (strm.avail_out === 0 || status === constants$1.Z_STREAM_END || (strm.avail_in === 0 && (_mode === constants$1.Z_FINISH || _mode === constants$1.Z_SYNC_FLUSH))) {

        if (this.options.to === 'string') {

          next_out_utf8 = strings.utf8border(strm.output, strm.next_out);

          tail = strm.next_out - next_out_utf8;
          utf8str = strings.buf2string(strm.output, next_out_utf8);

          // move tail
          strm.next_out = tail;
          strm.avail_out = chunkSize - tail;
          if (tail) { common$e.arraySet(strm.output, strm.output, next_out_utf8, tail, 0); }

          this.onData(utf8str);

        } else {
          this.onData(common$e.shrinkBuf(strm.output, strm.next_out));
        }
      }
    }

    // When no more input data, we should check that internal inflate buffers
    // are flushed. The only way to do it when avail_out = 0 - run one more
    // inflate pass. But if output data not exists, inflate return Z_BUF_ERROR.
    // Here we set flag to process this error properly.
    //
    // NOTE. Deflate does not return error in this case and does not needs such
    // logic.
    if (strm.avail_in === 0 && strm.avail_out === 0) {
      allowBufError = true;
    }

  } while ((strm.avail_in > 0 || strm.avail_out === 0) && status !== constants$1.Z_STREAM_END);

  if (status === constants$1.Z_STREAM_END) {
    _mode = constants$1.Z_FINISH;
  }

  // Finalize on the last chunk.
  if (_mode === constants$1.Z_FINISH) {
    status = inflate_1.inflateEnd(this.strm);
    this.onEnd(status);
    this.ended = true;
    return status === constants$1.Z_OK;
  }

  // callback interim results if Z_SYNC_FLUSH.
  if (_mode === constants$1.Z_SYNC_FLUSH) {
    this.onEnd(constants$1.Z_OK);
    strm.avail_out = 0;
    return true;
  }

  return true;
};


/**
 * Inflate#onData(chunk) -> Void
 * - chunk (Uint8Array|Array|String): output data. Type of array depends
 *   on js engine support. When string output requested, each chunk
 *   will be string.
 *
 * By default, stores data blocks in `chunks[]` property and glue
 * those in `onEnd`. Override this handler, if you need another behaviour.
 **/
Inflate.prototype.onData = function (chunk) {
  this.chunks.push(chunk);
};


/**
 * Inflate#onEnd(status) -> Void
 * - status (Number): inflate status. 0 (Z_OK) on success,
 *   other if not.
 *
 * Called either after you tell inflate that the input stream is
 * complete (Z_FINISH) or should be flushed (Z_SYNC_FLUSH)
 * or if an error happened. By default - join collected chunks,
 * free memory and fill `results` / `err` properties.
 **/
Inflate.prototype.onEnd = function (status) {
  // On success - join
  if (status === constants$1.Z_OK) {
    if (this.options.to === 'string') {
      // Glue & convert here, until we teach pako to send
      // utf8 aligned strings to onData
      this.result = this.chunks.join('');
    } else {
      this.result = common$e.flattenChunks(this.chunks);
    }
  }
  this.chunks = [];
  this.err = status;
  this.msg = this.strm.msg;
};


/**
 * inflate(data[, options]) -> Uint8Array|Array|String
 * - data (Uint8Array|Array|String): input data to decompress.
 * - options (Object): zlib inflate options.
 *
 * Decompress `data` with inflate/ungzip and `options`. Autodetect
 * format via wrapper header by default. That's why we don't provide
 * separate `ungzip` method.
 *
 * Supported options are:
 *
 * - windowBits
 *
 * [http://zlib.net/manual.html#Advanced](http://zlib.net/manual.html#Advanced)
 * for more information.
 *
 * Sugar (options):
 *
 * - `raw` (Boolean) - say that we work with raw stream, if you don't wish to specify
 *   negative windowBits implicitly.
 * - `to` (String) - if equal to 'string', then result will be converted
 *   from utf8 to utf16 (javascript) string. When string output requested,
 *   chunk length can differ from `chunkSize`, depending on content.
 *
 *
 * ##### Example:
 *
 * ```javascript
 * var pako = require('pako')
 *   , input = pako.deflate([1,2,3,4,5,6,7,8,9])
 *   , output;
 *
 * try {
 *   output = pako.inflate(input);
 * } catch (err)
 *   console.log(err);
 * }
 * ```
 **/
function inflate$1(input, options) {
  var inflator = new Inflate(options);

  inflator.push(input, true);

  // That will never happens, if you don't cheat with options :)
  if (inflator.err) { throw inflator.msg || messages[inflator.err]; }

  return inflator.result;
}


/**
 * inflateRaw(data[, options]) -> Uint8Array|Array|String
 * - data (Uint8Array|Array|String): input data to decompress.
 * - options (Object): zlib inflate options.
 *
 * The same as [[inflate]], but creates raw data, without wrapper
 * (header and adler32 crc).
 **/
function inflateRaw(input, options) {
  options = options || {};
  options.raw = true;
  return inflate$1(input, options);
}


/**
 * ungzip(data[, options]) -> Uint8Array|Array|String
 * - data (Uint8Array|Array|String): input data to decompress.
 * - options (Object): zlib inflate options.
 *
 * Just shortcut to [[inflate]], because it autodetects format
 * by header.content. Done for convenience.
 **/


var Inflate_1 = Inflate;
var inflate_2$1 = inflate$1;
var inflateRaw_1 = inflateRaw;
var ungzip  = inflate$1;

var inflate_1$1 = {
	Inflate: Inflate_1,
	inflate: inflate_2$1,
	inflateRaw: inflateRaw_1,
	ungzip: ungzip
};

var assign$1    = common$e.assign;





var pako = {};

assign$1(pako, deflate_1$1, inflate_1$1, constants$1);

var pako_1 = pako;

var legacy_trace_viewer = createCommonjsModule(function (module, exports) {
// 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.
Object.defineProperty(exports, "__esModule", { value: true });
exports.openBufferWithLegacyTraceViewer = exports.openFileWithLegacyTraceViewer = exports.isLegacyTrace = void 0;






const CTRACE_HEADER = 'TRACE:\n';
function isCtrace(file) {
    return tslib.__awaiter(this, void 0, void 0, function* () {
        const fileName = file.name.toLowerCase();
        if (fileName.endsWith('.ctrace')) {
            return true;
        }
        // .ctrace files sometimes end with .txt. We can detect these via
        // the presence of TRACE: near the top of the file.
        if (fileName.endsWith('.txt')) {
            const header = yield readText(file.slice(0, 128));
            if (header.includes(CTRACE_HEADER)) {
                return true;
            }
        }
        return false;
    });
}
function readText(blob) {
    return new Promise((resolve, reject) => {
        const reader = new FileReader();
        reader.onload = () => {
            if (typeof reader.result === 'string') {
                return resolve(reader.result);
            }
        };
        reader.onerror = err => {
            reject(err);
        };
        reader.readAsText(blob);
    });
}
function isLegacyTrace(file) {
    return tslib.__awaiter(this, void 0, void 0, function* () {
        const fileName = file.name.toLowerCase();
        if (fileName.endsWith('.json') || fileName.endsWith('.json.gz') ||
            fileName.endsWith('.zip') || fileName.endsWith('.html')) {
            return true;
        }
        if (yield isCtrace(file)) {
            return true;
        }
        // Sometimes systrace formatted traces end with '.trace'. This is a
        // little generic to assume all such traces are systrace format though
        // so we read the beginning of the file and check to see if is has the
        // systrace header (several comment lines):
        if (fileName.endsWith('.trace')) {
            const header = yield readText(file.slice(0, 512));
            const lines = header.split('\n');
            let commentCount = 0;
            for (const line of lines) {
                if (line.startsWith('#')) {
                    commentCount++;
                }
            }
            if (commentCount > 5) {
                return true;
            }
        }
        return false;
    });
}
exports.isLegacyTrace = isLegacyTrace;
function openFileWithLegacyTraceViewer(file) {
    return tslib.__awaiter(this, void 0, void 0, function* () {
        const reader = new FileReader();
        reader.onload = () => {
            if (reader.result instanceof ArrayBuffer) {
                return openBufferWithLegacyTraceViewer(file.name, reader.result, reader.result.byteLength);
            }
            else {
                const str = reader.result;
                return openBufferWithLegacyTraceViewer(file.name, str, str.length);
            }
        };
        reader.onerror = err => {
            console.error(err);
        };
        if (file.name.endsWith('.gz') || file.name.endsWith('.zip') ||
            (yield isCtrace(file))) {
            reader.readAsArrayBuffer(file);
        }
        else {
            reader.readAsText(file);
        }
    });
}
exports.openFileWithLegacyTraceViewer = openFileWithLegacyTraceViewer;
function openBufferWithLegacyTraceViewer(name, data, size) {
    if (data instanceof ArrayBuffer) {
        logging.assertTrue(size <= data.byteLength);
        if (size !== data.byteLength) {
            data = data.slice(0, size);
        }
        // Handle .ctrace files.
        const enc = new TextDecoder('utf-8');
        const header = enc.decode(data.slice(0, 128));
        if (header.includes(CTRACE_HEADER)) {
            const offset = header.indexOf(CTRACE_HEADER) + CTRACE_HEADER.length;
            data = pako_1.inflate(new Uint8Array(data.slice(offset)), { to: 'string' });
        }
    }
    // The location.pathname mangling is to make this code work also when hosted
    // in a non-root sub-directory, for the case of CI artifacts.
    const catapultUrl = globals$1.globals.root + 'assets/catapult_trace_viewer.html';
    const newWin = window.open(catapultUrl);
    if (newWin) {
        // Popup succeedeed.
        newWin.addEventListener('load', (e) => {
            const doc = e.target;
            const ctl = doc.querySelector('x-profiling-view');
            ctl.setActiveTrace(name, data);
        });
        return;
    }
    // Popup blocker detected.
    modal.showModal({
        title: 'Open trace in the legacy Catapult Trace Viewer',
        content: mithril('div', mithril('div', 'You are seeing this interstitial because popups are blocked'), mithril('div', 'Enable popups to skip this dialog next time.')),
        buttons: [{
                text: 'Open legacy UI',
                primary: true,
                id: 'open_legacy',
                action: () => openBufferWithLegacyTraceViewer(name, data, size),
            }],
    });
}
exports.openBufferWithLegacyTraceViewer = openBufferWithLegacyTraceViewer;

});

var trace_attrs = createCommonjsModule(function (module, exports) {
// Copyright (C) 2020 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.
Object.defineProperty(exports, "__esModule", { value: true });
exports.isDownloadable = exports.isShareable = void 0;

function isShareable() {
    return (globals$1.globals.isInternalUser && isDownloadable());
}
exports.isShareable = isShareable;
function isDownloadable() {
    if (globals$1.globals.frontendLocalState.localOnlyMode)
        return false;
    const engine = Object.values(globals$1.globals.state.engines)[0];
    if (engine && engine.source.type === 'HTTP_RPC')
        return false;
    return true;
}
exports.isDownloadable = isDownloadable;

});

var sidebar = createCommonjsModule(function (module, exports) {
// 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.
Object.defineProperty(exports, "__esModule", { value: true });
exports.Sidebar = void 0;














const ALL_PROCESSES_QUERY = 'select name, pid from process order by name;';
const CPU_TIME_FOR_PROCESSES = `
select
  process.name,
  sum(dur)/1e9 as cpu_sec
from sched
join thread using(utid)
join process using(upid)
group by upid
order by cpu_sec desc
limit 100;`;
const CYCLES_PER_P_STATE_PER_CPU = `
select
  cpu,
  freq,
  dur,
  sum(dur * freq)/1e6 as mcycles
from (
  select
    cpu,
    value as freq,
    lead(ts) over (partition by cpu order by ts) - ts as dur
  from counter
  inner join cpu_counter_track on counter.track_id = cpu_counter_track.id
  where name = 'cpufreq'
) group by cpu, freq
order by mcycles desc limit 32;`;
const CPU_TIME_BY_CPU_BY_PROCESS = `
select
  process.name as process,
  thread.name as thread,
  cpu,
  sum(dur) / 1e9 as cpu_sec
from sched
inner join thread using(utid)
inner join process using(upid)
group by utid, cpu
order by cpu_sec desc
limit 30;`;
const HEAP_GRAPH_BYTES_PER_TYPE = `
select
  o.upid,
  o.graph_sample_ts,
  c.name,
  sum(o.self_size) as total_self_size
from heap_graph_object o join heap_graph_class c on o.type_id = c.id
group by
 o.upid,
 o.graph_sample_ts,
 c.name
order by total_self_size desc
limit 100;`;
const SQL_STATS = `
with first as (select started as ts from sqlstats limit 1)
select query,
    round((max(ended - started, 0))/1e6) as runtime_ms,
    round((max(started - queued, 0))/1e6) as latency_ms,
    round((started - first.ts)/1e6) as t_start_ms
from sqlstats, first
order by started desc`;
let lastTabTitle = '';
function createCannedQuery(query) {
    return (e) => {
        e.preventDefault();
        globals$1.globals.dispatch(actions.Actions.executeQuery({
            engineId: '0',
            queryId: 'command',
            query,
        }));
    };
}
function showDebugTrack() {
    return (e) => {
        e.preventDefault();
        globals$1.globals.dispatch(actions.Actions.addDebugTrack({
            engineId: Object.keys(globals$1.globals.state.engines)[0],
            name: 'Debug Slices',
        }));
    };
}
const EXAMPLE_ANDROID_TRACE_URL = 'https://storage.googleapis.com/perfetto-misc/example_android_trace_15s';
const EXAMPLE_CHROME_TRACE_URL = 'https://storage.googleapis.com/perfetto-misc/example_chrome_trace_4s_1.json';
const SECTIONS = [
    {
        title: 'Navigation',
        summary: 'Open or record a new trace',
        expanded: true,
        items: [
            { t: 'Open trace file', a: popupFileSelectionDialog, i: 'folder_open' },
            {
                t: 'Open with legacy UI',
                a: popupFileSelectionDialogOldUI,
                i: 'filter_none'
            },
            { t: 'Record new trace', a: navigateRecord, i: 'fiber_smart_record' },
        ],
    },
    {
        title: 'Current Trace',
        summary: 'Actions on the current trace',
        expanded: true,
        hideIfNoTraceLoaded: true,
        appendOpenedTraceTitle: true,
        items: [
            { t: 'Show timeline', a: navigateViewer, i: 'line_style' },
            {
                t: 'Share',
                a: shareTrace,
                i: 'share',
                internalUserOnly: true,
                isPending: () => globals$1.globals.getConversionJobStatus('create_permalink') ===
                    conversion_jobs.ConversionJobStatus.InProgress,
            },
            {
                t: 'Download',
                a: downloadTrace,
                i: 'file_download',
                checkDownloadDisabled: true,
            },
            { t: 'Query (SQL)', a: navigateAnalyze, i: 'control_camera' },
            { t: 'Metrics', a: navigateMetrics, i: 'speed' },
            { t: 'Info and stats', a: navigateInfo, i: 'info' },
        ],
    },
    {
        title: 'Convert trace',
        summary: 'Convert to other formats',
        expanded: true,
        hideIfNoTraceLoaded: true,
        items: [
            {
                t: 'Switch to legacy UI',
                a: openCurrentTraceWithOldUI,
                i: 'filter_none',
                isPending: () => globals$1.globals.getConversionJobStatus('open_in_legacy') ===
                    conversion_jobs.ConversionJobStatus.InProgress,
            },
            {
                t: 'Convert to .json',
                a: convertTraceToJson,
                i: 'file_download',
                isPending: () => globals$1.globals.getConversionJobStatus('convert_json') ===
                    conversion_jobs.ConversionJobStatus.InProgress,
                checkDownloadDisabled: true,
            },
            {
                t: 'Convert to .systrace',
                a: convertTraceToSystrace,
                i: 'file_download',
                isVisible: () => globals$1.globals.hasFtrace,
                isPending: () => globals$1.globals.getConversionJobStatus('convert_systrace') ===
                    conversion_jobs.ConversionJobStatus.InProgress,
                checkDownloadDisabled: true,
            },
        ],
    },
    {
        title: 'Example Traces',
        expanded: true,
        summary: 'Open an example trace',
        items: [
            {
                t: 'Open Android example',
                a: openTraceUrl(EXAMPLE_ANDROID_TRACE_URL),
                i: 'description'
            },
            {
                t: 'Open Chrome example',
                a: openTraceUrl(EXAMPLE_CHROME_TRACE_URL),
                i: 'description'
            },
        ],
    },
    {
        title: 'Sample queries',
        summary: 'Compute summary statistics',
        items: [
            {
                t: 'Show Debug Track',
                a: showDebugTrack(),
                i: 'view_day',
            },
            {
                t: 'All Processes',
                a: createCannedQuery(ALL_PROCESSES_QUERY),
                i: 'search',
            },
            {
                t: 'CPU Time by process',
                a: createCannedQuery(CPU_TIME_FOR_PROCESSES),
                i: 'search',
            },
            {
                t: 'Cycles by p-state by CPU',
                a: createCannedQuery(CYCLES_PER_P_STATE_PER_CPU),
                i: 'search',
            },
            {
                t: 'CPU Time by CPU by process',
                a: createCannedQuery(CPU_TIME_BY_CPU_BY_PROCESS),
                i: 'search',
            },
            {
                t: 'Heap Graph: Bytes per type',
                a: createCannedQuery(HEAP_GRAPH_BYTES_PER_TYPE),
                i: 'search',
            },
            {
                t: 'Debug SQL performance',
                a: createCannedQuery(SQL_STATS),
                i: 'bug_report',
            },
        ],
    },
    {
        title: 'Support',
        summary: 'Documentation & Bugs',
        items: [
            {
                t: 'Controls',
                a: openHelp,
                i: 'help',
            },
            {
                t: 'Documentation',
                a: 'https://perfetto.dev',
                i: 'find_in_page',
            },
            {
                t: 'Report a bug',
                a: 'https://goto.google.com/perfetto-ui-bug',
                i: 'bug_report',
            },
        ],
    },
];
const vidSection = {
    title: 'Video',
    summary: 'Open a screen recording',
    expanded: true,
    items: [
        { t: 'Open video file', a: popupVideoSelectionDialog, i: 'folder_open' },
    ],
};
function openHelp(e) {
    e.preventDefault();
    help_modal.toggleHelp();
}
function getFileElement() {
    return document.querySelector('input[type=file]');
}
function popupFileSelectionDialog(e) {
    e.preventDefault();
    delete getFileElement().dataset['useCatapultLegacyUi'];
    delete getFileElement().dataset['video'];
    getFileElement().click();
}
function popupFileSelectionDialogOldUI(e) {
    e.preventDefault();
    delete getFileElement().dataset['video'];
    getFileElement().dataset['useCatapultLegacyUi'] = '1';
    getFileElement().click();
}
function downloadTraceFromUrl(url) {
    return mithril.request({
        method: 'GET',
        url,
        // TODO(hjd): Once mithril is updated we can use responseType here rather
        // than using config and remove the extract below.
        config: xhr => {
            xhr.responseType = 'blob';
            xhr.onprogress = progress => {
                const percent = (100 * progress.loaded / progress.total).toFixed(1);
                globals$1.globals.dispatch(actions.Actions.updateStatus({
                    msg: `Downloading trace ${percent}%`,
                    timestamp: Date.now() / 1000,
                }));
            };
        },
        extract: xhr => {
            return xhr.response;
        }
    });
}
function getCurrentTrace() {
    return tslib.__awaiter(this, void 0, void 0, function* () {
        // Caller must check engine exists.
        const engine = logging.assertExists(Object.values(globals$1.globals.state.engines)[0]);
        const src = engine.source;
        if (src.type === 'ARRAY_BUFFER') {
            return new Blob([src.buffer]);
        }
        else if (src.type === 'FILE') {
            return src.file;
        }
        else if (src.type === 'URL') {
            return downloadTraceFromUrl(src.url);
        }
        else {
            throw new Error(`Loading to catapult from source with type ${src.type}`);
        }
    });
}
function openCurrentTraceWithOldUI(e) {
    e.preventDefault();
    logging.assertTrue(isTraceLoaded());
    globals$1.globals.logging.logEvent('Trace Actions', 'Open current trace in legacy UI');
    if (!isTraceLoaded)
        return;
    getCurrentTrace()
        .then(file => {
        openInOldUIWithSizeCheck(file);
    })
        .catch(error => {
        throw new Error(`Failed to get current trace ${error}`);
    });
}
function convertTraceToSystrace(e) {
    e.preventDefault();
    logging.assertTrue(isTraceLoaded());
    globals$1.globals.logging.logEvent('Trace Actions', 'Convert to .systrace');
    if (!isTraceLoaded)
        return;
    getCurrentTrace()
        .then(file => {
        globals$1.globals.dispatch(actions.Actions.convertTraceToSystraceAndDownload({ file }));
    })
        .catch(error => {
        throw new Error(`Failed to get current trace ${error}`);
    });
}
function convertTraceToJson(e) {
    e.preventDefault();
    logging.assertTrue(isTraceLoaded());
    globals$1.globals.logging.logEvent('Trace Actions', 'Convert to .json');
    if (!isTraceLoaded)
        return;
    getCurrentTrace()
        .then(file => {
        globals$1.globals.dispatch(actions.Actions.convertTraceToJsonAndDownload({ file }));
    })
        .catch(error => {
        throw new Error(`Failed to get current trace ${error}`);
    });
}
function isTraceLoaded() {
    const engine = Object.values(globals$1.globals.state.engines)[0];
    return engine !== undefined;
}
function popupVideoSelectionDialog(e) {
    e.preventDefault();
    delete getFileElement().dataset['useCatapultLegacyUi'];
    getFileElement().dataset['video'] = '1';
    getFileElement().click();
}
function openTraceUrl(url) {
    return e => {
        globals$1.globals.logging.logEvent('Trace Actions', 'Open example trace');
        e.preventDefault();
        globals$1.globals.frontendLocalState.localOnlyMode = false;
        globals$1.globals.dispatch(actions.Actions.openTraceFromUrl({ url }));
    };
}
function onInputElementFileSelectionChanged(e) {
    if (!(e.target instanceof HTMLInputElement)) {
        throw new Error('Not an input element');
    }
    if (!e.target.files)
        return;
    const file = e.target.files[0];
    // Reset the value so onchange will be fired with the same file.
    e.target.value = '';
    globals$1.globals.frontendLocalState.localOnlyMode = false;
    if (e.target.dataset['useCatapultLegacyUi'] === '1') {
        openWithLegacyUi(file);
        return;
    }
    if (e.target.dataset['video'] === '1') {
        // TODO(hjd): Update this to use a controller and publish.
        globals$1.globals.dispatch(actions.Actions.executeQuery({
            engineId: '0', queryId: 'command',
            query: `select ts from slices where name = 'first_frame' union ` +
                `select start_ts from trace_bounds`
        }));
        setTimeout(() => {
            const resp = globals$1.globals.queryResults.get('command');
            // First value is screenrecord trace event timestamp
            // and second value is trace boundary's start timestamp
            const offset = (Number(resp.rows[1]['ts'].toString()) -
                Number(resp.rows[0]['ts'].toString())) /
                1e9;
            globals$1.globals.queryResults.delete('command');
            globals$1.globals.rafScheduler.scheduleFullRedraw();
            globals$1.globals.dispatch(actions.Actions.deleteQuery({ queryId: 'command' }));
            globals$1.globals.dispatch(actions.Actions.setVideoOffset({ offset }));
        }, 1000);
        globals$1.globals.dispatch(actions.Actions.openVideoFromFile({ file }));
        return;
    }
    globals$1.globals.logging.logEvent('Trace Actions', 'Open trace from file');
    globals$1.globals.dispatch(actions.Actions.openTraceFromFile({ file }));
}
function openWithLegacyUi(file) {
    return tslib.__awaiter(this, void 0, void 0, function* () {
        // Switch back to the old catapult UI.
        globals$1.globals.logging.logEvent('Trace Actions', 'Open trace in Legacy UI');
        if (yield legacy_trace_viewer.isLegacyTrace(file)) {
            legacy_trace_viewer.openFileWithLegacyTraceViewer(file);
            return;
        }
        openInOldUIWithSizeCheck(file);
    });
}
function openInOldUIWithSizeCheck(trace) {
    // Perfetto traces smaller than 50mb can be safely opened in the legacy UI.
    if (trace.size < 1024 * 1024 * 50) {
        globals$1.globals.dispatch(actions.Actions.convertTraceToJson({ file: trace }));
        return;
    }
    // Give the user the option to truncate larger perfetto traces.
    const size = Math.round(trace.size / (1024 * 1024));
    modal.showModal({
        title: 'Legacy UI may fail to open this trace',
        content: mithril('div', mithril('p', `This trace is ${size}mb, opening it in the legacy UI ` +
            `may fail.`), mithril('p', 'More options can be found at ', mithril('a', {
            href: 'https://goto.google.com/opening-large-traces',
            target: '_blank'
        }, 'go/opening-large-traces'), '.')),
        buttons: [
            {
                text: 'Open full trace (not recommended)',
                primary: false,
                id: 'open',
                action: () => {
                    globals$1.globals.dispatch(actions.Actions.convertTraceToJson({ file: trace }));
                }
            },
            {
                text: 'Open beginning of trace',
                primary: true,
                id: 'truncate-start',
                action: () => {
                    globals$1.globals.dispatch(actions.Actions.convertTraceToJson({ file: trace, truncate: 'start' }));
                }
            },
            {
                text: 'Open end of trace',
                primary: true,
                id: 'truncate-end',
                action: () => {
                    globals$1.globals.dispatch(actions.Actions.convertTraceToJson({ file: trace, truncate: 'end' }));
                }
            }
        ]
    });
    return;
}
function navigateRecord(e) {
    e.preventDefault();
    globals$1.globals.dispatch(actions.Actions.navigate({ route: '/record' }));
}
function navigateAnalyze(e) {
    e.preventDefault();
    globals$1.globals.dispatch(actions.Actions.navigate({ route: '/query' }));
}
function navigateMetrics(e) {
    e.preventDefault();
    globals$1.globals.dispatch(actions.Actions.navigate({ route: '/metrics' }));
}
function navigateInfo(e) {
    e.preventDefault();
    globals$1.globals.dispatch(actions.Actions.navigate({ route: '/info' }));
}
function navigateViewer(e) {
    e.preventDefault();
    globals$1.globals.dispatch(actions.Actions.navigate({ route: '/viewer' }));
}
function shareTrace(e) {
    e.preventDefault();
    const engine = logging.assertExists(Object.values(globals$1.globals.state.engines)[0]);
    const traceUrl = engine.source.url || '';
    // If the trace is not shareable (has been pushed via postMessage()) but has
    // a url, create a pseudo-permalink by echoing back the URL.
    if (!trace_attrs.isShareable()) {
        const msg = [mithril('p', 'This trace was opened by an external site and as such cannot ' +
                'be re-shared preserving the UI state.')];
        if (traceUrl) {
            msg.push(mithril('p', 'By using the URL below you can open this trace again.'));
            msg.push(mithril('p', 'Clicking will copy the URL into the clipboard.'));
            msg.push(createTraceLink(traceUrl, traceUrl));
        }
        modal.showModal({
            title: 'Cannot create permalink from external trace',
            content: mithril('div', msg),
            buttons: []
        });
        return;
    }
    if (!trace_attrs.isShareable() || !isTraceLoaded())
        return;
    const result = confirm(`Upload UI state and generate a permalink. ` +
        `The trace will be accessible by anybody with the permalink.`);
    if (result) {
        globals$1.globals.logging.logEvent('Trace Actions', 'Create permalink');
        globals$1.globals.dispatch(actions.Actions.createPermalink({ isRecordingConfig: false }));
    }
}
function downloadTrace(e) {
    e.preventDefault();
    if (!trace_attrs.isDownloadable() || !isTraceLoaded())
        return;
    globals$1.globals.logging.logEvent('Trace Actions', 'Download trace');
    const engine = Object.values(globals$1.globals.state.engines)[0];
    if (!engine)
        return;
    let url = '';
    let fileName = `trace${constants.TRACE_SUFFIX}`;
    const src = engine.source;
    if (src.type === 'URL') {
        url = src.url;
        fileName = url.split('/').slice(-1)[0];
    }
    else if (src.type === 'ARRAY_BUFFER') {
        const blob = new Blob([src.buffer], { type: 'application/octet-stream' });
        if (src.fileName) {
            fileName = src.fileName;
        }
        url = URL.createObjectURL(blob);
    }
    else if (src.type === 'FILE') {
        const file = src.file;
        url = URL.createObjectURL(file);
        fileName = file.name;
    }
    else {
        throw new Error(`Download from ${JSON.stringify(src)} is not supported`);
    }
    const a = document.createElement('a');
    a.href = url;
    a.download = fileName;
    a.target = '_blank';
    document.body.appendChild(a);
    a.click();
    document.body.removeChild(a);
    URL.revokeObjectURL(url);
}
const EngineRPCWidget = {
    view() {
        let cssClass = '';
        let title = 'Number of pending SQL queries';
        let label;
        let failed = false;
        let mode;
        // We are assuming we have at most one engine here.
        const engines = Object.values(globals$1.globals.state.engines);
        logging.assertTrue(engines.length <= 1);
        for (const engine of engines) {
            mode = engine.mode;
            if (engine.failed !== undefined) {
                cssClass += '.red';
                title = 'Query engine crashed\n' + engine.failed;
                failed = true;
            }
        }
        // If we don't have an engine yet, guess what will be the mode that will
        // be used next time we'll create one. Even if we guess it wrong (somehow
        // trace_controller.ts takes a different decision later, e.g. because the
        // RPC server is shut down after we load the UI and cached httpRpcState)
        // this will eventually become  consistent once the engine is created.
        if (mode === undefined) {
            if (globals$1.globals.frontendLocalState.httpRpcState.connected &&
                globals$1.globals.state.newEngineMode === 'USE_HTTP_RPC_IF_AVAILABLE') {
                mode = 'HTTP_RPC';
            }
            else {
                mode = 'WASM';
            }
        }
        if (mode === 'HTTP_RPC') {
            cssClass += '.green';
            label = 'RPC';
            title += '\n(Query engine: native accelerator over HTTP+RPC)';
        }
        else {
            label = 'WSM';
            title += '\n(Query engine: built-in WASM)';
        }
        return mithril(`.dbg-info-square${cssClass}`, { title }, mithril('div', label), mithril('div', `${failed ? 'FAIL' : globals$1.globals.numQueuedQueries}`));
    }
};
const ServiceWorkerWidget = {
    view() {
        let cssClass = '';
        let title = 'Service Worker: ';
        let label = 'N/A';
        const ctl = globals$1.globals.serviceWorkerController;
        if ((!('serviceWorker' in navigator))) {
            label = 'N/A';
            title += 'not supported by the browser (requires HTTPS)';
        }
        else if (ctl.bypassed) {
            label = 'OFF';
            cssClass = '.red';
            title += 'Bypassed, using live network. Double-click to re-enable';
        }
        else if (ctl.installing) {
            label = 'UPD';
            cssClass = '.amber';
            title += 'Installing / updating ...';
        }
        else if (!navigator.serviceWorker.controller) {
            label = 'N/A';
            title += 'Not available, using network';
        }
        else {
            label = 'ON';
            cssClass = '.green';
            title += 'Serving from cache. Ready for offline use';
        }
        const toggle = () => tslib.__awaiter(this, void 0, void 0, function* () {
            if (globals$1.globals.serviceWorkerController.bypassed) {
                globals$1.globals.serviceWorkerController.setBypass(false);
                return;
            }
            modal.showModal({
                title: 'Disable service worker?',
                content: mithril('div', mithril('p', `If you continue the service worker will be disabled until
                      manually re-enabled.`), mithril('p', `All future requests will be served from the network and the
                    UI won't be available offline.`), mithril('p', `You should do this only if you are debugging the UI
                    or if you are experiencing caching-related problems.`), mithril('p', `Disabling will cause a refresh of the UI, the current state
                    will be lost.`)),
                buttons: [
                    {
                        text: 'Disable and reload',
                        primary: true,
                        id: 'sw-bypass-enable',
                        action: () => {
                            globals$1.globals.serviceWorkerController.setBypass(true).then(() => location.reload());
                        }
                    },
                    {
                        text: 'Cancel',
                        primary: false,
                        id: 'sw-bypass-cancel',
                        action: () => { }
                    }
                ]
            });
        });
        return mithril(`.dbg-info-square${cssClass}`, { title, ondblclick: toggle }, mithril('div', 'SW'), mithril('div', label));
    }
};
const SidebarFooter = {
    view() {
        return mithril('.sidebar-footer', mithril('button', {
            onclick: () => globals$1.globals.frontendLocalState.togglePerfDebug(),
        }, mithril('i.material-icons', { title: 'Toggle Perf Debug Mode' }, 'assessment')), mithril(EngineRPCWidget), mithril(ServiceWorkerWidget), mithril('.version', mithril('a', {
            href: `https://github.com/google/perfetto/tree/${perfetto_version.SCM_REVISION}/ui`,
            title: `Channel: ${globals$1.globals.channel}`,
            target: '_blank',
        }, `${perfetto_version.VERSION}`)));
    }
};
class Sidebar {
    constructor() {
        this._redrawWhileAnimating = new animation.Animation(() => globals$1.globals.rafScheduler.scheduleFullRedraw());
    }
    view() {
        const vdomSections = [];
        for (const section of SECTIONS) {
            if (section.hideIfNoTraceLoaded && !isTraceLoaded())
                continue;
            const vdomItems = [];
            for (const item of section.items) {
                if (item.isVisible !== undefined && !item.isVisible()) {
                    continue;
                }
                let css = '';
                let attrs = {
                    onclick: typeof item.a === 'function' ? item.a : null,
                    href: typeof item.a === 'string' ? item.a : '#',
                    target: typeof item.a === 'string' ? '_blank' : null,
                    disabled: false,
                };
                if (item.isPending && item.isPending()) {
                    attrs.onclick = e => e.preventDefault();
                    css = '.pending';
                }
                if (item.internalUserOnly && !globals$1.globals.isInternalUser) {
                    continue;
                }
                if (item.checkDownloadDisabled && !trace_attrs.isDownloadable()) {
                    attrs = {
                        onclick: e => {
                            e.preventDefault();
                            alert('Can not download external trace.');
                        },
                        href: '#',
                        target: null,
                        disabled: true,
                    };
                }
                vdomItems.push(mithril('li', mithril(`a${css}`, attrs, mithril('i.material-icons', item.i), item.t)));
            }
            if (section.appendOpenedTraceTitle) {
                const engines = Object.values(globals$1.globals.state.engines);
                if (engines.length === 1) {
                    let traceTitle = '';
                    let traceUrl = '';
                    switch (engines[0].source.type) {
                        case 'FILE':
                            // Split on both \ and / (because C:\Windows\paths\are\like\this).
                            traceTitle = engines[0].source.file.name.split(/[/\\]/).pop();
                            const fileSizeMB = Math.ceil(engines[0].source.file.size / 1e6);
                            traceTitle += ` (${fileSizeMB} MB)`;
                            break;
                        case 'URL':
                            traceUrl = engines[0].source.url;
                            traceTitle = traceUrl.split('/').pop();
                            break;
                        case 'ARRAY_BUFFER':
                            traceTitle = engines[0].source.title;
                            traceUrl = engines[0].source.url || '';
                            break;
                        case 'HTTP_RPC':
                            traceTitle = 'External trace (RPC)';
                            break;
                    }
                    if (traceTitle !== '') {
                        const tabTitle = `${traceTitle} - Perfetto UI`;
                        if (tabTitle !== lastTabTitle) {
                            document.title = lastTabTitle = tabTitle;
                        }
                        vdomItems.unshift(mithril('li', createTraceLink(traceTitle, traceUrl)));
                    }
                }
            }
            vdomSections.push(mithril(`section${section.expanded ? '.expanded' : ''}`, mithril('.section-header', {
                onclick: () => {
                    section.expanded = !section.expanded;
                    globals$1.globals.rafScheduler.scheduleFullRedraw();
                }
            }, mithril('h1', { title: section.summary }, section.title), mithril('h2', section.summary)), mithril('.section-content', mithril('ul', vdomItems))));
        }
        if (globals$1.globals.state.videoEnabled) {
            const videoVdomItems = [];
            for (const item of vidSection.items) {
                videoVdomItems.push(mithril('li', mithril(`a`, {
                    onclick: typeof item.a === 'function' ? item.a : null,
                    href: typeof item.a === 'string' ? item.a : '#',
                }, mithril('i.material-icons', item.i), item.t)));
            }
            vdomSections.push(mithril(`section${vidSection.expanded ? '.expanded' : ''}`, mithril('.section-header', {
                onclick: () => {
                    vidSection.expanded = !vidSection.expanded;
                    globals$1.globals.rafScheduler.scheduleFullRedraw();
                }
            }, mithril('h1', vidSection.title), mithril('h2', vidSection.summary)), mithril('.section-content', mithril('ul', videoVdomItems))));
        }
        return mithril('nav.sidebar', {
            class: globals$1.globals.frontendLocalState.sidebarVisible ? 'show-sidebar' :
                'hide-sidebar',
            // 150 here matches --sidebar-timing in the css.
            ontransitionstart: () => this._redrawWhileAnimating.start(150),
            ontransitionend: () => this._redrawWhileAnimating.stop(),
        }, mithril(`header.${globals$1.globals.channel}`, mithril(`img[src=${globals$1.globals.root}assets/brand.png].brand`), mithril('button.sidebar-button', {
            onclick: () => {
                globals$1.globals.frontendLocalState.toggleSidebar();
            },
        }, mithril('i.material-icons', {
            title: globals$1.globals.frontendLocalState.sidebarVisible ?
                'Hide menu' :
                'Show menu',
        }, 'menu'))), mithril('input[type=file]', { onchange: onInputElementFileSelectionChanged }), mithril('.sidebar-scroll', mithril('.sidebar-scroll-container', ...vdomSections, mithril(SidebarFooter))));
    }
}
exports.Sidebar = Sidebar;
function createTraceLink(title, url) {
    if (url === '') {
        return mithril('a.trace-file-name', title);
    }
    const linkProps = {
        href: url,
        title: 'Click to copy the URL',
        target: '_blank',
        onclick: (e) => {
            e.preventDefault();
            clipboard.copyToClipboard(url);
            globals$1.globals.dispatch(actions.Actions.updateStatus({
                msg: 'Link copied into the clipboard',
                timestamp: Date.now() / 1000,
            }));
        },
    };
    return mithril('a.trace-file-name', linkProps, title);
}

});

var search_handler = createCommonjsModule(function (module, exports) {
// Copyright (C) 2019 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.
Object.defineProperty(exports, "__esModule", { value: true });
exports.executeSearch = void 0;





function setToPrevious(current) {
    globals$1.globals.frontendLocalState.setSearchIndex(Math.max(current - 1, 0));
}
function setToNext(current) {
    globals$1.globals.frontendLocalState.setSearchIndex(Math.min(current + 1, globals$1.globals.currentSearchResults.totalResults - 1));
}
function executeSearch(reverse = false) {
    const state = globals$1.globals.frontendLocalState;
    const index = state.searchIndex;
    const startNs = time.toNs(globals$1.globals.frontendLocalState.visibleWindowTime.start);
    const endNs = time.toNs(globals$1.globals.frontendLocalState.visibleWindowTime.end);
    const currentTs = globals$1.globals.currentSearchResults.tsStarts[index];
    // If this is a new search or the currentTs is not in the viewport,
    // select the first/last item in the viewport.
    if (index === -1 || currentTs < startNs || currentTs > endNs) {
        if (reverse) {
            const [smaller,] = binary_search.searchSegment(globals$1.globals.currentSearchResults.tsStarts, endNs);
            // If there is no item in the viewport just go to the previous.
            smaller === -1 ? setToPrevious(index) :
                globals$1.globals.frontendLocalState.setSearchIndex(smaller);
        }
        else {
            const [, larger] = binary_search.searchSegment(globals$1.globals.currentSearchResults.tsStarts, startNs);
            // If there is no item in the viewport just go to the next.
            larger === -1 ? setToNext(index) :
                globals$1.globals.frontendLocalState.setSearchIndex(larger);
        }
    }
    else {
        // If the currentTs is in the viewport, increment the index.
        if (reverse) {
            setToPrevious(index);
        }
        else {
            setToNext(index);
        }
    }
    selectCurrentSearchResult();
    // TODO(hjd): If the user does a search before any other selection,
    // the details panel will pop up when the search is executed. If the search
    // result is behind where the details panel appears then it won't get scrolled
    // to. This time delay is a workaround for this specific situation.
    // A better solution will be a callback that allows something to happen on the
    // first redraw after an Action is applied.
    const delay = index === -1 ? 50 : 0;
    setTimeout(() => moveViewportToCurrentSearch(), delay);
}
exports.executeSearch = executeSearch;
function moveViewportToCurrentSearch() {
    const searchIndex = globals$1.globals.frontendLocalState.searchIndex;
    if (searchIndex === -1)
        return;
    const currentTs = globals$1.globals.currentSearchResults.tsStarts[searchIndex];
    const trackId = globals$1.globals.currentSearchResults.trackIds[searchIndex];
    scroll_helper.scrollToTrackAndTs(trackId, currentTs);
}
function selectCurrentSearchResult() {
    const state = globals$1.globals.frontendLocalState;
    const searchIndex = state.searchIndex;
    const source = globals$1.globals.currentSearchResults.sources[searchIndex];
    const currentId = globals$1.globals.currentSearchResults.sliceIds[searchIndex];
    const trackId = globals$1.globals.currentSearchResults.trackIds[searchIndex];
    if (currentId === undefined)
        return;
    if (source === 'cpu') {
        globals$1.globals.dispatch(actions.Actions.selectSlice({ id: currentId, trackId }));
    }
    else {
        // Search results only include slices from the slice table for now.
        // When we include annotations we need to pass the correct table.
        globals$1.globals.dispatch(actions.Actions.selectChromeSlice({ id: currentId, trackId, table: 'slice' }));
    }
}

});

var task_tracker = createCommonjsModule(function (module, exports) {
// Copyright (C) 2020 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.
Object.defineProperty(exports, "__esModule", { value: true });
exports.taskTracker = exports.TaskTracker = void 0;
class TaskTracker {
    constructor() {
        this.promisesSeen = 0;
        this.promisesRejected = 0;
        this.promisesFulfilled = 0;
        this.promiseInfo = new Map();
    }
    trackPromise(promise, message) {
        this.promiseInfo.set(promise, {
            startTimeMs: (new Date()).getMilliseconds(),
            message,
        });
        this.promisesSeen += 1;
        promise.then(() => {
            this.promisesFulfilled += 1;
        }).catch(() => {
            this.promisesRejected += 1;
        }).finally(() => {
            this.promiseInfo.delete(promise);
        });
    }
    hasPendingTasks() {
        return this.promisesSeen > (this.promisesFulfilled + this.promisesRejected);
    }
    progressMessage() {
        const { value } = this.promiseInfo.values().next();
        if (value === undefined) {
            return value;
        }
        else {
            const nowMs = (new Date()).getMilliseconds();
            const runtimeSeconds = Math.round((nowMs - value.startTimeMs) / 1000);
            return `${value.message} (${runtimeSeconds}s)`;
        }
    }
}
exports.TaskTracker = TaskTracker;
exports.taskTracker = new TaskTracker();

});

var topbar = createCommonjsModule(function (module, exports) {
// 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.
Object.defineProperty(exports, "__esModule", { value: true });
exports.Topbar = exports.DISMISSED_PANNING_HINT_KEY = void 0;






const SEARCH = Symbol('search');
const COMMAND = Symbol('command');
const PLACEHOLDER = {
    [SEARCH]: 'Search',
    [COMMAND]: 'e.g. select * from sched left join thread using(utid) limit 10'
};
exports.DISMISSED_PANNING_HINT_KEY = 'dismissedPanningHint';
let mode = SEARCH;
let displayStepThrough = false;
function onKeyDown(e) {
    const event = e;
    const key = event.key;
    if (key !== 'Enter') {
        e.stopPropagation();
    }
    const txt = e.target;
    if (mode === SEARCH && txt.value === '' && key === ':') {
        e.preventDefault();
        mode = COMMAND;
        globals$1.globals.rafScheduler.scheduleFullRedraw();
        return;
    }
    if (mode === COMMAND && txt.value === '' && key === 'Backspace') {
        mode = SEARCH;
        globals$1.globals.rafScheduler.scheduleFullRedraw();
        return;
    }
    if (mode === SEARCH && key === 'Enter') {
        txt.blur();
    }
}
function onKeyUp(e) {
    e.stopPropagation();
    const event = e;
    const key = event.key;
    const txt = e.target;
    if (key === 'Escape') {
        globals$1.globals.dispatch(actions.Actions.deleteQuery({ queryId: 'command' }));
        mode = SEARCH;
        txt.value = '';
        txt.blur();
        globals$1.globals.rafScheduler.scheduleFullRedraw();
        return;
    }
    if (mode === COMMAND && key === 'Enter') {
        globals$1.globals.dispatch(actions.Actions.executeQuery({ engineId: '0', queryId: 'command', query: txt.value }));
    }
}
class Omnibox {
    oncreate(vnode) {
        const txt = vnode.dom.querySelector('input');
        txt.addEventListener('keydown', onKeyDown);
        txt.addEventListener('keyup', onKeyUp);
    }
    view() {
        const msgTTL = globals$1.globals.state.status.timestamp + 1 - Date.now() / 1e3;
        let enginesAreBusy = false;
        for (const engine of Object.values(globals$1.globals.state.engines)) {
            enginesAreBusy = enginesAreBusy || !engine.ready;
        }
        if (msgTTL > 0 || enginesAreBusy) {
            setTimeout(() => globals$1.globals.rafScheduler.scheduleFullRedraw(), msgTTL * 1000);
            return mithril(`.omnibox.message-mode`, mithril(`input[placeholder=${globals$1.globals.state.status.msg}][readonly]`, {
                value: '',
            }));
        }
        const commandMode = mode === COMMAND;
        const state = globals$1.globals.frontendLocalState;
        return mithril(`.omnibox${commandMode ? '.command-mode' : ''}`, mithril('input', {
            placeholder: PLACEHOLDER[mode],
            oninput: (e) => {
                const value = e.target.value;
                globals$1.globals.frontendLocalState.setOmnibox(value, commandMode ? 'COMMAND' : 'SEARCH');
                if (mode === SEARCH) {
                    globals$1.globals.frontendLocalState.setSearchIndex(-1);
                    displayStepThrough = value.length >= 4;
                    globals$1.globals.rafScheduler.scheduleFullRedraw();
                }
            },
            value: globals$1.globals.frontendLocalState.omnibox,
        }), displayStepThrough ?
            mithril('.stepthrough', mithril('.current', `${globals$1.globals.currentSearchResults.totalResults === 0 ?
                '0 / 0' :
                `${state.searchIndex + 1} / ${globals$1.globals.currentSearchResults.totalResults}`}`), mithril('button', {
                disabled: state.searchIndex <= 0,
                onclick: () => {
                    search_handler.executeSearch(true /* reverse direction */);
                }
            }, mithril('i.material-icons.left', 'keyboard_arrow_left')), mithril('button', {
                disabled: state.searchIndex ===
                    globals$1.globals.currentSearchResults.totalResults - 1,
                onclick: () => {
                    search_handler.executeSearch();
                }
            }, mithril('i.material-icons.right', 'keyboard_arrow_right'))) :
            '');
    }
}
class Progress {
    constructor() {
        this.loading = () => this.loadingAnimation();
    }
    oncreate(vnodeDom) {
        this.progressBar = vnodeDom.dom;
        globals$1.globals.rafScheduler.addRedrawCallback(this.loading);
    }
    onremove() {
        globals$1.globals.rafScheduler.removeRedrawCallback(this.loading);
    }
    view() {
        return mithril('.progress');
    }
    loadingAnimation() {
        if (this.progressBar === undefined)
            return;
        const engine = globals$1.globals.state.engines['0'];
        if ((engine !== undefined && !engine.ready) ||
            globals$1.globals.numQueuedQueries > 0 || task_tracker.taskTracker.hasPendingTasks()) {
            this.progressBar.classList.add('progress-anim');
        }
        else {
            this.progressBar.classList.remove('progress-anim');
        }
    }
}
class NewVersionNotification {
    view() {
        return mithril('.new-version-toast', `Updated to ${perfetto_version.VERSION} and ready for offline use!`, mithril('button.notification-btn.preferred', {
            onclick: () => {
                globals$1.globals.frontendLocalState.newVersionAvailable = false;
                globals$1.globals.rafScheduler.scheduleFullRedraw();
            }
        }, 'Dismiss'));
    }
}
class HelpPanningNotification {
    view() {
        const dismissed = localStorage.getItem(exports.DISMISSED_PANNING_HINT_KEY);
        if (dismissed === 'true' || !globals$1.globals.frontendLocalState.showPanningHint) {
            return;
        }
        return mithril('.helpful-hint', mithril('.hint-text', 'Are you trying to pan? Use the WASD keys or hold shift to click ' +
            'and drag. Press \'?\' for more help.'), mithril('button.hint-dismiss-button', {
            onclick: () => {
                globals$1.globals.frontendLocalState.showPanningHint = false;
                localStorage.setItem(exports.DISMISSED_PANNING_HINT_KEY, 'true');
                globals$1.globals.rafScheduler.scheduleFullRedraw();
            }
        }, 'Dismiss'));
    }
}
class TraceErrorIcon {
    view() {
        const errors = globals$1.globals.traceErrors;
        if (!errors && !globals$1.globals.metricError || mode === COMMAND)
            return;
        const message = errors ? `${errors} import or data loss errors detected.` :
            `Metric error detected.`;
        return mithril('a.error', { href: '#!/info' }, mithril('i.material-icons', {
            title: message + ` Click for more info.`,
        }, 'announcement'));
    }
}
class RefreshIcon {
    view() {
        return mithril('button.topbar-button', {
            onclick: () => {
                // @ts-ignore this function is set in index.html
                window.clearAllCaches();
            },
        }, mithril('i.material-icons', 'refresh'));
    }
}
class Topbar {
    view() {
        return mithril('.topbar', {
            class: globals$1.globals.frontendLocalState.sidebarVisible ? '' : 'hide-sidebar'
        }, globals$1.globals.frontendLocalState.newVersionAvailable ?
            mithril(NewVersionNotification) :
            mithril(Omnibox), mithril(Progress), mithril(HelpPanningNotification), mithril(TraceErrorIcon), mithril(RefreshIcon));
    }
}
exports.Topbar = Topbar;

});

var pages = createCommonjsModule(function (module, exports) {
// 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.
Object.defineProperty(exports, "__esModule", { value: true });
exports.createPage = void 0;






function renderPermalink() {
    const permalink = globals$1.globals.state.permalink;
    if (!permalink.requestId || !permalink.hash)
        return null;
    const url = `${self.location.origin}/#!/?s=${permalink.hash}`;
    return mithril('.alert-permalink', [
        mithril('div', 'Permalink: ', mithril(`a[href=${url}]`, url)),
        mithril('button', {
            onclick: () => globals$1.globals.dispatch(actions.Actions.clearPermalink({})),
        }, mithril('i.material-icons.disallow-selection', 'close')),
    ]);
}
class Alerts {
    view() {
        return mithril('.alerts', renderPermalink());
    }
}
/**
 * Wrap component with common UI elements (nav bar etc).
 */
function createPage(component) {
    const pageComponent = {
        view() {
            const children = [
                mithril(sidebar.Sidebar),
                mithril(topbar.Topbar),
                mithril(Alerts),
                mithril(component),
                mithril(cookie_consent.CookieConsent),
            ];
            if (globals$1.globals.frontendLocalState.perfDebug) {
                children.push(mithril('.perf-stats'));
            }
            return children;
        },
    };
    return pageComponent;
}
exports.createPage = createPage;

});

var query_table = createCommonjsModule(function (module, exports) {
// Copyright (C) 2020 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.
Object.defineProperty(exports, "__esModule", { value: true });
exports.QueryTable = void 0;







class QueryTableRow {
    static columnsContainsSliceLocation(columns) {
        const requiredColumns = ['ts', 'dur', 'track_id'];
        for (const col of requiredColumns) {
            if (!columns.includes(col))
                return false;
        }
        return true;
    }
    static rowOnClickHandler(event, row, nextTab) {
        var _a;
        // TODO(dproy): Make click handler work from analyze page.
        if (globals$1.globals.state.route !== '/viewer')
            return;
        // If the click bubbles up to the pan and zoom handler that will deselect
        // the slice.
        event.stopPropagation();
        const sliceStart = time.fromNs(row.ts);
        // row.dur can be negative. Clamp to 1ns.
        const sliceDur = time.fromNs(Math.max(row.dur, 1));
        const sliceEnd = sliceStart + sliceDur;
        const trackId = row.track_id;
        const uiTrackId = scroll_helper.findUiTrackId(trackId);
        if (uiTrackId === null)
            return;
        scroll_helper.verticalScrollToTrack(uiTrackId, true);
        scroll_helper.horizontalScrollAndZoomToRange(sliceStart, sliceEnd);
        let sliceId;
        if ((_a = row.type) === null || _a === void 0 ? void 0 : _a.toString().includes('slice')) {
            sliceId = row.id;
        }
        else {
            sliceId = row.slice_id;
        }
        if (sliceId !== undefined) {
            globals$1.globals.makeSelection(actions.Actions.selectChromeSlice({ id: sliceId, trackId: uiTrackId, table: 'slice' }), nextTab === 'QueryResults' ? globals$1.globals.frontendLocalState.currentTab :
                'current_selection');
        }
    }
    view(vnode) {
        const cells = [];
        const { row, columns } = vnode.attrs;
        for (const col of columns) {
            cells.push(mithril('td', row[col]));
        }
        const containsSliceLocation = QueryTableRow.columnsContainsSliceLocation(columns);
        const maybeOnClick = containsSliceLocation ?
            (e) => QueryTableRow.rowOnClickHandler(e, row, 'QueryResults') :
            null;
        const maybeOnDblClick = containsSliceLocation ?
            (e) => QueryTableRow.rowOnClickHandler(e, row, 'CurrentSelection') :
            null;
        return mithril('tr', {
            onclick: maybeOnClick,
            // TODO(altimin): Consider improving the logic here (e.g. delay?) to
            // account for cases when dblclick fires late.
            ondblclick: maybeOnDblClick,
            'clickable': containsSliceLocation
        }, cells);
    }
}
class QueryTable extends panel.Panel {
    onbeforeupdate(vnode) {
        const { queryId } = vnode.attrs;
        const resp = globals$1.globals.queryResults.get(queryId);
        const res = resp !== this.previousResponse;
        return res;
    }
    view(vnode) {
        const { queryId } = vnode.attrs;
        const resp = globals$1.globals.queryResults.get(queryId);
        if (resp === undefined) {
            return mithril('');
        }
        this.previousResponse = resp;
        const cols = [];
        for (const col of resp.columns) {
            cols.push(mithril('td', col));
        }
        const header = mithril('tr', cols);
        const rows = [];
        for (let i = 0; i < resp.rows.length; i++) {
            rows.push(mithril(QueryTableRow, { row: resp.rows[i], columns: resp.columns }));
        }
        return mithril('div', mithril('header.overview', `Query result - ${Math.round(resp.durationMs)} ms`, mithril('span.code', resp.query), resp.error ?
            null :
            mithril('button.query-ctrl', {
                onclick: () => {
                    const lines = [];
                    lines.push(resp.columns);
                    for (const row of resp.rows) {
                        const line = [];
                        for (const col of resp.columns) {
                            line.push(row[col].toString());
                        }
                        lines.push(line);
                    }
                    clipboard.copyToClipboard(lines.map(line => line.join('\t')).join('\n'));
                },
            }, 'Copy as .tsv'), mithril('button.query-ctrl', {
            onclick: () => {
                globals$1.globals.queryResults.delete(queryId);
                globals$1.globals.rafScheduler.scheduleFullRedraw();
            }
        }, 'Close')), resp.error ?
            mithril('.query-error', `SQL error: ${resp.error}`) :
            mithril('.query-table-container', mithril('table.query-table', mithril('thead', header), mithril('tbody', rows))));
    }
    renderCanvas() { }
}
exports.QueryTable = QueryTable;

});

var analyze_page = createCommonjsModule(function (module, exports) {
// Copyright (C) 2020 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.
Object.defineProperty(exports, "__esModule", { value: true });
exports.AnalyzePage = void 0;





const INPUT_PLACEHOLDER = 'Enter query and press Cmd/Ctrl + Enter';
const INPUT_MIN_LINES = 2;
const INPUT_MAX_LINES = 10;
const INPUT_LINE_HEIGHT_EM = 1.2;
const TAB_SPACES = 2;
const QUERY_ID = 'analyze-page-query';
class QueryInput {
    constructor() {
        // How many lines to display if the user hasn't resized the input box.
        this.displayLines = INPUT_MIN_LINES;
    }
    static onKeyDown(e) {
        const event = e;
        const target = e.target;
        if (event.code === 'Enter' && (event.metaKey || event.ctrlKey)) {
            event.preventDefault();
            const query = target.value;
            if (!query)
                return;
            globals$1.globals.dispatch(actions.Actions.executeQuery({ engineId: '0', queryId: QUERY_ID, query }));
        }
        if (event.code === 'Tab') {
            // Handle tabs to insert spaces.
            event.preventDefault();
            const whitespace = ' '.repeat(TAB_SPACES);
            const { selectionStart, selectionEnd } = target;
            target.value = target.value.substring(0, selectionStart) + whitespace +
                target.value.substring(selectionEnd);
            target.selectionEnd = selectionStart + TAB_SPACES;
        }
    }
    onInput(textareaValue) {
        const textareaLines = textareaValue.split('\n').length;
        const clampedNumLines = Math.min(Math.max(textareaLines, INPUT_MIN_LINES), INPUT_MAX_LINES);
        this.displayLines = clampedNumLines;
        globals$1.globals.dispatch(actions.Actions.setAnalyzePageQuery({ query: textareaValue }));
        globals$1.globals.rafScheduler.scheduleFullRedraw();
    }
    // This method exists because unfortunatley setting custom properties on an
    // element's inline style attribue doesn't seem to work in mithril, even
    // though the docs claim so.
    setHeightBeforeResize(node) {
        // +2em for some extra breathing space to account for padding.
        const heightEm = this.displayLines * INPUT_LINE_HEIGHT_EM + 2;
        // We set a height based on the number of lines that we want to display by
        // default. If the user resizes the textbox using the resize handle in the
        // bottom-right corner, this height is overridden.
        node.style.setProperty('--height-before-resize', `${heightEm}em`);
        // TODO(dproy): The resized height is lost if user navigates away from the
        // page and comes back.
    }
    oncreate(vnode) {
        // This makes sure query persists if user navigates to other pages and comes
        // back to analyze page.
        const existingQuery = globals$1.globals.state.analyzePageQuery;
        const textarea = vnode.dom;
        if (existingQuery) {
            textarea.value = existingQuery;
            this.onInput(existingQuery);
        }
        this.setHeightBeforeResize(textarea);
    }
    onupdate(vnode) {
        this.setHeightBeforeResize(vnode.dom);
    }
    view() {
        return mithril('textarea.query-input', {
            placeholder: INPUT_PLACEHOLDER,
            onkeydown: (e) => QueryInput.onKeyDown(e),
            oninput: (e) => this.onInput(e.target.value),
        });
    }
}
exports.AnalyzePage = pages.createPage({
    view() {
        return mithril('.analyze-page', mithril(QueryInput), mithril(query_table.QueryTable, { queryId: QUERY_ID }));
    }
});

});

var android_bug_tool = createCommonjsModule(function (module, exports) {
Object.defineProperty(exports, "__esModule", { value: true });
exports.loadAndroidBugToolInfo = void 0;


var WebContentScriptMessageType;
(function (WebContentScriptMessageType) {
    WebContentScriptMessageType[WebContentScriptMessageType["UNKNOWN"] = 0] = "UNKNOWN";
    WebContentScriptMessageType[WebContentScriptMessageType["CONVERT_OBJECT_URL"] = 1] = "CONVERT_OBJECT_URL";
    WebContentScriptMessageType[WebContentScriptMessageType["CONVERT_OBJECT_URL_RESPONSE"] = 2] = "CONVERT_OBJECT_URL_RESPONSE";
})(WebContentScriptMessageType || (WebContentScriptMessageType = {}));
const ANDROID_BUG_TOOL_EXTENSION_ID = 'mbbaofdfoekifkfpgehgffcpagbbjkmj';
function loadAndroidBugToolInfo() {
    const deferred$1 = deferred.defer();
    // Request to convert the blob object url "blob:chrome-extension://xxx"
    // the chrome extension has to a web downloadable url "blob:http://xxx".
    chrome.runtime.sendMessage(ANDROID_BUG_TOOL_EXTENSION_ID, { action: WebContentScriptMessageType.CONVERT_OBJECT_URL }, (response) => tslib.__awaiter(this, void 0, void 0, function* () {
        var _a;
        switch (response.action) {
            case WebContentScriptMessageType.CONVERT_OBJECT_URL_RESPONSE:
                if (((_a = response.attachments) === null || _a === void 0 ? void 0 : _a.length) > 0) {
                    const filesBlobPromises = response.attachments.map((attachment) => tslib.__awaiter(this, void 0, void 0, function* () {
                        const fileQueryResponse = yield fetch(attachment.objectUrl);
                        const blob = yield fileQueryResponse.blob();
                        // Note: The blob's media type is always set to "image/png".
                        // Clone blob to clear media type.
                        return new File([blob], attachment.name);
                    }));
                    const files = yield Promise.all(filesBlobPromises);
                    deferred$1.resolve({
                        issueId: response.issueId,
                        issueTitle: response.issueTitle,
                        file: files[0],
                    });
                }
                else {
                    throw new Error('Got no attachements from extension');
                }
                break;
            default:
                throw new Error(`Received unhandled response code (${response.action}) from extension.`);
        }
    }));
    return deferred$1;
}
exports.loadAndroidBugToolInfo = loadAndroidBugToolInfo;

});

var rngBrowser = createCommonjsModule(function (module) {
// Unique ID creation requires a high quality random # generator.  In the
// browser this is a little complicated due to unknown quality of Math.random()
// and inconsistent support for the `crypto` API.  We do the best we can via
// feature-detection

// getRandomValues needs to be invoked in a context where "this" is a Crypto
// implementation. Also, find the complete implementation of crypto on IE11.
var getRandomValues = (typeof(crypto) != 'undefined' && crypto.getRandomValues && crypto.getRandomValues.bind(crypto)) ||
                      (typeof(msCrypto) != 'undefined' && typeof window.msCrypto.getRandomValues == 'function' && msCrypto.getRandomValues.bind(msCrypto));

if (getRandomValues) {
  // WHATWG crypto RNG - http://wiki.whatwg.org/wiki/Crypto
  var rnds8 = new Uint8Array(16); // eslint-disable-line no-undef

  module.exports = function whatwgRNG() {
    getRandomValues(rnds8);
    return rnds8;
  };
} else {
  // Math.random()-based (RNG)
  //
  // If all else fails, use Math.random().  It's fast, but is of unspecified
  // quality.
  var rnds = new Array(16);

  module.exports = function mathRNG() {
    for (var i = 0, r; i < 16; i++) {
      if ((i & 0x03) === 0) r = Math.random() * 0x100000000;
      rnds[i] = r >>> ((i & 0x03) << 3) & 0xff;
    }

    return rnds;
  };
}
});

/**
 * Convert array of 16 byte values to UUID string format of the form:
 * XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
 */
var byteToHex = [];
for (var i = 0; i < 256; ++i) {
  byteToHex[i] = (i + 0x100).toString(16).substr(1);
}

function bytesToUuid(buf, offset) {
  var i = offset || 0;
  var bth = byteToHex;
  // join used to fix memory issue caused by concatenation: https://bugs.chromium.org/p/v8/issues/detail?id=3175#c4
  return ([
    bth[buf[i++]], bth[buf[i++]],
    bth[buf[i++]], bth[buf[i++]], '-',
    bth[buf[i++]], bth[buf[i++]], '-',
    bth[buf[i++]], bth[buf[i++]], '-',
    bth[buf[i++]], bth[buf[i++]], '-',
    bth[buf[i++]], bth[buf[i++]],
    bth[buf[i++]], bth[buf[i++]],
    bth[buf[i++]], bth[buf[i++]]
  ]).join('');
}

var bytesToUuid_1 = bytesToUuid;

function v4(options, buf, offset) {
  var i = buf && offset || 0;

  if (typeof(options) == 'string') {
    buf = options === 'binary' ? new Array(16) : null;
    options = null;
  }
  options = options || {};

  var rnds = options.random || (options.rng || rngBrowser)();

  // Per 4.4, set bits for version and `clock_seq_hi_and_reserved`
  rnds[6] = (rnds[6] & 0x0f) | 0x40;
  rnds[8] = (rnds[8] & 0x3f) | 0x80;

  // Copy bytes to buffer, if provided
  if (buf) {
    for (var ii = 0; ii < 16; ++ii) {
      buf[i + ii] = rnds[ii];
    }
  }

  return buf || bytesToUuid_1(rnds);
}

var v4_1 = v4;

var upload_utils = createCommonjsModule(function (module, exports) {
// Copyright (C) 2020 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.
Object.defineProperty(exports, "__esModule", { value: true });
exports.toSha256 = exports.saveState = exports.saveTrace = exports.BUCKET_NAME = void 0;

exports.BUCKET_NAME = 'perfetto-ui-data';

function saveTrace(trace) {
    return tslib.__awaiter(this, void 0, void 0, function* () {
        // TODO(hjd): This should probably also be a hash but that requires
        // trace processor support.
        const name = v4_1();
        const url = 'https://www.googleapis.com/upload/storage/v1/b/' +
            `${exports.BUCKET_NAME}/o?uploadType=media` +
            `&name=${name}&predefinedAcl=publicRead`;
        const response = yield fetch(url, {
            method: 'post',
            headers: { 'Content-Type': 'application/octet-stream;' },
            body: trace,
        });
        yield response.json();
        return `https://storage.googleapis.com/${exports.BUCKET_NAME}/${name}`;
    });
}
exports.saveTrace = saveTrace;
function saveState(stateOrConfig) {
    return tslib.__awaiter(this, void 0, void 0, function* () {
        const text = JSON.stringify(stateOrConfig);
        const hash = yield toSha256(text);
        const url = 'https://www.googleapis.com/upload/storage/v1/b/' +
            `${exports.BUCKET_NAME}/o?uploadType=media` +
            `&name=${hash}&predefinedAcl=publicRead`;
        const response = yield fetch(url, {
            method: 'post',
            headers: {
                'Content-Type': 'application/json; charset=utf-8',
            },
            body: text,
        });
        yield response.json();
        return hash;
    });
}
exports.saveState = saveState;
function toSha256(str) {
    return tslib.__awaiter(this, void 0, void 0, function* () {
        // TODO(hjd): TypeScript bug with definition of TextEncoder.
        // tslint:disable-next-line no-any
        const buffer = new TextEncoder('utf-8').encode(str);
        const digest = yield crypto.subtle.digest('SHA-256', buffer);
        return Array.from(new Uint8Array(digest)).map(x => x.toString(16)).join('');
    });
}
exports.toSha256 = toSha256;

});

var error_dialog = createCommonjsModule(function (module, exports) {
// Copyright (C) 2019 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.
Object.defineProperty(exports, "__esModule", { value: true });
exports.maybeShowErrorDialog = void 0;





// Never show more than one dialog per minute.
const MIN_REPORT_PERIOD_MS = 60000;
let timeLastReport = 0;
// Keeps the last ERR_QUEUE_MAX_LEN errors while the dialog is throttled.
const queuedErrors = new Array();
const ERR_QUEUE_MAX_LEN = 10;
function maybeShowErrorDialog(errLog) {
    globals$1.globals.logging.logError(errLog);
    const now = performance.now();
    // Here we rely on the exception message from onCannotGrowMemory function
    if (errLog.includes('Cannot enlarge memory')) {
        showOutOfMemoryDialog();
        // Refresh timeLastReport to prevent a different error showing a dialog
        timeLastReport = now;
        return;
    }
    if (errLog.includes('Unable to claim interface.') ||
        errLog.includes('A transfer error has occurred')) {
        showWebUSBError();
        timeLastReport = now;
    }
    if (errLog.includes('(ERR:fmt)')) {
        showUnknownFileError();
        return;
    }
    if (timeLastReport > 0 && now - timeLastReport <= MIN_REPORT_PERIOD_MS) {
        queuedErrors.unshift(errLog);
        if (queuedErrors.length > ERR_QUEUE_MAX_LEN)
            queuedErrors.pop();
        console.log('Suppressing crash dialog, last error notified too soon.');
        return;
    }
    timeLastReport = now;
    // Append queued errors.
    while (queuedErrors.length > 0) {
        const queuedErr = queuedErrors.shift();
        errLog += `\n\n---------------------------------------\n${queuedErr}`;
    }
    const errTitle = errLog.split('\n', 1)[0].substr(0, 80);
    const userDescription = '';
    let checked = false;
    const engine = Object.values(globals$1.globals.state.engines)[0];
    const shareTraceSection = [];
    if (trace_attrs.isShareable() && !urlExists()) {
        shareTraceSection.push(mithril(`input[type=checkbox]`, {
            checked,
            oninput: (ev) => {
                checked = ev.target.checked;
                if (checked && engine.source.type === 'FILE') {
                    upload_utils.saveTrace(engine.source.file).then(url => {
                        const errMessage = createErrorMessage(errLog, checked, url);
                        renderModal(errTitle, errMessage, userDescription, shareTraceSection);
                        return;
                    });
                }
                const errMessage = createErrorMessage(errLog, checked);
                renderModal(errTitle, errMessage, userDescription, shareTraceSection);
            },
        }), mithril('span', `Check this box to share the current trace for debugging
     purposes.`), mithril('div.modal-small', `This will create a permalink to this trace, you may
     leave it unchecked and attach the trace manually
     to the bug if preferred.`));
    }
    renderModal(errTitle, createErrorMessage(errLog, checked), userDescription, shareTraceSection);
}
exports.maybeShowErrorDialog = maybeShowErrorDialog;
function renderModal(errTitle, errMessage, userDescription, shareTraceSection) {
    modal.showModal({
        title: 'Oops, something went wrong. Please file a bug.',
        content: mithril('div', mithril('.modal-logs', errMessage), mithril('span', `Please provide any additional details describing
           how the crash occurred:`), mithril('textarea.modal-textarea', {
            rows: 3,
            maxlength: 1000,
            oninput: (ev) => {
                userDescription = ev.target.value;
            },
            onkeydown: (e) => {
                e.stopPropagation();
            },
            onkeyup: (e) => {
                e.stopPropagation();
            },
        }), shareTraceSection),
        buttons: [
            {
                text: 'File a bug (Googlers only)',
                primary: true,
                id: 'file_bug',
                action: () => {
                    window.open(createLink(errTitle, errMessage, userDescription), '_blank');
                }
            },
        ]
    });
}
// If there is a trace URL to share, we don't have to show the upload checkbox.
function urlExists() {
    const engine = Object.values(globals$1.globals.state.engines)[0];
    return engine !== undefined &&
        (engine.source.type === 'ARRAY_BUFFER' || engine.source.type === 'URL') &&
        engine.source.url !== undefined;
}
function createErrorMessage(errLog, checked, url) {
    let errMessage = '';
    const engine = Object.values(globals$1.globals.state.engines)[0];
    if (checked && url !== undefined) {
        errMessage += `Trace: ${url}`;
    }
    else if (urlExists()) {
        errMessage += `Trace: ${engine.source.url}`;
    }
    else {
        errMessage += 'To assist with debugging please attach or link to the ' +
            'trace you were viewing.';
    }
    return errMessage + '\n\n' +
        'Viewed on: ' + self.location.origin + '\n\n' + errLog;
}
function createLink(errTitle, errMessage, userDescription) {
    let link = 'https://goto.google.com/perfetto-ui-bug';
    link += '?title=' + encodeURIComponent(`UI Error: ${errTitle}`);
    link += '&description=';
    if (userDescription !== '') {
        link +=
            encodeURIComponent('User description:\n' + userDescription + '\n\n');
    }
    link += encodeURIComponent(errMessage);
    // 8kb is common limit on request size so restrict links to that long:
    return link.substr(0, 8000);
}
function showOutOfMemoryDialog() {
    const url = 'https://perfetto.dev/docs/quickstart/trace-analysis#get-trace-processor';
    const tpCmd = 'curl -LO https://get.perfetto.dev/trace_processor\n' +
        'chmod +x ./trace_processor\n' +
        'trace_processor --httpd /path/to/trace.pftrace\n' +
        '# Reload the UI, it will prompt to use the HTTP+RPC interface';
    modal.showModal({
        title: 'Oops! Your WASM trace processor ran out of memory',
        content: mithril('div', mithril('span', 'The in-memory representation of the trace is too big ' +
            'for the browser memory limits (typically 2GB per tab).'), mithril('br'), mithril('span', 'You can work around this problem by using the trace_processor ' +
            'native binary as an accelerator for the UI as follows:'), mithril('br'), mithril('br'), mithril('.modal-bash', tpCmd), mithril('br'), mithril('span', 'For details see '), mithril('a', { href: url, target: '_blank' }, url)),
        buttons: []
    });
}
function showUnknownFileError() {
    modal.showModal({
        title: 'Cannot open this file',
        content: mithril('div', mithril('p', 'The file opened doesn\'t look like a Perfetto trace or any ' +
            'other format recognized by the Perfetto TraceProcessor.'), mithril('p', 'Formats supported:'), mithril('ul', mithril('li', 'Perfetto protobuf trace'), mithril('li', 'chrome://tracing JSON'), mithril('li', 'Android systrace'), mithril('li', 'Fuchsia trace'), mithril('li', 'Ninja build log'))),
        buttons: []
    });
}
function showWebUSBError() {
    modal.showModal({
        title: 'A WebUSB error occurred',
        content: mithril('div', mithril('span', `Is adb already running on the host? Run this command and
      try again.`), mithril('br'), mithril('.modal-bash', '> adb kill-server'), mithril('br'), mithril('span', 'For details see '), mithril('a', { href: 'http://b/159048331', target: '_blank' }, 'b/159048331')),
        buttons: []
    });
}

});

var file_drop_handler = createCommonjsModule(function (module, exports) {
// 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.
Object.defineProperty(exports, "__esModule", { value: true });
exports.installFileDropHandler = void 0;


let lastDragTarget = null;
function installFileDropHandler() {
    window.ondragenter = (evt) => {
        evt.preventDefault();
        evt.stopPropagation();
        lastDragTarget = evt.target;
        if (dragEventHasFiles(evt)) {
            document.body.classList.add('filedrag');
        }
    };
    window.ondragleave = (evt) => {
        evt.preventDefault();
        evt.stopPropagation();
        if (evt.target === lastDragTarget) {
            document.body.classList.remove('filedrag');
        }
    };
    window.ondrop = (evt) => {
        evt.preventDefault();
        evt.stopPropagation();
        document.body.classList.remove('filedrag');
        if (evt.dataTransfer && dragEventHasFiles(evt)) {
            const file = evt.dataTransfer.files[0];
            if (file) {
                globals$1.globals.frontendLocalState.localOnlyMode = false;
                globals$1.globals.dispatch(actions.Actions.openTraceFromFile({ file }));
            }
        }
        evt.preventDefault();
    };
    window.ondragover = (evt) => {
        evt.preventDefault();
        evt.stopPropagation();
    };
}
exports.installFileDropHandler = installFileDropHandler;
function dragEventHasFiles(event) {
    if (event.dataTransfer && event.dataTransfer.types) {
        for (const type of event.dataTransfer.types) {
            if (type === 'Files')
                return true;
        }
    }
    return false;
}

});

var home_page = createCommonjsModule(function (module, exports) {
// 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.
Object.defineProperty(exports, "__esModule", { value: true });
exports.HomePage = void 0;



let channelChanged = false;
exports.HomePage = pages.createPage({
    view() {
        return mithril('.page.home-page', mithril('.home-page-center', mithril('.home-page-title', 'Perfetto'), mithril(`img.logo[src=${globals$1.globals.root}assets/logo-3d.png]`), mithril('div.channel-select', mithril('div', 'Feeling adventurous? Try our bleeding edge Canary version'), mithril('fieldset', mkChan('stable'), mkChan('canary'), mithril('.highlight')), mithril(`.home-page-reload${channelChanged ? '.show' : ''}`, 'You need to reload the page for the changes to have effect'))), mithril('a.privacy', { href: 'https://policies.google.com/privacy', target: '_blank' }, 'Privacy policy'));
    }
});
function mkChan(chan) {
    const checked = !channelChanged && globals$1.globals.channel === chan ? '[checked=true]' : '';
    return [
        mithril(`input[type=radio][name=chan][id=chan_${chan}]${checked}`, { onchange: () => changeChannel(chan) }),
        mithril(`label[for=chan_${chan}]`, chan),
    ];
}
function changeChannel(chan) {
    localStorage.setItem('perfettoUiChannel', chan);
    channelChanged = true;
    globals$1.globals.rafScheduler.scheduleFullRedraw();
}

});

var live_reload = createCommonjsModule(function (module, exports) {
// Copyright (C) 2021 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.
Object.defineProperty(exports, "__esModule", { value: true });
exports.initLiveReloadIfLocalhost = void 0;
let lastReloadDialogTime = 0;
const kMinTimeBetweenDialogsMs = 10000;
const changedPaths = new Set();
function initLiveReloadIfLocalhost() {
    if (!location.origin.startsWith('http://localhost:') ||
        location.origin.endsWith('9001'))
        return;
    const monitor = new EventSource('/live_reload');
    monitor.onmessage = msg => {
        const change = msg.data;
        console.log('Live reload:', change);
        changedPaths.add(change);
        if (change.endsWith('.css')) {
            reloadCSS();
        }
        else if (change.endsWith('.html') || change.endsWith('.js')) {
            reloadDelayed();
        }
    };
    monitor.onerror = (err) => {
        // In most cases the error is fired on reload, when the socket disconnects.
        // Delay the error and the reconnection, so in the case of a reload we don't
        // see any midleading message.
        setTimeout(() => console.error('LiveReload SSE error', err), 1000);
    };
}
exports.initLiveReloadIfLocalhost = initLiveReloadIfLocalhost;
function reloadCSS() {
    const css = document.querySelector('link[rel=stylesheet]');
    if (!css)
        return;
    const parent = css.parentElement;
    parent.removeChild(css);
    parent.appendChild(css);
}
function reloadDelayed() {
    setTimeout(() => {
        let pathsStr = '';
        for (const path of changedPaths) {
            pathsStr += path + '\n';
        }
        changedPaths.clear();
        if (Date.now() - lastReloadDialogTime < kMinTimeBetweenDialogsMs)
            return;
        const reload = confirm(`${pathsStr}changed, click to reload`);
        lastReloadDialogTime = Date.now();
        if (reload) {
            window.location.reload();
        }
    }, 1000);
}

});

var metrics_page = createCommonjsModule(function (module, exports) {
// Copyright (C) 2020 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.
Object.defineProperty(exports, "__esModule", { value: true });
exports.MetricsPage = void 0;




function getCurrSelectedMetric() {
    const { availableMetrics, selectedIndex } = globals$1.globals.state.metrics;
    if (!availableMetrics)
        return undefined;
    if (selectedIndex === undefined)
        return undefined;
    return availableMetrics[selectedIndex];
}
class MetricResult {
    view() {
        const metricResult = globals$1.globals.metricResult;
        if (metricResult === undefined)
            return undefined;
        const currSelection = getCurrSelectedMetric();
        if (!(metricResult && metricResult.name === currSelection)) {
            return undefined;
        }
        if (metricResult.error !== undefined) {
            return mithril('pre.metric-error', metricResult.error);
        }
        if (metricResult.resultString !== undefined) {
            return mithril('pre', metricResult.resultString);
        }
        return undefined;
    }
}
class MetricPicker {
    view() {
        const { availableMetrics, selectedIndex } = globals$1.globals.state.metrics;
        if (availableMetrics === undefined)
            return 'Loading metrics...';
        if (availableMetrics.length === 0)
            return 'No metrics available';
        if (selectedIndex === undefined) {
            throw Error('Should not happen when avaibleMetrics is non-empty');
        }
        return mithril('div', [
            'Select a metric:',
            mithril('select', {
                selectedIndex: globals$1.globals.state.metrics.selectedIndex,
                onchange: (e) => {
                    globals$1.globals.dispatch(actions.Actions.setMetricSelectedIndex({ index: e.target.selectedIndex }));
                },
            }, availableMetrics.map(metric => mithril('option', { value: metric, key: metric }, metric))),
            mithril('button.metric-run-button', { onclick: () => globals$1.globals.dispatch(actions.Actions.requestSelectedMetric({})) }, 'Run'),
        ]);
    }
}
exports.MetricsPage = pages.createPage({
    view() {
        return mithril('.metrics-page', mithril(MetricPicker), mithril(MetricResult));
    }
});

});

var post_message_handler = createCommonjsModule(function (module, exports) {
// Copyright (C) 2019 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.
Object.defineProperty(exports, "__esModule", { value: true });
exports.postMessageHandler = void 0;




// Returns whether incoming traces should be opened automatically or should
// instead require a user interaction.
function isTrustedOrigin(origin) {
    const TRUSTED_ORIGINS = [
        'https://chrometto.googleplex.com',
        'https://uma.googleplex.com',
    ];
    if (TRUSTED_ORIGINS.includes(origin))
        return true;
    if (new URL(origin).hostname.endsWith('corp.google.com'))
        return true;
    return false;
}
// The message handler supports loading traces from an ArrayBuffer.
// There is no other requirement than sending the ArrayBuffer as the |data|
// property. However, since this will happen across different origins, it is not
// possible for the source website to inspect whether the message handler is
// ready, so the message handler always replies to a 'PING' message with 'PONG',
// which indicates it is ready to receive a trace.
function postMessageHandler(messageEvent) {
    if (messageEvent.origin === 'https://tagassistant.google.com') {
        // The GA debugger, does a window.open() and sends messages to the GA
        // script. Ignore them.
        return;
    }
    if (document.readyState !== 'complete') {
        console.error('Ignoring message - document not ready yet.');
        return;
    }
    if (messageEvent.source === null || messageEvent.source !== window.opener) {
        // This can happen if an extension tries to postMessage.
        return;
    }
    if (!('data' in messageEvent)) {
        throw new Error('Incoming message has no data property');
    }
    if (messageEvent.data === 'PING') {
        // Cross-origin messaging means we can't read |messageEvent.source|, but
        // it still needs to be of the correct type to be able to invoke the
        // correct version of postMessage(...).
        const windowSource = messageEvent.source;
        windowSource.postMessage('PONG', messageEvent.origin);
        return;
    }
    let postedTrace;
    if (isPostedTraceWrapped(messageEvent.data)) {
        postedTrace = sanitizePostedTrace(messageEvent.data.perfetto);
    }
    else if (messageEvent.data instanceof ArrayBuffer) {
        postedTrace = { title: 'External trace', buffer: messageEvent.data };
    }
    else {
        console.warn('Unknown postMessage() event received. If you are trying to open a ' +
            'trace via postMessage(), this is a bug in your code. If not, this ' +
            'could be due to some Chrome extension.');
        console.log('origin:', messageEvent.origin, 'data:', messageEvent.data);
        return;
    }
    if (postedTrace.buffer.byteLength === 0) {
        throw new Error('Incoming message trace buffer is empty');
    }
    const openTrace = () => {
        // For external traces, we need to disable other features such as
        // downloading and sharing a trace.
        globals$1.globals.frontendLocalState.localOnlyMode = true;
        globals$1.globals.dispatch(actions.Actions.openTraceFromBuffer(postedTrace));
    };
    // If the origin is trusted open the trace directly.
    if (isTrustedOrigin(messageEvent.origin)) {
        openTrace();
        return;
    }
    // If not ask the user if they expect this and trust the origin.
    modal.showModal({
        title: 'Open trace?',
        content: mithril('div', mithril('div', `${messageEvent.origin} is trying to open a trace file.`), mithril('div', 'Do you trust the origin and want to proceed?')),
        buttons: [
            { text: 'NO', primary: true, id: 'pm_reject_trace', action: () => { } },
            { text: 'YES', primary: false, id: 'pm_open_trace', action: openTrace },
        ],
    });
}
exports.postMessageHandler = postMessageHandler;
function sanitizePostedTrace(postedTrace) {
    const result = {
        title: sanitizeString(postedTrace.title),
        buffer: postedTrace.buffer
    };
    if (postedTrace.url !== undefined) {
        result.url = sanitizeString(postedTrace.url);
    }
    return result;
}
function sanitizeString(str) {
    return str.replace(/[^A-Za-z0-9.\-_#:/?=&;% ]/g, ' ');
}
// tslint:disable:no-any
function isPostedTraceWrapped(obj) {
    const wrapped = obj;
    if (wrapped.perfetto === undefined) {
        return false;
    }
    return wrapped.perfetto.buffer !== undefined &&
        wrapped.perfetto.title !== undefined;
}

});

var aspromise = asPromise;

/**
 * Callback as used by {@link util.asPromise}.
 * @typedef asPromiseCallback
 * @type {function}
 * @param {Error|null} error Error, if any
 * @param {...*} params Additional arguments
 * @returns {undefined}
 */

/**
 * Returns a promise from a node-style callback function.
 * @memberof util
 * @param {asPromiseCallback} fn Function to call
 * @param {*} ctx Function context
 * @param {...*} params Function arguments
 * @returns {Promise<*>} Promisified function
 */
function asPromise(fn, ctx/*, varargs */) {
    var params  = new Array(arguments.length - 1),
        offset  = 0,
        index   = 2,
        pending = true;
    while (index < arguments.length)
        params[offset++] = arguments[index++];
    return new Promise(function executor(resolve, reject) {
        params[offset] = function callback(err/*, varargs */) {
            if (pending) {
                pending = false;
                if (err)
                    reject(err);
                else {
                    var params = new Array(arguments.length - 1),
                        offset = 0;
                    while (offset < params.length)
                        params[offset++] = arguments[offset];
                    resolve.apply(null, params);
                }
            }
        };
        try {
            fn.apply(ctx || null, params);
        } catch (err) {
            if (pending) {
                pending = false;
                reject(err);
            }
        }
    });
}

var base64_1 = createCommonjsModule(function (module, exports) {

/**
 * A minimal base64 implementation for number arrays.
 * @memberof util
 * @namespace
 */
var base64 = exports;

/**
 * Calculates the byte length of a base64 encoded string.
 * @param {string} string Base64 encoded string
 * @returns {number} Byte length
 */
base64.length = function length(string) {
    var p = string.length;
    if (!p)
        return 0;
    var n = 0;
    while (--p % 4 > 1 && string.charAt(p) === "=")
        ++n;
    return Math.ceil(string.length * 3) / 4 - n;
};

// Base64 encoding table
var b64 = new Array(64);

// Base64 decoding table
var s64 = new Array(123);

// 65..90, 97..122, 48..57, 43, 47
for (var i = 0; i < 64;)
    s64[b64[i] = i < 26 ? i + 65 : i < 52 ? i + 71 : i < 62 ? i - 4 : i - 59 | 43] = i++;

/**
 * Encodes a buffer to a base64 encoded string.
 * @param {Uint8Array} buffer Source buffer
 * @param {number} start Source start
 * @param {number} end Source end
 * @returns {string} Base64 encoded string
 */
base64.encode = function encode(buffer, start, end) {
    var parts = null,
        chunk = [];
    var i = 0, // output index
        j = 0, // goto index
        t;     // temporary
    while (start < end) {
        var b = buffer[start++];
        switch (j) {
            case 0:
                chunk[i++] = b64[b >> 2];
                t = (b & 3) << 4;
                j = 1;
                break;
            case 1:
                chunk[i++] = b64[t | b >> 4];
                t = (b & 15) << 2;
                j = 2;
                break;
            case 2:
                chunk[i++] = b64[t | b >> 6];
                chunk[i++] = b64[b & 63];
                j = 0;
                break;
        }
        if (i > 8191) {
            (parts || (parts = [])).push(String.fromCharCode.apply(String, chunk));
            i = 0;
        }
    }
    if (j) {
        chunk[i++] = b64[t];
        chunk[i++] = 61;
        if (j === 1)
            chunk[i++] = 61;
    }
    if (parts) {
        if (i)
            parts.push(String.fromCharCode.apply(String, chunk.slice(0, i)));
        return parts.join("");
    }
    return String.fromCharCode.apply(String, chunk.slice(0, i));
};

var invalidEncoding = "invalid encoding";

/**
 * Decodes a base64 encoded string to a buffer.
 * @param {string} string Source string
 * @param {Uint8Array} buffer Destination buffer
 * @param {number} offset Destination offset
 * @returns {number} Number of bytes written
 * @throws {Error} If encoding is invalid
 */
base64.decode = function decode(string, buffer, offset) {
    var start = offset;
    var j = 0, // goto index
        t;     // temporary
    for (var i = 0; i < string.length;) {
        var c = string.charCodeAt(i++);
        if (c === 61 && j > 1)
            break;
        if ((c = s64[c]) === undefined)
            throw Error(invalidEncoding);
        switch (j) {
            case 0:
                t = c;
                j = 1;
                break;
            case 1:
                buffer[offset++] = t << 2 | (c & 48) >> 4;
                t = c;
                j = 2;
                break;
            case 2:
                buffer[offset++] = (t & 15) << 4 | (c & 60) >> 2;
                t = c;
                j = 3;
                break;
            case 3:
                buffer[offset++] = (t & 3) << 6 | c;
                j = 0;
                break;
        }
    }
    if (j === 1)
        throw Error(invalidEncoding);
    return offset - start;
};

/**
 * Tests if the specified string appears to be base64 encoded.
 * @param {string} string String to test
 * @returns {boolean} `true` if probably base64 encoded, otherwise false
 */
base64.test = function test(string) {
    return /^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/.test(string);
};
});

var eventemitter = EventEmitter;

/**
 * Constructs a new event emitter instance.
 * @classdesc A minimal event emitter.
 * @memberof util
 * @constructor
 */
function EventEmitter() {

    /**
     * Registered listeners.
     * @type {Object.<string,*>}
     * @private
     */
    this._listeners = {};
}

/**
 * Registers an event listener.
 * @param {string} evt Event name
 * @param {function} fn Listener
 * @param {*} [ctx] Listener context
 * @returns {util.EventEmitter} `this`
 */
EventEmitter.prototype.on = function on(evt, fn, ctx) {
    (this._listeners[evt] || (this._listeners[evt] = [])).push({
        fn  : fn,
        ctx : ctx || this
    });
    return this;
};

/**
 * Removes an event listener or any matching listeners if arguments are omitted.
 * @param {string} [evt] Event name. Removes all listeners if omitted.
 * @param {function} [fn] Listener to remove. Removes all listeners of `evt` if omitted.
 * @returns {util.EventEmitter} `this`
 */
EventEmitter.prototype.off = function off(evt, fn) {
    if (evt === undefined)
        this._listeners = {};
    else {
        if (fn === undefined)
            this._listeners[evt] = [];
        else {
            var listeners = this._listeners[evt];
            for (var i = 0; i < listeners.length;)
                if (listeners[i].fn === fn)
                    listeners.splice(i, 1);
                else
                    ++i;
        }
    }
    return this;
};

/**
 * Emits an event by calling its listeners with the specified arguments.
 * @param {string} evt Event name
 * @param {...*} args Arguments
 * @returns {util.EventEmitter} `this`
 */
EventEmitter.prototype.emit = function emit(evt) {
    var listeners = this._listeners[evt];
    if (listeners) {
        var args = [],
            i = 1;
        for (; i < arguments.length;)
            args.push(arguments[i++]);
        for (i = 0; i < listeners.length;)
            listeners[i].fn.apply(listeners[i++].ctx, args);
    }
    return this;
};

var float_1 = factory(factory);

/**
 * Reads / writes floats / doubles from / to buffers.
 * @name util.float
 * @namespace
 */

/**
 * Writes a 32 bit float to a buffer using little endian byte order.
 * @name util.float.writeFloatLE
 * @function
 * @param {number} val Value to write
 * @param {Uint8Array} buf Target buffer
 * @param {number} pos Target buffer offset
 * @returns {undefined}
 */

/**
 * Writes a 32 bit float to a buffer using big endian byte order.
 * @name util.float.writeFloatBE
 * @function
 * @param {number} val Value to write
 * @param {Uint8Array} buf Target buffer
 * @param {number} pos Target buffer offset
 * @returns {undefined}
 */

/**
 * Reads a 32 bit float from a buffer using little endian byte order.
 * @name util.float.readFloatLE
 * @function
 * @param {Uint8Array} buf Source buffer
 * @param {number} pos Source buffer offset
 * @returns {number} Value read
 */

/**
 * Reads a 32 bit float from a buffer using big endian byte order.
 * @name util.float.readFloatBE
 * @function
 * @param {Uint8Array} buf Source buffer
 * @param {number} pos Source buffer offset
 * @returns {number} Value read
 */

/**
 * Writes a 64 bit double to a buffer using little endian byte order.
 * @name util.float.writeDoubleLE
 * @function
 * @param {number} val Value to write
 * @param {Uint8Array} buf Target buffer
 * @param {number} pos Target buffer offset
 * @returns {undefined}
 */

/**
 * Writes a 64 bit double to a buffer using big endian byte order.
 * @name util.float.writeDoubleBE
 * @function
 * @param {number} val Value to write
 * @param {Uint8Array} buf Target buffer
 * @param {number} pos Target buffer offset
 * @returns {undefined}
 */

/**
 * Reads a 64 bit double from a buffer using little endian byte order.
 * @name util.float.readDoubleLE
 * @function
 * @param {Uint8Array} buf Source buffer
 * @param {number} pos Source buffer offset
 * @returns {number} Value read
 */

/**
 * Reads a 64 bit double from a buffer using big endian byte order.
 * @name util.float.readDoubleBE
 * @function
 * @param {Uint8Array} buf Source buffer
 * @param {number} pos Source buffer offset
 * @returns {number} Value read
 */

// Factory function for the purpose of node-based testing in modified global environments
function factory(exports) {

    // float: typed array
    if (typeof Float32Array !== "undefined") (function() {

        var f32 = new Float32Array([ -0 ]),
            f8b = new Uint8Array(f32.buffer),
            le  = f8b[3] === 128;

        function writeFloat_f32_cpy(val, buf, pos) {
            f32[0] = val;
            buf[pos    ] = f8b[0];
            buf[pos + 1] = f8b[1];
            buf[pos + 2] = f8b[2];
            buf[pos + 3] = f8b[3];
        }

        function writeFloat_f32_rev(val, buf, pos) {
            f32[0] = val;
            buf[pos    ] = f8b[3];
            buf[pos + 1] = f8b[2];
            buf[pos + 2] = f8b[1];
            buf[pos + 3] = f8b[0];
        }

        /* istanbul ignore next */
        exports.writeFloatLE = le ? writeFloat_f32_cpy : writeFloat_f32_rev;
        /* istanbul ignore next */
        exports.writeFloatBE = le ? writeFloat_f32_rev : writeFloat_f32_cpy;

        function readFloat_f32_cpy(buf, pos) {
            f8b[0] = buf[pos    ];
            f8b[1] = buf[pos + 1];
            f8b[2] = buf[pos + 2];
            f8b[3] = buf[pos + 3];
            return f32[0];
        }

        function readFloat_f32_rev(buf, pos) {
            f8b[3] = buf[pos    ];
            f8b[2] = buf[pos + 1];
            f8b[1] = buf[pos + 2];
            f8b[0] = buf[pos + 3];
            return f32[0];
        }

        /* istanbul ignore next */
        exports.readFloatLE = le ? readFloat_f32_cpy : readFloat_f32_rev;
        /* istanbul ignore next */
        exports.readFloatBE = le ? readFloat_f32_rev : readFloat_f32_cpy;

    // float: ieee754
    })(); else (function() {

        function writeFloat_ieee754(writeUint, val, buf, pos) {
            var sign = val < 0 ? 1 : 0;
            if (sign)
                val = -val;
            if (val === 0)
                writeUint(1 / val > 0 ? /* positive */ 0 : /* negative 0 */ 2147483648, buf, pos);
            else if (isNaN(val))
                writeUint(2143289344, buf, pos);
            else if (val > 3.4028234663852886e+38) // +-Infinity
                writeUint((sign << 31 | 2139095040) >>> 0, buf, pos);
            else if (val < 1.1754943508222875e-38) // denormal
                writeUint((sign << 31 | Math.round(val / 1.401298464324817e-45)) >>> 0, buf, pos);
            else {
                var exponent = Math.floor(Math.log(val) / Math.LN2),
                    mantissa = Math.round(val * Math.pow(2, -exponent) * 8388608) & 8388607;
                writeUint((sign << 31 | exponent + 127 << 23 | mantissa) >>> 0, buf, pos);
            }
        }

        exports.writeFloatLE = writeFloat_ieee754.bind(null, writeUintLE);
        exports.writeFloatBE = writeFloat_ieee754.bind(null, writeUintBE);

        function readFloat_ieee754(readUint, buf, pos) {
            var uint = readUint(buf, pos),
                sign = (uint >> 31) * 2 + 1,
                exponent = uint >>> 23 & 255,
                mantissa = uint & 8388607;
            return exponent === 255
                ? mantissa
                ? NaN
                : sign * Infinity
                : exponent === 0 // denormal
                ? sign * 1.401298464324817e-45 * mantissa
                : sign * Math.pow(2, exponent - 150) * (mantissa + 8388608);
        }

        exports.readFloatLE = readFloat_ieee754.bind(null, readUintLE);
        exports.readFloatBE = readFloat_ieee754.bind(null, readUintBE);

    })();

    // double: typed array
    if (typeof Float64Array !== "undefined") (function() {

        var f64 = new Float64Array([-0]),
            f8b = new Uint8Array(f64.buffer),
            le  = f8b[7] === 128;

        function writeDouble_f64_cpy(val, buf, pos) {
            f64[0] = val;
            buf[pos    ] = f8b[0];
            buf[pos + 1] = f8b[1];
            buf[pos + 2] = f8b[2];
            buf[pos + 3] = f8b[3];
            buf[pos + 4] = f8b[4];
            buf[pos + 5] = f8b[5];
            buf[pos + 6] = f8b[6];
            buf[pos + 7] = f8b[7];
        }

        function writeDouble_f64_rev(val, buf, pos) {
            f64[0] = val;
            buf[pos    ] = f8b[7];
            buf[pos + 1] = f8b[6];
            buf[pos + 2] = f8b[5];
            buf[pos + 3] = f8b[4];
            buf[pos + 4] = f8b[3];
            buf[pos + 5] = f8b[2];
            buf[pos + 6] = f8b[1];
            buf[pos + 7] = f8b[0];
        }

        /* istanbul ignore next */
        exports.writeDoubleLE = le ? writeDouble_f64_cpy : writeDouble_f64_rev;
        /* istanbul ignore next */
        exports.writeDoubleBE = le ? writeDouble_f64_rev : writeDouble_f64_cpy;

        function readDouble_f64_cpy(buf, pos) {
            f8b[0] = buf[pos    ];
            f8b[1] = buf[pos + 1];
            f8b[2] = buf[pos + 2];
            f8b[3] = buf[pos + 3];
            f8b[4] = buf[pos + 4];
            f8b[5] = buf[pos + 5];
            f8b[6] = buf[pos + 6];
            f8b[7] = buf[pos + 7];
            return f64[0];
        }

        function readDouble_f64_rev(buf, pos) {
            f8b[7] = buf[pos    ];
            f8b[6] = buf[pos + 1];
            f8b[5] = buf[pos + 2];
            f8b[4] = buf[pos + 3];
            f8b[3] = buf[pos + 4];
            f8b[2] = buf[pos + 5];
            f8b[1] = buf[pos + 6];
            f8b[0] = buf[pos + 7];
            return f64[0];
        }

        /* istanbul ignore next */
        exports.readDoubleLE = le ? readDouble_f64_cpy : readDouble_f64_rev;
        /* istanbul ignore next */
        exports.readDoubleBE = le ? readDouble_f64_rev : readDouble_f64_cpy;

    // double: ieee754
    })(); else (function() {

        function writeDouble_ieee754(writeUint, off0, off1, val, buf, pos) {
            var sign = val < 0 ? 1 : 0;
            if (sign)
                val = -val;
            if (val === 0) {
                writeUint(0, buf, pos + off0);
                writeUint(1 / val > 0 ? /* positive */ 0 : /* negative 0 */ 2147483648, buf, pos + off1);
            } else if (isNaN(val)) {
                writeUint(0, buf, pos + off0);
                writeUint(2146959360, buf, pos + off1);
            } else if (val > 1.7976931348623157e+308) { // +-Infinity
                writeUint(0, buf, pos + off0);
                writeUint((sign << 31 | 2146435072) >>> 0, buf, pos + off1);
            } else {
                var mantissa;
                if (val < 2.2250738585072014e-308) { // denormal
                    mantissa = val / 5e-324;
                    writeUint(mantissa >>> 0, buf, pos + off0);
                    writeUint((sign << 31 | mantissa / 4294967296) >>> 0, buf, pos + off1);
                } else {
                    var exponent = Math.floor(Math.log(val) / Math.LN2);
                    if (exponent === 1024)
                        exponent = 1023;
                    mantissa = val * Math.pow(2, -exponent);
                    writeUint(mantissa * 4503599627370496 >>> 0, buf, pos + off0);
                    writeUint((sign << 31 | exponent + 1023 << 20 | mantissa * 1048576 & 1048575) >>> 0, buf, pos + off1);
                }
            }
        }

        exports.writeDoubleLE = writeDouble_ieee754.bind(null, writeUintLE, 0, 4);
        exports.writeDoubleBE = writeDouble_ieee754.bind(null, writeUintBE, 4, 0);

        function readDouble_ieee754(readUint, off0, off1, buf, pos) {
            var lo = readUint(buf, pos + off0),
                hi = readUint(buf, pos + off1);
            var sign = (hi >> 31) * 2 + 1,
                exponent = hi >>> 20 & 2047,
                mantissa = 4294967296 * (hi & 1048575) + lo;
            return exponent === 2047
                ? mantissa
                ? NaN
                : sign * Infinity
                : exponent === 0 // denormal
                ? sign * 5e-324 * mantissa
                : sign * Math.pow(2, exponent - 1075) * (mantissa + 4503599627370496);
        }

        exports.readDoubleLE = readDouble_ieee754.bind(null, readUintLE, 0, 4);
        exports.readDoubleBE = readDouble_ieee754.bind(null, readUintBE, 4, 0);

    })();

    return exports;
}

// uint helpers

function writeUintLE(val, buf, pos) {
    buf[pos    ] =  val        & 255;
    buf[pos + 1] =  val >>> 8  & 255;
    buf[pos + 2] =  val >>> 16 & 255;
    buf[pos + 3] =  val >>> 24;
}

function writeUintBE(val, buf, pos) {
    buf[pos    ] =  val >>> 24;
    buf[pos + 1] =  val >>> 16 & 255;
    buf[pos + 2] =  val >>> 8  & 255;
    buf[pos + 3] =  val        & 255;
}

function readUintLE(buf, pos) {
    return (buf[pos    ]
          | buf[pos + 1] << 8
          | buf[pos + 2] << 16
          | buf[pos + 3] << 24) >>> 0;
}

function readUintBE(buf, pos) {
    return (buf[pos    ] << 24
          | buf[pos + 1] << 16
          | buf[pos + 2] << 8
          | buf[pos + 3]) >>> 0;
}

var inquire_1 = inquire;

/**
 * Requires a module only if available.
 * @memberof util
 * @param {string} moduleName Module to require
 * @returns {?Object} Required module if available and not empty, otherwise `null`
 */
function inquire(moduleName) {
    try {
        var mod = undefined; // eslint-disable-line no-eval
        if (mod && (mod.length || Object.keys(mod).length))
            return mod;
    } catch (e) {} // eslint-disable-line no-empty
    return null;
}

var utf8_1 = createCommonjsModule(function (module, exports) {

/**
 * A minimal UTF8 implementation for number arrays.
 * @memberof util
 * @namespace
 */
var utf8 = exports;

/**
 * Calculates the UTF8 byte length of a string.
 * @param {string} string String
 * @returns {number} Byte length
 */
utf8.length = function utf8_length(string) {
    var len = 0,
        c = 0;
    for (var i = 0; i < string.length; ++i) {
        c = string.charCodeAt(i);
        if (c < 128)
            len += 1;
        else if (c < 2048)
            len += 2;
        else if ((c & 0xFC00) === 0xD800 && (string.charCodeAt(i + 1) & 0xFC00) === 0xDC00) {
            ++i;
            len += 4;
        } else
            len += 3;
    }
    return len;
};

/**
 * Reads UTF8 bytes as a string.
 * @param {Uint8Array} buffer Source buffer
 * @param {number} start Source start
 * @param {number} end Source end
 * @returns {string} String read
 */
utf8.read = function utf8_read(buffer, start, end) {
    var len = end - start;
    if (len < 1)
        return "";
    var parts = null,
        chunk = [],
        i = 0, // char offset
        t;     // temporary
    while (start < end) {
        t = buffer[start++];
        if (t < 128)
            chunk[i++] = t;
        else if (t > 191 && t < 224)
            chunk[i++] = (t & 31) << 6 | buffer[start++] & 63;
        else if (t > 239 && t < 365) {
            t = ((t & 7) << 18 | (buffer[start++] & 63) << 12 | (buffer[start++] & 63) << 6 | buffer[start++] & 63) - 0x10000;
            chunk[i++] = 0xD800 + (t >> 10);
            chunk[i++] = 0xDC00 + (t & 1023);
        } else
            chunk[i++] = (t & 15) << 12 | (buffer[start++] & 63) << 6 | buffer[start++] & 63;
        if (i > 8191) {
            (parts || (parts = [])).push(String.fromCharCode.apply(String, chunk));
            i = 0;
        }
    }
    if (parts) {
        if (i)
            parts.push(String.fromCharCode.apply(String, chunk.slice(0, i)));
        return parts.join("");
    }
    return String.fromCharCode.apply(String, chunk.slice(0, i));
};

/**
 * Writes a string as UTF8 bytes.
 * @param {string} string Source string
 * @param {Uint8Array} buffer Destination buffer
 * @param {number} offset Destination offset
 * @returns {number} Bytes written
 */
utf8.write = function utf8_write(string, buffer, offset) {
    var start = offset,
        c1, // character 1
        c2; // character 2
    for (var i = 0; i < string.length; ++i) {
        c1 = string.charCodeAt(i);
        if (c1 < 128) {
            buffer[offset++] = c1;
        } else if (c1 < 2048) {
            buffer[offset++] = c1 >> 6       | 192;
            buffer[offset++] = c1       & 63 | 128;
        } else if ((c1 & 0xFC00) === 0xD800 && ((c2 = string.charCodeAt(i + 1)) & 0xFC00) === 0xDC00) {
            c1 = 0x10000 + ((c1 & 0x03FF) << 10) + (c2 & 0x03FF);
            ++i;
            buffer[offset++] = c1 >> 18      | 240;
            buffer[offset++] = c1 >> 12 & 63 | 128;
            buffer[offset++] = c1 >> 6  & 63 | 128;
            buffer[offset++] = c1       & 63 | 128;
        } else {
            buffer[offset++] = c1 >> 12      | 224;
            buffer[offset++] = c1 >> 6  & 63 | 128;
            buffer[offset++] = c1       & 63 | 128;
        }
    }
    return offset - start;
};
});

var pool_1 = pool;

/**
 * An allocator as used by {@link util.pool}.
 * @typedef PoolAllocator
 * @type {function}
 * @param {number} size Buffer size
 * @returns {Uint8Array} Buffer
 */

/**
 * A slicer as used by {@link util.pool}.
 * @typedef PoolSlicer
 * @type {function}
 * @param {number} start Start offset
 * @param {number} end End offset
 * @returns {Uint8Array} Buffer slice
 * @this {Uint8Array}
 */

/**
 * A general purpose buffer pool.
 * @memberof util
 * @function
 * @param {PoolAllocator} alloc Allocator
 * @param {PoolSlicer} slice Slicer
 * @param {number} [size=8192] Slab size
 * @returns {PoolAllocator} Pooled allocator
 */
function pool(alloc, slice, size) {
    var SIZE   = size || 8192;
    var MAX    = SIZE >>> 1;
    var slab   = null;
    var offset = SIZE;
    return function pool_alloc(size) {
        if (size < 1 || size > MAX)
            return alloc(size);
        if (offset + size > SIZE) {
            slab = alloc(SIZE);
            offset = 0;
        }
        var buf = slice.call(slab, offset, offset += size);
        if (offset & 7) // align to 32 bit
            offset = (offset | 7) + 1;
        return buf;
    };
}

var longbits = LongBits;



/**
 * Constructs new long bits.
 * @classdesc Helper class for working with the low and high bits of a 64 bit value.
 * @memberof util
 * @constructor
 * @param {number} lo Low 32 bits, unsigned
 * @param {number} hi High 32 bits, unsigned
 */
function LongBits(lo, hi) {

    // note that the casts below are theoretically unnecessary as of today, but older statically
    // generated converter code might still call the ctor with signed 32bits. kept for compat.

    /**
     * Low bits.
     * @type {number}
     */
    this.lo = lo >>> 0;

    /**
     * High bits.
     * @type {number}
     */
    this.hi = hi >>> 0;
}

/**
 * Zero bits.
 * @memberof util.LongBits
 * @type {util.LongBits}
 */
var zero$2 = LongBits.zero = new LongBits(0, 0);

zero$2.toNumber = function() { return 0; };
zero$2.zzEncode = zero$2.zzDecode = function() { return this; };
zero$2.length = function() { return 1; };

/**
 * Zero hash.
 * @memberof util.LongBits
 * @type {string}
 */
var zeroHash = LongBits.zeroHash = "\0\0\0\0\0\0\0\0";

/**
 * Constructs new long bits from the specified number.
 * @param {number} value Value
 * @returns {util.LongBits} Instance
 */
LongBits.fromNumber = function fromNumber(value) {
    if (value === 0)
        return zero$2;
    var sign = value < 0;
    if (sign)
        value = -value;
    var lo = value >>> 0,
        hi = (value - lo) / 4294967296 >>> 0;
    if (sign) {
        hi = ~hi >>> 0;
        lo = ~lo >>> 0;
        if (++lo > 4294967295) {
            lo = 0;
            if (++hi > 4294967295)
                hi = 0;
        }
    }
    return new LongBits(lo, hi);
};

/**
 * Constructs new long bits from a number, long or string.
 * @param {Long|number|string} value Value
 * @returns {util.LongBits} Instance
 */
LongBits.from = function from(value) {
    if (typeof value === "number")
        return LongBits.fromNumber(value);
    if (minimal.isString(value)) {
        /* istanbul ignore else */
        if (minimal.Long)
            value = minimal.Long.fromString(value);
        else
            return LongBits.fromNumber(parseInt(value, 10));
    }
    return value.low || value.high ? new LongBits(value.low >>> 0, value.high >>> 0) : zero$2;
};

/**
 * Converts this long bits to a possibly unsafe JavaScript number.
 * @param {boolean} [unsigned=false] Whether unsigned or not
 * @returns {number} Possibly unsafe number
 */
LongBits.prototype.toNumber = function toNumber(unsigned) {
    if (!unsigned && this.hi >>> 31) {
        var lo = ~this.lo + 1 >>> 0,
            hi = ~this.hi     >>> 0;
        if (!lo)
            hi = hi + 1 >>> 0;
        return -(lo + hi * 4294967296);
    }
    return this.lo + this.hi * 4294967296;
};

/**
 * Converts this long bits to a long.
 * @param {boolean} [unsigned=false] Whether unsigned or not
 * @returns {Long} Long
 */
LongBits.prototype.toLong = function toLong(unsigned) {
    return minimal.Long
        ? new minimal.Long(this.lo | 0, this.hi | 0, Boolean(unsigned))
        /* istanbul ignore next */
        : { low: this.lo | 0, high: this.hi | 0, unsigned: Boolean(unsigned) };
};

var charCodeAt = String.prototype.charCodeAt;

/**
 * Constructs new long bits from the specified 8 characters long hash.
 * @param {string} hash Hash
 * @returns {util.LongBits} Bits
 */
LongBits.fromHash = function fromHash(hash) {
    if (hash === zeroHash)
        return zero$2;
    return new LongBits(
        ( charCodeAt.call(hash, 0)
        | charCodeAt.call(hash, 1) << 8
        | charCodeAt.call(hash, 2) << 16
        | charCodeAt.call(hash, 3) << 24) >>> 0
    ,
        ( charCodeAt.call(hash, 4)
        | charCodeAt.call(hash, 5) << 8
        | charCodeAt.call(hash, 6) << 16
        | charCodeAt.call(hash, 7) << 24) >>> 0
    );
};

/**
 * Converts this long bits to a 8 characters long hash.
 * @returns {string} Hash
 */
LongBits.prototype.toHash = function toHash() {
    return String.fromCharCode(
        this.lo        & 255,
        this.lo >>> 8  & 255,
        this.lo >>> 16 & 255,
        this.lo >>> 24      ,
        this.hi        & 255,
        this.hi >>> 8  & 255,
        this.hi >>> 16 & 255,
        this.hi >>> 24
    );
};

/**
 * Zig-zag encodes this long bits.
 * @returns {util.LongBits} `this`
 */
LongBits.prototype.zzEncode = function zzEncode() {
    var mask =   this.hi >> 31;
    this.hi  = ((this.hi << 1 | this.lo >>> 31) ^ mask) >>> 0;
    this.lo  = ( this.lo << 1                   ^ mask) >>> 0;
    return this;
};

/**
 * Zig-zag decodes this long bits.
 * @returns {util.LongBits} `this`
 */
LongBits.prototype.zzDecode = function zzDecode() {
    var mask = -(this.lo & 1);
    this.lo  = ((this.lo >>> 1 | this.hi << 31) ^ mask) >>> 0;
    this.hi  = ( this.hi >>> 1                  ^ mask) >>> 0;
    return this;
};

/**
 * Calculates the length of this longbits when encoded as a varint.
 * @returns {number} Length
 */
LongBits.prototype.length = function length() {
    var part0 =  this.lo,
        part1 = (this.lo >>> 28 | this.hi << 4) >>> 0,
        part2 =  this.hi >>> 24;
    return part2 === 0
         ? part1 === 0
           ? part0 < 16384
             ? part0 < 128 ? 1 : 2
             : part0 < 2097152 ? 3 : 4
           : part1 < 16384
             ? part1 < 128 ? 5 : 6
             : part1 < 2097152 ? 7 : 8
         : part2 < 128 ? 9 : 10;
};

var minimal = createCommonjsModule(function (module, exports) {
var util = exports;

// used to return a Promise where callback is omitted
util.asPromise = aspromise;

// converts to / from base64 encoded strings
util.base64 = base64_1;

// base class of rpc.Service
util.EventEmitter = eventemitter;

// float handling accross browsers
util.float = float_1;

// requires modules optionally and hides the call from bundlers
util.inquire = inquire_1;

// converts to / from utf8 encoded strings
util.utf8 = utf8_1;

// provides a node-like buffer pool in the browser
util.pool = pool_1;

// utility to work with the low and high bits of a 64 bit value
util.LongBits = longbits;

/**
 * Whether running within node or not.
 * @memberof util
 * @type {boolean}
 */
util.isNode = Boolean(typeof commonjsGlobal !== "undefined"
                   && commonjsGlobal
                   && commonjsGlobal.process
                   && commonjsGlobal.process.versions
                   && commonjsGlobal.process.versions.node);

/**
 * Global object reference.
 * @memberof util
 * @type {Object}
 */
util.global = util.isNode && commonjsGlobal
           || typeof window !== "undefined" && window
           || typeof self   !== "undefined" && self
           || commonjsGlobal; // eslint-disable-line no-invalid-this

/**
 * An immuable empty array.
 * @memberof util
 * @type {Array.<*>}
 * @const
 */
util.emptyArray = Object.freeze ? Object.freeze([]) : /* istanbul ignore next */ []; // used on prototypes

/**
 * An immutable empty object.
 * @type {Object}
 * @const
 */
util.emptyObject = Object.freeze ? Object.freeze({}) : /* istanbul ignore next */ {}; // used on prototypes

/**
 * Tests if the specified value is an integer.
 * @function
 * @param {*} value Value to test
 * @returns {boolean} `true` if the value is an integer
 */
util.isInteger = Number.isInteger || /* istanbul ignore next */ function isInteger(value) {
    return typeof value === "number" && isFinite(value) && Math.floor(value) === value;
};

/**
 * Tests if the specified value is a string.
 * @param {*} value Value to test
 * @returns {boolean} `true` if the value is a string
 */
util.isString = function isString(value) {
    return typeof value === "string" || value instanceof String;
};

/**
 * Tests if the specified value is a non-null object.
 * @param {*} value Value to test
 * @returns {boolean} `true` if the value is a non-null object
 */
util.isObject = function isObject(value) {
    return value && typeof value === "object";
};

/**
 * Checks if a property on a message is considered to be present.
 * This is an alias of {@link util.isSet}.
 * @function
 * @param {Object} obj Plain object or message instance
 * @param {string} prop Property name
 * @returns {boolean} `true` if considered to be present, otherwise `false`
 */
util.isset =

/**
 * Checks if a property on a message is considered to be present.
 * @param {Object} obj Plain object or message instance
 * @param {string} prop Property name
 * @returns {boolean} `true` if considered to be present, otherwise `false`
 */
util.isSet = function isSet(obj, prop) {
    var value = obj[prop];
    if (value != null && obj.hasOwnProperty(prop)) // eslint-disable-line eqeqeq, no-prototype-builtins
        return typeof value !== "object" || (Array.isArray(value) ? value.length : Object.keys(value).length) > 0;
    return false;
};

/**
 * Any compatible Buffer instance.
 * This is a minimal stand-alone definition of a Buffer instance. The actual type is that exported by node's typings.
 * @interface Buffer
 * @extends Uint8Array
 */

/**
 * Node's Buffer class if available.
 * @type {Constructor<Buffer>}
 */
util.Buffer = (function() {
    try {
        var Buffer = util.inquire("buffer").Buffer;
        // refuse to use non-node buffers if not explicitly assigned (perf reasons):
        return Buffer.prototype.utf8Write ? Buffer : /* istanbul ignore next */ null;
    } catch (e) {
        /* istanbul ignore next */
        return null;
    }
})();

// Internal alias of or polyfull for Buffer.from.
util._Buffer_from = null;

// Internal alias of or polyfill for Buffer.allocUnsafe.
util._Buffer_allocUnsafe = null;

/**
 * Creates a new buffer of whatever type supported by the environment.
 * @param {number|number[]} [sizeOrArray=0] Buffer size or number array
 * @returns {Uint8Array|Buffer} Buffer
 */
util.newBuffer = function newBuffer(sizeOrArray) {
    /* istanbul ignore next */
    return typeof sizeOrArray === "number"
        ? util.Buffer
            ? util._Buffer_allocUnsafe(sizeOrArray)
            : new util.Array(sizeOrArray)
        : util.Buffer
            ? util._Buffer_from(sizeOrArray)
            : typeof Uint8Array === "undefined"
                ? sizeOrArray
                : new Uint8Array(sizeOrArray);
};

/**
 * Array implementation used in the browser. `Uint8Array` if supported, otherwise `Array`.
 * @type {Constructor<Uint8Array>}
 */
util.Array = typeof Uint8Array !== "undefined" ? Uint8Array /* istanbul ignore next */ : Array;

/**
 * Any compatible Long instance.
 * This is a minimal stand-alone definition of a Long instance. The actual type is that exported by long.js.
 * @interface Long
 * @property {number} low Low bits
 * @property {number} high High bits
 * @property {boolean} unsigned Whether unsigned or not
 */

/**
 * Long.js's Long class if available.
 * @type {Constructor<Long>}
 */
util.Long = /* istanbul ignore next */ util.global.dcodeIO && /* istanbul ignore next */ util.global.dcodeIO.Long
         || /* istanbul ignore next */ util.global.Long
         || util.inquire("long");

/**
 * Regular expression used to verify 2 bit (`bool`) map keys.
 * @type {RegExp}
 * @const
 */
util.key2Re = /^true|false|0|1$/;

/**
 * Regular expression used to verify 32 bit (`int32` etc.) map keys.
 * @type {RegExp}
 * @const
 */
util.key32Re = /^-?(?:0|[1-9][0-9]*)$/;

/**
 * Regular expression used to verify 64 bit (`int64` etc.) map keys.
 * @type {RegExp}
 * @const
 */
util.key64Re = /^(?:[\\x00-\\xff]{8}|-?(?:0|[1-9][0-9]*))$/;

/**
 * Converts a number or long to an 8 characters long hash string.
 * @param {Long|number} value Value to convert
 * @returns {string} Hash
 */
util.longToHash = function longToHash(value) {
    return value
        ? util.LongBits.from(value).toHash()
        : util.LongBits.zeroHash;
};

/**
 * Converts an 8 characters long hash string to a long or number.
 * @param {string} hash Hash
 * @param {boolean} [unsigned=false] Whether unsigned or not
 * @returns {Long|number} Original value
 */
util.longFromHash = function longFromHash(hash, unsigned) {
    var bits = util.LongBits.fromHash(hash);
    if (util.Long)
        return util.Long.fromBits(bits.lo, bits.hi, unsigned);
    return bits.toNumber(Boolean(unsigned));
};

/**
 * Merges the properties of the source object into the destination object.
 * @memberof util
 * @param {Object.<string,*>} dst Destination object
 * @param {Object.<string,*>} src Source object
 * @param {boolean} [ifNotSet=false] Merges only if the key is not already set
 * @returns {Object.<string,*>} Destination object
 */
function merge(dst, src, ifNotSet) { // used by converters
    for (var keys = Object.keys(src), i = 0; i < keys.length; ++i)
        if (dst[keys[i]] === undefined || !ifNotSet)
            dst[keys[i]] = src[keys[i]];
    return dst;
}

util.merge = merge;

/**
 * Converts the first character of a string to lower case.
 * @param {string} str String to convert
 * @returns {string} Converted string
 */
util.lcFirst = function lcFirst(str) {
    return str.charAt(0).toLowerCase() + str.substring(1);
};

/**
 * Creates a custom error constructor.
 * @memberof util
 * @param {string} name Error name
 * @returns {Constructor<Error>} Custom error constructor
 */
function newError(name) {

    function CustomError(message, properties) {

        if (!(this instanceof CustomError))
            return new CustomError(message, properties);

        // Error.call(this, message);
        // ^ just returns a new error instance because the ctor can be called as a function

        Object.defineProperty(this, "message", { get: function() { return message; } });

        /* istanbul ignore next */
        if (Error.captureStackTrace) // node
            Error.captureStackTrace(this, CustomError);
        else
            Object.defineProperty(this, "stack", { value: new Error().stack || "" });

        if (properties)
            merge(this, properties);
    }

    (CustomError.prototype = Object.create(Error.prototype)).constructor = CustomError;

    Object.defineProperty(CustomError.prototype, "name", { get: function() { return name; } });

    CustomError.prototype.toString = function toString() {
        return this.name + ": " + this.message;
    };

    return CustomError;
}

util.newError = newError;

/**
 * Constructs a new protocol error.
 * @classdesc Error subclass indicating a protocol specifc error.
 * @memberof util
 * @extends Error
 * @template T extends Message<T>
 * @constructor
 * @param {string} message Error message
 * @param {Object.<string,*>} [properties] Additional properties
 * @example
 * try {
 *     MyMessage.decode(someBuffer); // throws if required fields are missing
 * } catch (e) {
 *     if (e instanceof ProtocolError && e.instance)
 *         console.log("decoded so far: " + JSON.stringify(e.instance));
 * }
 */
util.ProtocolError = newError("ProtocolError");

/**
 * So far decoded message instance.
 * @name util.ProtocolError#instance
 * @type {Message<T>}
 */

/**
 * A OneOf getter as returned by {@link util.oneOfGetter}.
 * @typedef OneOfGetter
 * @type {function}
 * @returns {string|undefined} Set field name, if any
 */

/**
 * Builds a getter for a oneof's present field name.
 * @param {string[]} fieldNames Field names
 * @returns {OneOfGetter} Unbound getter
 */
util.oneOfGetter = function getOneOf(fieldNames) {
    var fieldMap = {};
    for (var i = 0; i < fieldNames.length; ++i)
        fieldMap[fieldNames[i]] = 1;

    /**
     * @returns {string|undefined} Set field name, if any
     * @this Object
     * @ignore
     */
    return function() { // eslint-disable-line consistent-return
        for (var keys = Object.keys(this), i = keys.length - 1; i > -1; --i)
            if (fieldMap[keys[i]] === 1 && this[keys[i]] !== undefined && this[keys[i]] !== null)
                return keys[i];
    };
};

/**
 * A OneOf setter as returned by {@link util.oneOfSetter}.
 * @typedef OneOfSetter
 * @type {function}
 * @param {string|undefined} value Field name
 * @returns {undefined}
 */

/**
 * Builds a setter for a oneof's present field name.
 * @param {string[]} fieldNames Field names
 * @returns {OneOfSetter} Unbound setter
 */
util.oneOfSetter = function setOneOf(fieldNames) {

    /**
     * @param {string} name Field name
     * @returns {undefined}
     * @this Object
     * @ignore
     */
    return function(name) {
        for (var i = 0; i < fieldNames.length; ++i)
            if (fieldNames[i] !== name)
                delete this[fieldNames[i]];
    };
};

/**
 * Default conversion options used for {@link Message#toJSON} implementations.
 *
 * These options are close to proto3's JSON mapping with the exception that internal types like Any are handled just like messages. More precisely:
 *
 * - Longs become strings
 * - Enums become string keys
 * - Bytes become base64 encoded strings
 * - (Sub-)Messages become plain objects
 * - Maps become plain objects with all string keys
 * - Repeated fields become arrays
 * - NaN and Infinity for float and double fields become strings
 *
 * @type {IConversionOptions}
 * @see https://developers.google.com/protocol-buffers/docs/proto3?hl=en#json
 */
util.toJSONOptions = {
    longs: String,
    enums: String,
    bytes: String,
    json: true
};

// Sets up buffer utility according to the environment (called in index-minimal)
util._configure = function() {
    var Buffer = util.Buffer;
    /* istanbul ignore if */
    if (!Buffer) {
        util._Buffer_from = util._Buffer_allocUnsafe = null;
        return;
    }
    // because node 4.x buffers are incompatible & immutable
    // see: https://github.com/dcodeIO/protobuf.js/pull/665
    util._Buffer_from = Buffer.from !== Uint8Array.from && Buffer.from ||
        /* istanbul ignore next */
        function Buffer_from(value, encoding) {
            return new Buffer(value, encoding);
        };
    util._Buffer_allocUnsafe = Buffer.allocUnsafe ||
        /* istanbul ignore next */
        function Buffer_allocUnsafe(size) {
            return new Buffer(size);
        };
};
});

var writer = Writer;



var BufferWriter; // cyclic

var LongBits$1  = minimal.LongBits,
    base64    = minimal.base64,
    utf8      = minimal.utf8;

/**
 * Constructs a new writer operation instance.
 * @classdesc Scheduled writer operation.
 * @constructor
 * @param {function(*, Uint8Array, number)} fn Function to call
 * @param {number} len Value byte length
 * @param {*} val Value to write
 * @ignore
 */
function Op(fn, len, val) {

    /**
     * Function to call.
     * @type {function(Uint8Array, number, *)}
     */
    this.fn = fn;

    /**
     * Value byte length.
     * @type {number}
     */
    this.len = len;

    /**
     * Next operation.
     * @type {Writer.Op|undefined}
     */
    this.next = undefined;

    /**
     * Value to write.
     * @type {*}
     */
    this.val = val; // type varies
}

/* istanbul ignore next */
function noop() {} // eslint-disable-line no-empty-function

/**
 * Constructs a new writer state instance.
 * @classdesc Copied writer state.
 * @memberof Writer
 * @constructor
 * @param {Writer} writer Writer to copy state from
 * @ignore
 */
function State(writer) {

    /**
     * Current head.
     * @type {Writer.Op}
     */
    this.head = writer.head;

    /**
     * Current tail.
     * @type {Writer.Op}
     */
    this.tail = writer.tail;

    /**
     * Current buffer length.
     * @type {number}
     */
    this.len = writer.len;

    /**
     * Next state.
     * @type {State|null}
     */
    this.next = writer.states;
}

/**
 * Constructs a new writer instance.
 * @classdesc Wire format writer using `Uint8Array` if available, otherwise `Array`.
 * @constructor
 */
function Writer() {

    /**
     * Current length.
     * @type {number}
     */
    this.len = 0;

    /**
     * Operations head.
     * @type {Object}
     */
    this.head = new Op(noop, 0, 0);

    /**
     * Operations tail
     * @type {Object}
     */
    this.tail = this.head;

    /**
     * Linked forked states.
     * @type {Object|null}
     */
    this.states = null;

    // When a value is written, the writer calculates its byte length and puts it into a linked
    // list of operations to perform when finish() is called. This both allows us to allocate
    // buffers of the exact required size and reduces the amount of work we have to do compared
    // to first calculating over objects and then encoding over objects. In our case, the encoding
    // part is just a linked list walk calling operations with already prepared values.
}

var create = function create() {
    return minimal.Buffer
        ? function create_buffer_setup() {
            return (Writer.create = function create_buffer() {
                return new BufferWriter();
            })();
        }
        /* istanbul ignore next */
        : function create_array() {
            return new Writer();
        };
};

/**
 * Creates a new writer.
 * @function
 * @returns {BufferWriter|Writer} A {@link BufferWriter} when Buffers are supported, otherwise a {@link Writer}
 */
Writer.create = create();

/**
 * Allocates a buffer of the specified size.
 * @param {number} size Buffer size
 * @returns {Uint8Array} Buffer
 */
Writer.alloc = function alloc(size) {
    return new minimal.Array(size);
};

// Use Uint8Array buffer pool in the browser, just like node does with buffers
/* istanbul ignore else */
if (minimal.Array !== Array)
    Writer.alloc = minimal.pool(Writer.alloc, minimal.Array.prototype.subarray);

/**
 * Pushes a new operation to the queue.
 * @param {function(Uint8Array, number, *)} fn Function to call
 * @param {number} len Value byte length
 * @param {number} val Value to write
 * @returns {Writer} `this`
 * @private
 */
Writer.prototype._push = function push(fn, len, val) {
    this.tail = this.tail.next = new Op(fn, len, val);
    this.len += len;
    return this;
};

function writeByte(val, buf, pos) {
    buf[pos] = val & 255;
}

function writeVarint32(val, buf, pos) {
    while (val > 127) {
        buf[pos++] = val & 127 | 128;
        val >>>= 7;
    }
    buf[pos] = val;
}

/**
 * Constructs a new varint writer operation instance.
 * @classdesc Scheduled varint writer operation.
 * @extends Op
 * @constructor
 * @param {number} len Value byte length
 * @param {number} val Value to write
 * @ignore
 */
function VarintOp(len, val) {
    this.len = len;
    this.next = undefined;
    this.val = val;
}

VarintOp.prototype = Object.create(Op.prototype);
VarintOp.prototype.fn = writeVarint32;

/**
 * Writes an unsigned 32 bit value as a varint.
 * @param {number} value Value to write
 * @returns {Writer} `this`
 */
Writer.prototype.uint32 = function write_uint32(value) {
    // here, the call to this.push has been inlined and a varint specific Op subclass is used.
    // uint32 is by far the most frequently used operation and benefits significantly from this.
    this.len += (this.tail = this.tail.next = new VarintOp(
        (value = value >>> 0)
                < 128       ? 1
        : value < 16384     ? 2
        : value < 2097152   ? 3
        : value < 268435456 ? 4
        :                     5,
    value)).len;
    return this;
};

/**
 * Writes a signed 32 bit value as a varint.
 * @function
 * @param {number} value Value to write
 * @returns {Writer} `this`
 */
Writer.prototype.int32 = function write_int32(value) {
    return value < 0
        ? this._push(writeVarint64, 10, LongBits$1.fromNumber(value)) // 10 bytes per spec
        : this.uint32(value);
};

/**
 * Writes a 32 bit value as a varint, zig-zag encoded.
 * @param {number} value Value to write
 * @returns {Writer} `this`
 */
Writer.prototype.sint32 = function write_sint32(value) {
    return this.uint32((value << 1 ^ value >> 31) >>> 0);
};

function writeVarint64(val, buf, pos) {
    while (val.hi) {
        buf[pos++] = val.lo & 127 | 128;
        val.lo = (val.lo >>> 7 | val.hi << 25) >>> 0;
        val.hi >>>= 7;
    }
    while (val.lo > 127) {
        buf[pos++] = val.lo & 127 | 128;
        val.lo = val.lo >>> 7;
    }
    buf[pos++] = val.lo;
}

/**
 * Writes an unsigned 64 bit value as a varint.
 * @param {Long|number|string} value Value to write
 * @returns {Writer} `this`
 * @throws {TypeError} If `value` is a string and no long library is present.
 */
Writer.prototype.uint64 = function write_uint64(value) {
    var bits = LongBits$1.from(value);
    return this._push(writeVarint64, bits.length(), bits);
};

/**
 * Writes a signed 64 bit value as a varint.
 * @function
 * @param {Long|number|string} value Value to write
 * @returns {Writer} `this`
 * @throws {TypeError} If `value` is a string and no long library is present.
 */
Writer.prototype.int64 = Writer.prototype.uint64;

/**
 * Writes a signed 64 bit value as a varint, zig-zag encoded.
 * @param {Long|number|string} value Value to write
 * @returns {Writer} `this`
 * @throws {TypeError} If `value` is a string and no long library is present.
 */
Writer.prototype.sint64 = function write_sint64(value) {
    var bits = LongBits$1.from(value).zzEncode();
    return this._push(writeVarint64, bits.length(), bits);
};

/**
 * Writes a boolish value as a varint.
 * @param {boolean} value Value to write
 * @returns {Writer} `this`
 */
Writer.prototype.bool = function write_bool(value) {
    return this._push(writeByte, 1, value ? 1 : 0);
};

function writeFixed32(val, buf, pos) {
    buf[pos    ] =  val         & 255;
    buf[pos + 1] =  val >>> 8   & 255;
    buf[pos + 2] =  val >>> 16  & 255;
    buf[pos + 3] =  val >>> 24;
}

/**
 * Writes an unsigned 32 bit value as fixed 32 bits.
 * @param {number} value Value to write
 * @returns {Writer} `this`
 */
Writer.prototype.fixed32 = function write_fixed32(value) {
    return this._push(writeFixed32, 4, value >>> 0);
};

/**
 * Writes a signed 32 bit value as fixed 32 bits.
 * @function
 * @param {number} value Value to write
 * @returns {Writer} `this`
 */
Writer.prototype.sfixed32 = Writer.prototype.fixed32;

/**
 * Writes an unsigned 64 bit value as fixed 64 bits.
 * @param {Long|number|string} value Value to write
 * @returns {Writer} `this`
 * @throws {TypeError} If `value` is a string and no long library is present.
 */
Writer.prototype.fixed64 = function write_fixed64(value) {
    var bits = LongBits$1.from(value);
    return this._push(writeFixed32, 4, bits.lo)._push(writeFixed32, 4, bits.hi);
};

/**
 * Writes a signed 64 bit value as fixed 64 bits.
 * @function
 * @param {Long|number|string} value Value to write
 * @returns {Writer} `this`
 * @throws {TypeError} If `value` is a string and no long library is present.
 */
Writer.prototype.sfixed64 = Writer.prototype.fixed64;

/**
 * Writes a float (32 bit).
 * @function
 * @param {number} value Value to write
 * @returns {Writer} `this`
 */
Writer.prototype.float = function write_float(value) {
    return this._push(minimal.float.writeFloatLE, 4, value);
};

/**
 * Writes a double (64 bit float).
 * @function
 * @param {number} value Value to write
 * @returns {Writer} `this`
 */
Writer.prototype.double = function write_double(value) {
    return this._push(minimal.float.writeDoubleLE, 8, value);
};

var writeBytes = minimal.Array.prototype.set
    ? function writeBytes_set(val, buf, pos) {
        buf.set(val, pos); // also works for plain array values
    }
    /* istanbul ignore next */
    : function writeBytes_for(val, buf, pos) {
        for (var i = 0; i < val.length; ++i)
            buf[pos + i] = val[i];
    };

/**
 * Writes a sequence of bytes.
 * @param {Uint8Array|string} value Buffer or base64 encoded string to write
 * @returns {Writer} `this`
 */
Writer.prototype.bytes = function write_bytes(value) {
    var len = value.length >>> 0;
    if (!len)
        return this._push(writeByte, 1, 0);
    if (minimal.isString(value)) {
        var buf = Writer.alloc(len = base64.length(value));
        base64.decode(value, buf, 0);
        value = buf;
    }
    return this.uint32(len)._push(writeBytes, len, value);
};

/**
 * Writes a string.
 * @param {string} value Value to write
 * @returns {Writer} `this`
 */
Writer.prototype.string = function write_string(value) {
    var len = utf8.length(value);
    return len
        ? this.uint32(len)._push(utf8.write, len, value)
        : this._push(writeByte, 1, 0);
};

/**
 * Forks this writer's state by pushing it to a stack.
 * Calling {@link Writer#reset|reset} or {@link Writer#ldelim|ldelim} resets the writer to the previous state.
 * @returns {Writer} `this`
 */
Writer.prototype.fork = function fork() {
    this.states = new State(this);
    this.head = this.tail = new Op(noop, 0, 0);
    this.len = 0;
    return this;
};

/**
 * Resets this instance to the last state.
 * @returns {Writer} `this`
 */
Writer.prototype.reset = function reset() {
    if (this.states) {
        this.head   = this.states.head;
        this.tail   = this.states.tail;
        this.len    = this.states.len;
        this.states = this.states.next;
    } else {
        this.head = this.tail = new Op(noop, 0, 0);
        this.len  = 0;
    }
    return this;
};

/**
 * Resets to the last state and appends the fork state's current write length as a varint followed by its operations.
 * @returns {Writer} `this`
 */
Writer.prototype.ldelim = function ldelim() {
    var head = this.head,
        tail = this.tail,
        len  = this.len;
    this.reset().uint32(len);
    if (len) {
        this.tail.next = head.next; // skip noop
        this.tail = tail;
        this.len += len;
    }
    return this;
};

/**
 * Finishes the write operation.
 * @returns {Uint8Array} Finished buffer
 */
Writer.prototype.finish = function finish() {
    var head = this.head.next, // skip noop
        buf  = this.constructor.alloc(this.len),
        pos  = 0;
    while (head) {
        head.fn(head.val, buf, pos);
        pos += head.len;
        head = head.next;
    }
    // this.head = this.tail = null;
    return buf;
};

Writer._configure = function(BufferWriter_) {
    BufferWriter = BufferWriter_;
    Writer.create = create();
    BufferWriter._configure();
};

var writer_buffer = BufferWriter$1;

// extends Writer

(BufferWriter$1.prototype = Object.create(writer.prototype)).constructor = BufferWriter$1;



/**
 * Constructs a new buffer writer instance.
 * @classdesc Wire format writer using node buffers.
 * @extends Writer
 * @constructor
 */
function BufferWriter$1() {
    writer.call(this);
}

BufferWriter$1._configure = function () {
    /**
     * Allocates a buffer of the specified size.
     * @function
     * @param {number} size Buffer size
     * @returns {Buffer} Buffer
     */
    BufferWriter$1.alloc = minimal._Buffer_allocUnsafe;

    BufferWriter$1.writeBytesBuffer = minimal.Buffer && minimal.Buffer.prototype instanceof Uint8Array && minimal.Buffer.prototype.set.name === "set"
        ? function writeBytesBuffer_set(val, buf, pos) {
          buf.set(val, pos); // faster than copy (requires node >= 4 where Buffers extend Uint8Array and set is properly inherited)
          // also works for plain array values
        }
        /* istanbul ignore next */
        : function writeBytesBuffer_copy(val, buf, pos) {
          if (val.copy) // Buffer values
            val.copy(buf, pos, 0, val.length);
          else for (var i = 0; i < val.length;) // plain array values
            buf[pos++] = val[i++];
        };
};


/**
 * @override
 */
BufferWriter$1.prototype.bytes = function write_bytes_buffer(value) {
    if (minimal.isString(value))
        value = minimal._Buffer_from(value, "base64");
    var len = value.length >>> 0;
    this.uint32(len);
    if (len)
        this._push(BufferWriter$1.writeBytesBuffer, len, value);
    return this;
};

function writeStringBuffer(val, buf, pos) {
    if (val.length < 40) // plain js is faster for short strings (probably due to redundant assertions)
        minimal.utf8.write(val, buf, pos);
    else if (buf.utf8Write)
        buf.utf8Write(val, pos);
    else
        buf.write(val, pos);
}

/**
 * @override
 */
BufferWriter$1.prototype.string = function write_string_buffer(value) {
    var len = minimal.Buffer.byteLength(value);
    this.uint32(len);
    if (len)
        this._push(writeStringBuffer, len, value);
    return this;
};


/**
 * Finishes the write operation.
 * @name BufferWriter#finish
 * @function
 * @returns {Buffer} Finished buffer
 */

BufferWriter$1._configure();

var reader = Reader;



var BufferReader; // cyclic

var LongBits$2  = minimal.LongBits,
    utf8$1      = minimal.utf8;

/* istanbul ignore next */
function indexOutOfRange(reader, writeLength) {
    return RangeError("index out of range: " + reader.pos + " + " + (writeLength || 1) + " > " + reader.len);
}

/**
 * Constructs a new reader instance using the specified buffer.
 * @classdesc Wire format reader using `Uint8Array` if available, otherwise `Array`.
 * @constructor
 * @param {Uint8Array} buffer Buffer to read from
 */
function Reader(buffer) {

    /**
     * Read buffer.
     * @type {Uint8Array}
     */
    this.buf = buffer;

    /**
     * Read buffer position.
     * @type {number}
     */
    this.pos = 0;

    /**
     * Read buffer length.
     * @type {number}
     */
    this.len = buffer.length;
}

var create_array = typeof Uint8Array !== "undefined"
    ? function create_typed_array(buffer) {
        if (buffer instanceof Uint8Array || Array.isArray(buffer))
            return new Reader(buffer);
        throw Error("illegal buffer");
    }
    /* istanbul ignore next */
    : function create_array(buffer) {
        if (Array.isArray(buffer))
            return new Reader(buffer);
        throw Error("illegal buffer");
    };

var create$1 = function create() {
    return minimal.Buffer
        ? function create_buffer_setup(buffer) {
            return (Reader.create = function create_buffer(buffer) {
                return minimal.Buffer.isBuffer(buffer)
                    ? new BufferReader(buffer)
                    /* istanbul ignore next */
                    : create_array(buffer);
            })(buffer);
        }
        /* istanbul ignore next */
        : create_array;
};

/**
 * Creates a new reader using the specified buffer.
 * @function
 * @param {Uint8Array|Buffer} buffer Buffer to read from
 * @returns {Reader|BufferReader} A {@link BufferReader} if `buffer` is a Buffer, otherwise a {@link Reader}
 * @throws {Error} If `buffer` is not a valid buffer
 */
Reader.create = create$1();

Reader.prototype._slice = minimal.Array.prototype.subarray || /* istanbul ignore next */ minimal.Array.prototype.slice;

/**
 * Reads a varint as an unsigned 32 bit value.
 * @function
 * @returns {number} Value read
 */
Reader.prototype.uint32 = (function read_uint32_setup() {
    var value = 4294967295; // optimizer type-hint, tends to deopt otherwise (?!)
    return function read_uint32() {
        value = (         this.buf[this.pos] & 127       ) >>> 0; if (this.buf[this.pos++] < 128) return value;
        value = (value | (this.buf[this.pos] & 127) <<  7) >>> 0; if (this.buf[this.pos++] < 128) return value;
        value = (value | (this.buf[this.pos] & 127) << 14) >>> 0; if (this.buf[this.pos++] < 128) return value;
        value = (value | (this.buf[this.pos] & 127) << 21) >>> 0; if (this.buf[this.pos++] < 128) return value;
        value = (value | (this.buf[this.pos] &  15) << 28) >>> 0; if (this.buf[this.pos++] < 128) return value;

        /* istanbul ignore if */
        if ((this.pos += 5) > this.len) {
            this.pos = this.len;
            throw indexOutOfRange(this, 10);
        }
        return value;
    };
})();

/**
 * Reads a varint as a signed 32 bit value.
 * @returns {number} Value read
 */
Reader.prototype.int32 = function read_int32() {
    return this.uint32() | 0;
};

/**
 * Reads a zig-zag encoded varint as a signed 32 bit value.
 * @returns {number} Value read
 */
Reader.prototype.sint32 = function read_sint32() {
    var value = this.uint32();
    return value >>> 1 ^ -(value & 1) | 0;
};

/* eslint-disable no-invalid-this */

function readLongVarint() {
    // tends to deopt with local vars for octet etc.
    var bits = new LongBits$2(0, 0);
    var i = 0;
    if (this.len - this.pos > 4) { // fast route (lo)
        for (; i < 4; ++i) {
            // 1st..4th
            bits.lo = (bits.lo | (this.buf[this.pos] & 127) << i * 7) >>> 0;
            if (this.buf[this.pos++] < 128)
                return bits;
        }
        // 5th
        bits.lo = (bits.lo | (this.buf[this.pos] & 127) << 28) >>> 0;
        bits.hi = (bits.hi | (this.buf[this.pos] & 127) >>  4) >>> 0;
        if (this.buf[this.pos++] < 128)
            return bits;
        i = 0;
    } else {
        for (; i < 3; ++i) {
            /* istanbul ignore if */
            if (this.pos >= this.len)
                throw indexOutOfRange(this);
            // 1st..3th
            bits.lo = (bits.lo | (this.buf[this.pos] & 127) << i * 7) >>> 0;
            if (this.buf[this.pos++] < 128)
                return bits;
        }
        // 4th
        bits.lo = (bits.lo | (this.buf[this.pos++] & 127) << i * 7) >>> 0;
        return bits;
    }
    if (this.len - this.pos > 4) { // fast route (hi)
        for (; i < 5; ++i) {
            // 6th..10th
            bits.hi = (bits.hi | (this.buf[this.pos] & 127) << i * 7 + 3) >>> 0;
            if (this.buf[this.pos++] < 128)
                return bits;
        }
    } else {
        for (; i < 5; ++i) {
            /* istanbul ignore if */
            if (this.pos >= this.len)
                throw indexOutOfRange(this);
            // 6th..10th
            bits.hi = (bits.hi | (this.buf[this.pos] & 127) << i * 7 + 3) >>> 0;
            if (this.buf[this.pos++] < 128)
                return bits;
        }
    }
    /* istanbul ignore next */
    throw Error("invalid varint encoding");
}

/* eslint-enable no-invalid-this */

/**
 * Reads a varint as a signed 64 bit value.
 * @name Reader#int64
 * @function
 * @returns {Long} Value read
 */

/**
 * Reads a varint as an unsigned 64 bit value.
 * @name Reader#uint64
 * @function
 * @returns {Long} Value read
 */

/**
 * Reads a zig-zag encoded varint as a signed 64 bit value.
 * @name Reader#sint64
 * @function
 * @returns {Long} Value read
 */

/**
 * Reads a varint as a boolean.
 * @returns {boolean} Value read
 */
Reader.prototype.bool = function read_bool() {
    return this.uint32() !== 0;
};

function readFixed32_end(buf, end) { // note that this uses `end`, not `pos`
    return (buf[end - 4]
          | buf[end - 3] << 8
          | buf[end - 2] << 16
          | buf[end - 1] << 24) >>> 0;
}

/**
 * Reads fixed 32 bits as an unsigned 32 bit integer.
 * @returns {number} Value read
 */
Reader.prototype.fixed32 = function read_fixed32() {

    /* istanbul ignore if */
    if (this.pos + 4 > this.len)
        throw indexOutOfRange(this, 4);

    return readFixed32_end(this.buf, this.pos += 4);
};

/**
 * Reads fixed 32 bits as a signed 32 bit integer.
 * @returns {number} Value read
 */
Reader.prototype.sfixed32 = function read_sfixed32() {

    /* istanbul ignore if */
    if (this.pos + 4 > this.len)
        throw indexOutOfRange(this, 4);

    return readFixed32_end(this.buf, this.pos += 4) | 0;
};

/* eslint-disable no-invalid-this */

function readFixed64(/* this: Reader */) {

    /* istanbul ignore if */
    if (this.pos + 8 > this.len)
        throw indexOutOfRange(this, 8);

    return new LongBits$2(readFixed32_end(this.buf, this.pos += 4), readFixed32_end(this.buf, this.pos += 4));
}

/* eslint-enable no-invalid-this */

/**
 * Reads fixed 64 bits.
 * @name Reader#fixed64
 * @function
 * @returns {Long} Value read
 */

/**
 * Reads zig-zag encoded fixed 64 bits.
 * @name Reader#sfixed64
 * @function
 * @returns {Long} Value read
 */

/**
 * Reads a float (32 bit) as a number.
 * @function
 * @returns {number} Value read
 */
Reader.prototype.float = function read_float() {

    /* istanbul ignore if */
    if (this.pos + 4 > this.len)
        throw indexOutOfRange(this, 4);

    var value = minimal.float.readFloatLE(this.buf, this.pos);
    this.pos += 4;
    return value;
};

/**
 * Reads a double (64 bit float) as a number.
 * @function
 * @returns {number} Value read
 */
Reader.prototype.double = function read_double() {

    /* istanbul ignore if */
    if (this.pos + 8 > this.len)
        throw indexOutOfRange(this, 4);

    var value = minimal.float.readDoubleLE(this.buf, this.pos);
    this.pos += 8;
    return value;
};

/**
 * Reads a sequence of bytes preceeded by its length as a varint.
 * @returns {Uint8Array} Value read
 */
Reader.prototype.bytes = function read_bytes() {
    var length = this.uint32(),
        start  = this.pos,
        end    = this.pos + length;

    /* istanbul ignore if */
    if (end > this.len)
        throw indexOutOfRange(this, length);

    this.pos += length;
    if (Array.isArray(this.buf)) // plain array
        return this.buf.slice(start, end);
    return start === end // fix for IE 10/Win8 and others' subarray returning array of size 1
        ? new this.buf.constructor(0)
        : this._slice.call(this.buf, start, end);
};

/**
 * Reads a string preceeded by its byte length as a varint.
 * @returns {string} Value read
 */
Reader.prototype.string = function read_string() {
    var bytes = this.bytes();
    return utf8$1.read(bytes, 0, bytes.length);
};

/**
 * Skips the specified number of bytes if specified, otherwise skips a varint.
 * @param {number} [length] Length if known, otherwise a varint is assumed
 * @returns {Reader} `this`
 */
Reader.prototype.skip = function skip(length) {
    if (typeof length === "number") {
        /* istanbul ignore if */
        if (this.pos + length > this.len)
            throw indexOutOfRange(this, length);
        this.pos += length;
    } else {
        do {
            /* istanbul ignore if */
            if (this.pos >= this.len)
                throw indexOutOfRange(this);
        } while (this.buf[this.pos++] & 128);
    }
    return this;
};

/**
 * Skips the next element of the specified wire type.
 * @param {number} wireType Wire type received
 * @returns {Reader} `this`
 */
Reader.prototype.skipType = function(wireType) {
    switch (wireType) {
        case 0:
            this.skip();
            break;
        case 1:
            this.skip(8);
            break;
        case 2:
            this.skip(this.uint32());
            break;
        case 3:
            while ((wireType = this.uint32() & 7) !== 4) {
                this.skipType(wireType);
            }
            break;
        case 5:
            this.skip(4);
            break;

        /* istanbul ignore next */
        default:
            throw Error("invalid wire type " + wireType + " at offset " + this.pos);
    }
    return this;
};

Reader._configure = function(BufferReader_) {
    BufferReader = BufferReader_;
    Reader.create = create$1();
    BufferReader._configure();

    var fn = minimal.Long ? "toLong" : /* istanbul ignore next */ "toNumber";
    minimal.merge(Reader.prototype, {

        int64: function read_int64() {
            return readLongVarint.call(this)[fn](false);
        },

        uint64: function read_uint64() {
            return readLongVarint.call(this)[fn](true);
        },

        sint64: function read_sint64() {
            return readLongVarint.call(this).zzDecode()[fn](false);
        },

        fixed64: function read_fixed64() {
            return readFixed64.call(this)[fn](true);
        },

        sfixed64: function read_sfixed64() {
            return readFixed64.call(this)[fn](false);
        }

    });
};

var reader_buffer = BufferReader$1;

// extends Reader

(BufferReader$1.prototype = Object.create(reader.prototype)).constructor = BufferReader$1;



/**
 * Constructs a new buffer reader instance.
 * @classdesc Wire format reader using node buffers.
 * @extends Reader
 * @constructor
 * @param {Buffer} buffer Buffer to read from
 */
function BufferReader$1(buffer) {
    reader.call(this, buffer);

    /**
     * Read buffer.
     * @name BufferReader#buf
     * @type {Buffer}
     */
}

BufferReader$1._configure = function () {
    /* istanbul ignore else */
    if (minimal.Buffer)
        BufferReader$1.prototype._slice = minimal.Buffer.prototype.slice;
};


/**
 * @override
 */
BufferReader$1.prototype.string = function read_string_buffer() {
    var len = this.uint32(); // modifies pos
    return this.buf.utf8Slice
        ? this.buf.utf8Slice(this.pos, this.pos = Math.min(this.pos + len, this.len))
        : this.buf.toString("utf-8", this.pos, this.pos = Math.min(this.pos + len, this.len));
};

/**
 * Reads a sequence of bytes preceeded by its length as a varint.
 * @name BufferReader#bytes
 * @function
 * @returns {Buffer} Value read
 */

BufferReader$1._configure();

var service = Service;



// Extends EventEmitter
(Service.prototype = Object.create(minimal.EventEmitter.prototype)).constructor = Service;

/**
 * A service method callback as used by {@link rpc.ServiceMethod|ServiceMethod}.
 *
 * Differs from {@link RPCImplCallback} in that it is an actual callback of a service method which may not return `response = null`.
 * @typedef rpc.ServiceMethodCallback
 * @template TRes extends Message<TRes>
 * @type {function}
 * @param {Error|null} error Error, if any
 * @param {TRes} [response] Response message
 * @returns {undefined}
 */

/**
 * A service method part of a {@link rpc.Service} as created by {@link Service.create}.
 * @typedef rpc.ServiceMethod
 * @template TReq extends Message<TReq>
 * @template TRes extends Message<TRes>
 * @type {function}
 * @param {TReq|Properties<TReq>} request Request message or plain object
 * @param {rpc.ServiceMethodCallback<TRes>} [callback] Node-style callback called with the error, if any, and the response message
 * @returns {Promise<Message<TRes>>} Promise if `callback` has been omitted, otherwise `undefined`
 */

/**
 * Constructs a new RPC service instance.
 * @classdesc An RPC service as returned by {@link Service#create}.
 * @exports rpc.Service
 * @extends util.EventEmitter
 * @constructor
 * @param {RPCImpl} rpcImpl RPC implementation
 * @param {boolean} [requestDelimited=false] Whether requests are length-delimited
 * @param {boolean} [responseDelimited=false] Whether responses are length-delimited
 */
function Service(rpcImpl, requestDelimited, responseDelimited) {

    if (typeof rpcImpl !== "function")
        throw TypeError("rpcImpl must be a function");

    minimal.EventEmitter.call(this);

    /**
     * RPC implementation. Becomes `null` once the service is ended.
     * @type {RPCImpl|null}
     */
    this.rpcImpl = rpcImpl;

    /**
     * Whether requests are length-delimited.
     * @type {boolean}
     */
    this.requestDelimited = Boolean(requestDelimited);

    /**
     * Whether responses are length-delimited.
     * @type {boolean}
     */
    this.responseDelimited = Boolean(responseDelimited);
}

/**
 * Calls a service method through {@link rpc.Service#rpcImpl|rpcImpl}.
 * @param {Method|rpc.ServiceMethod<TReq,TRes>} method Reflected or static method
 * @param {Constructor<TReq>} requestCtor Request constructor
 * @param {Constructor<TRes>} responseCtor Response constructor
 * @param {TReq|Properties<TReq>} request Request message or plain object
 * @param {rpc.ServiceMethodCallback<TRes>} callback Service callback
 * @returns {undefined}
 * @template TReq extends Message<TReq>
 * @template TRes extends Message<TRes>
 */
Service.prototype.rpcCall = function rpcCall(method, requestCtor, responseCtor, request, callback) {

    if (!request)
        throw TypeError("request must be specified");

    var self = this;
    if (!callback)
        return minimal.asPromise(rpcCall, self, method, requestCtor, responseCtor, request);

    if (!self.rpcImpl) {
        setTimeout(function() { callback(Error("already ended")); }, 0);
        return undefined;
    }

    try {
        return self.rpcImpl(
            method,
            requestCtor[self.requestDelimited ? "encodeDelimited" : "encode"](request).finish(),
            function rpcCallback(err, response) {

                if (err) {
                    self.emit("error", err, method);
                    return callback(err);
                }

                if (response === null) {
                    self.end(/* endedByRPC */ true);
                    return undefined;
                }

                if (!(response instanceof responseCtor)) {
                    try {
                        response = responseCtor[self.responseDelimited ? "decodeDelimited" : "decode"](response);
                    } catch (err) {
                        self.emit("error", err, method);
                        return callback(err);
                    }
                }

                self.emit("data", response, method);
                return callback(null, response);
            }
        );
    } catch (err) {
        self.emit("error", err, method);
        setTimeout(function() { callback(err); }, 0);
        return undefined;
    }
};

/**
 * Ends this service and emits the `end` event.
 * @param {boolean} [endedByRPC=false] Whether the service has been ended by the RPC implementation.
 * @returns {rpc.Service} `this`
 */
Service.prototype.end = function end(endedByRPC) {
    if (this.rpcImpl) {
        if (!endedByRPC) // signal end to rpcImpl
            this.rpcImpl(null, null, null);
        this.rpcImpl = null;
        this.emit("end").off();
    }
    return this;
};

var rpc_1 = createCommonjsModule(function (module, exports) {

/**
 * Streaming RPC helpers.
 * @namespace
 */
var rpc = exports;

/**
 * RPC implementation passed to {@link Service#create} performing a service request on network level, i.e. by utilizing http requests or websockets.
 * @typedef RPCImpl
 * @type {function}
 * @param {Method|rpc.ServiceMethod<Message<{}>,Message<{}>>} method Reflected or static method being called
 * @param {Uint8Array} requestData Request data
 * @param {RPCImplCallback} callback Callback function
 * @returns {undefined}
 * @example
 * function rpcImpl(method, requestData, callback) {
 *     if (protobuf.util.lcFirst(method.name) !== "myMethod") // compatible with static code
 *         throw Error("no such method");
 *     asynchronouslyObtainAResponse(requestData, function(err, responseData) {
 *         callback(err, responseData);
 *     });
 * }
 */

/**
 * Node-style callback as used by {@link RPCImpl}.
 * @typedef RPCImplCallback
 * @type {function}
 * @param {Error|null} error Error, if any, otherwise `null`
 * @param {Uint8Array|null} [response] Response data or `null` to signal end of stream, if there hasn't been an error
 * @returns {undefined}
 */

rpc.Service = service;
});

var roots = {};

var indexMinimal = createCommonjsModule(function (module, exports) {
var protobuf = exports;

/**
 * Build type, one of `"full"`, `"light"` or `"minimal"`.
 * @name build
 * @type {string}
 * @const
 */
protobuf.build = "minimal";

// Serialization
protobuf.Writer       = writer;
protobuf.BufferWriter = writer_buffer;
protobuf.Reader       = reader;
protobuf.BufferReader = reader_buffer;

// Utility
protobuf.util         = minimal;
protobuf.rpc          = rpc_1;
protobuf.roots        = roots;
protobuf.configure    = configure;

/* istanbul ignore next */
/**
 * Reconfigures the library according to the environment.
 * @returns {undefined}
 */
function configure() {
    protobuf.util._configure();
    protobuf.Writer._configure(protobuf.BufferWriter);
    protobuf.Reader._configure(protobuf.BufferReader);
}

// Set up buffer utility according to the environment
configure();
});

var minimal$1 = indexMinimal;

// Common aliases
var $Reader = minimal$1.Reader, $Writer = minimal$1.Writer, $util = minimal$1.util;

// Exported root namespace
var $root = minimal$1.roots["default"] || (minimal$1.roots["default"] = {});

$root.perfetto = (function() {

    /**
     * Namespace perfetto.
     * @exports perfetto
     * @namespace
     */
    var perfetto = {};

    perfetto.protos = (function() {

        /**
         * Namespace protos.
         * @memberof perfetto
         * @namespace
         */
        var protos = {};

        protos.TraceProcessorRpcStream = (function() {

            /**
             * Properties of a TraceProcessorRpcStream.
             * @memberof perfetto.protos
             * @interface ITraceProcessorRpcStream
             * @property {Array.<perfetto.protos.ITraceProcessorRpc>|null} [msg] TraceProcessorRpcStream msg
             */

            /**
             * Constructs a new TraceProcessorRpcStream.
             * @memberof perfetto.protos
             * @classdesc Represents a TraceProcessorRpcStream.
             * @implements ITraceProcessorRpcStream
             * @constructor
             * @param {perfetto.protos.ITraceProcessorRpcStream=} [properties] Properties to set
             */
            function TraceProcessorRpcStream(properties) {
                this.msg = [];
                if (properties)
                    for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                        if (properties[keys[i]] != null)
                            this[keys[i]] = properties[keys[i]];
            }

            /**
             * TraceProcessorRpcStream msg.
             * @member {Array.<perfetto.protos.ITraceProcessorRpc>} msg
             * @memberof perfetto.protos.TraceProcessorRpcStream
             * @instance
             */
            TraceProcessorRpcStream.prototype.msg = $util.emptyArray;

            /**
             * Creates a new TraceProcessorRpcStream instance using the specified properties.
             * @function create
             * @memberof perfetto.protos.TraceProcessorRpcStream
             * @static
             * @param {perfetto.protos.ITraceProcessorRpcStream=} [properties] Properties to set
             * @returns {perfetto.protos.TraceProcessorRpcStream} TraceProcessorRpcStream instance
             */
            TraceProcessorRpcStream.create = function create(properties) {
                return new TraceProcessorRpcStream(properties);
            };

            /**
             * Encodes the specified TraceProcessorRpcStream message. Does not implicitly {@link perfetto.protos.TraceProcessorRpcStream.verify|verify} messages.
             * @function encode
             * @memberof perfetto.protos.TraceProcessorRpcStream
             * @static
             * @param {perfetto.protos.ITraceProcessorRpcStream} message TraceProcessorRpcStream message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            TraceProcessorRpcStream.encode = function encode(message, writer) {
                if (!writer)
                    writer = $Writer.create();
                if (message.msg != null && message.msg.length)
                    for (var i = 0; i < message.msg.length; ++i)
                        $root.perfetto.protos.TraceProcessorRpc.encode(message.msg[i], writer.uint32(/* id 1, wireType 2 =*/10).fork()).ldelim();
                return writer;
            };

            /**
             * Encodes the specified TraceProcessorRpcStream message, length delimited. Does not implicitly {@link perfetto.protos.TraceProcessorRpcStream.verify|verify} messages.
             * @function encodeDelimited
             * @memberof perfetto.protos.TraceProcessorRpcStream
             * @static
             * @param {perfetto.protos.ITraceProcessorRpcStream} message TraceProcessorRpcStream message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            TraceProcessorRpcStream.encodeDelimited = function encodeDelimited(message, writer) {
                return this.encode(message, writer).ldelim();
            };

            /**
             * Decodes a TraceProcessorRpcStream message from the specified reader or buffer.
             * @function decode
             * @memberof perfetto.protos.TraceProcessorRpcStream
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @param {number} [length] Message length if known beforehand
             * @returns {perfetto.protos.TraceProcessorRpcStream} TraceProcessorRpcStream
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            TraceProcessorRpcStream.decode = function decode(reader, length) {
                if (!(reader instanceof $Reader))
                    reader = $Reader.create(reader);
                var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.TraceProcessorRpcStream();
                while (reader.pos < end) {
                    var tag = reader.uint32();
                    switch (tag >>> 3) {
                    case 1:
                        if (!(message.msg && message.msg.length))
                            message.msg = [];
                        message.msg.push($root.perfetto.protos.TraceProcessorRpc.decode(reader, reader.uint32()));
                        break;
                    default:
                        reader.skipType(tag & 7);
                        break;
                    }
                }
                return message;
            };

            /**
             * Decodes a TraceProcessorRpcStream message from the specified reader or buffer, length delimited.
             * @function decodeDelimited
             * @memberof perfetto.protos.TraceProcessorRpcStream
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @returns {perfetto.protos.TraceProcessorRpcStream} TraceProcessorRpcStream
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            TraceProcessorRpcStream.decodeDelimited = function decodeDelimited(reader) {
                if (!(reader instanceof $Reader))
                    reader = new $Reader(reader);
                return this.decode(reader, reader.uint32());
            };

            /**
             * Verifies a TraceProcessorRpcStream message.
             * @function verify
             * @memberof perfetto.protos.TraceProcessorRpcStream
             * @static
             * @param {Object.<string,*>} message Plain object to verify
             * @returns {string|null} `null` if valid, otherwise the reason why it is not
             */
            TraceProcessorRpcStream.verify = function verify(message) {
                if (typeof message !== "object" || message === null)
                    return "object expected";
                if (message.msg != null && message.hasOwnProperty("msg")) {
                    if (!Array.isArray(message.msg))
                        return "msg: array expected";
                    for (var i = 0; i < message.msg.length; ++i) {
                        var error = $root.perfetto.protos.TraceProcessorRpc.verify(message.msg[i]);
                        if (error)
                            return "msg." + error;
                    }
                }
                return null;
            };

            /**
             * Creates a TraceProcessorRpcStream message from a plain object. Also converts values to their respective internal types.
             * @function fromObject
             * @memberof perfetto.protos.TraceProcessorRpcStream
             * @static
             * @param {Object.<string,*>} object Plain object
             * @returns {perfetto.protos.TraceProcessorRpcStream} TraceProcessorRpcStream
             */
            TraceProcessorRpcStream.fromObject = function fromObject(object) {
                if (object instanceof $root.perfetto.protos.TraceProcessorRpcStream)
                    return object;
                var message = new $root.perfetto.protos.TraceProcessorRpcStream();
                if (object.msg) {
                    if (!Array.isArray(object.msg))
                        throw TypeError(".perfetto.protos.TraceProcessorRpcStream.msg: array expected");
                    message.msg = [];
                    for (var i = 0; i < object.msg.length; ++i) {
                        if (typeof object.msg[i] !== "object")
                            throw TypeError(".perfetto.protos.TraceProcessorRpcStream.msg: object expected");
                        message.msg[i] = $root.perfetto.protos.TraceProcessorRpc.fromObject(object.msg[i]);
                    }
                }
                return message;
            };

            /**
             * Creates a plain object from a TraceProcessorRpcStream message. Also converts values to other types if specified.
             * @function toObject
             * @memberof perfetto.protos.TraceProcessorRpcStream
             * @static
             * @param {perfetto.protos.TraceProcessorRpcStream} message TraceProcessorRpcStream
             * @param {$protobuf.IConversionOptions} [options] Conversion options
             * @returns {Object.<string,*>} Plain object
             */
            TraceProcessorRpcStream.toObject = function toObject(message, options) {
                if (!options)
                    options = {};
                var object = {};
                if (options.arrays || options.defaults)
                    object.msg = [];
                if (message.msg && message.msg.length) {
                    object.msg = [];
                    for (var j = 0; j < message.msg.length; ++j)
                        object.msg[j] = $root.perfetto.protos.TraceProcessorRpc.toObject(message.msg[j], options);
                }
                return object;
            };

            /**
             * Converts this TraceProcessorRpcStream to JSON.
             * @function toJSON
             * @memberof perfetto.protos.TraceProcessorRpcStream
             * @instance
             * @returns {Object.<string,*>} JSON object
             */
            TraceProcessorRpcStream.prototype.toJSON = function toJSON() {
                return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
            };

            return TraceProcessorRpcStream;
        })();

        protos.TraceProcessorRpc = (function() {

            /**
             * Properties of a TraceProcessorRpc.
             * @memberof perfetto.protos
             * @interface ITraceProcessorRpc
             * @property {number|null} [seq] TraceProcessorRpc seq
             * @property {perfetto.protos.TraceProcessorRpc.TraceProcessorMethod|null} [request] TraceProcessorRpc request
             * @property {perfetto.protos.TraceProcessorRpc.TraceProcessorMethod|null} [response] TraceProcessorRpc response
             * @property {perfetto.protos.TraceProcessorRpc.TraceProcessorMethod|null} [invalidRequest] TraceProcessorRpc invalidRequest
             * @property {Uint8Array|null} [appendTraceData] TraceProcessorRpc appendTraceData
             * @property {perfetto.protos.IQueryArgs|null} [queryArgs] TraceProcessorRpc queryArgs
             * @property {perfetto.protos.IRawQueryArgs|null} [rawQueryArgs] TraceProcessorRpc rawQueryArgs
             * @property {perfetto.protos.IComputeMetricArgs|null} [computeMetricArgs] TraceProcessorRpc computeMetricArgs
             * @property {perfetto.protos.IAppendTraceDataResult|null} [appendResult] TraceProcessorRpc appendResult
             * @property {perfetto.protos.IQueryResult|null} [queryResult] TraceProcessorRpc queryResult
             * @property {perfetto.protos.IRawQueryResult|null} [rawQueryResult] TraceProcessorRpc rawQueryResult
             * @property {perfetto.protos.IComputeMetricResult|null} [metricResult] TraceProcessorRpc metricResult
             * @property {perfetto.protos.IDescriptorSet|null} [metricDescriptors] TraceProcessorRpc metricDescriptors
             * @property {perfetto.protos.IDisableAndReadMetatraceResult|null} [metatrace] TraceProcessorRpc metatrace
             */

            /**
             * Constructs a new TraceProcessorRpc.
             * @memberof perfetto.protos
             * @classdesc Represents a TraceProcessorRpc.
             * @implements ITraceProcessorRpc
             * @constructor
             * @param {perfetto.protos.ITraceProcessorRpc=} [properties] Properties to set
             */
            function TraceProcessorRpc(properties) {
                if (properties)
                    for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                        if (properties[keys[i]] != null)
                            this[keys[i]] = properties[keys[i]];
            }

            /**
             * TraceProcessorRpc seq.
             * @member {number} seq
             * @memberof perfetto.protos.TraceProcessorRpc
             * @instance
             */
            TraceProcessorRpc.prototype.seq = $util.Long ? $util.Long.fromBits(0,0,false) : 0;

            /**
             * TraceProcessorRpc request.
             * @member {perfetto.protos.TraceProcessorRpc.TraceProcessorMethod} request
             * @memberof perfetto.protos.TraceProcessorRpc
             * @instance
             */
            TraceProcessorRpc.prototype.request = 0;

            /**
             * TraceProcessorRpc response.
             * @member {perfetto.protos.TraceProcessorRpc.TraceProcessorMethod} response
             * @memberof perfetto.protos.TraceProcessorRpc
             * @instance
             */
            TraceProcessorRpc.prototype.response = 0;

            /**
             * TraceProcessorRpc invalidRequest.
             * @member {perfetto.protos.TraceProcessorRpc.TraceProcessorMethod} invalidRequest
             * @memberof perfetto.protos.TraceProcessorRpc
             * @instance
             */
            TraceProcessorRpc.prototype.invalidRequest = 0;

            /**
             * TraceProcessorRpc appendTraceData.
             * @member {Uint8Array} appendTraceData
             * @memberof perfetto.protos.TraceProcessorRpc
             * @instance
             */
            TraceProcessorRpc.prototype.appendTraceData = $util.newBuffer([]);

            /**
             * TraceProcessorRpc queryArgs.
             * @member {perfetto.protos.IQueryArgs|null|undefined} queryArgs
             * @memberof perfetto.protos.TraceProcessorRpc
             * @instance
             */
            TraceProcessorRpc.prototype.queryArgs = null;

            /**
             * TraceProcessorRpc rawQueryArgs.
             * @member {perfetto.protos.IRawQueryArgs|null|undefined} rawQueryArgs
             * @memberof perfetto.protos.TraceProcessorRpc
             * @instance
             */
            TraceProcessorRpc.prototype.rawQueryArgs = null;

            /**
             * TraceProcessorRpc computeMetricArgs.
             * @member {perfetto.protos.IComputeMetricArgs|null|undefined} computeMetricArgs
             * @memberof perfetto.protos.TraceProcessorRpc
             * @instance
             */
            TraceProcessorRpc.prototype.computeMetricArgs = null;

            /**
             * TraceProcessorRpc appendResult.
             * @member {perfetto.protos.IAppendTraceDataResult|null|undefined} appendResult
             * @memberof perfetto.protos.TraceProcessorRpc
             * @instance
             */
            TraceProcessorRpc.prototype.appendResult = null;

            /**
             * TraceProcessorRpc queryResult.
             * @member {perfetto.protos.IQueryResult|null|undefined} queryResult
             * @memberof perfetto.protos.TraceProcessorRpc
             * @instance
             */
            TraceProcessorRpc.prototype.queryResult = null;

            /**
             * TraceProcessorRpc rawQueryResult.
             * @member {perfetto.protos.IRawQueryResult|null|undefined} rawQueryResult
             * @memberof perfetto.protos.TraceProcessorRpc
             * @instance
             */
            TraceProcessorRpc.prototype.rawQueryResult = null;

            /**
             * TraceProcessorRpc metricResult.
             * @member {perfetto.protos.IComputeMetricResult|null|undefined} metricResult
             * @memberof perfetto.protos.TraceProcessorRpc
             * @instance
             */
            TraceProcessorRpc.prototype.metricResult = null;

            /**
             * TraceProcessorRpc metricDescriptors.
             * @member {perfetto.protos.IDescriptorSet|null|undefined} metricDescriptors
             * @memberof perfetto.protos.TraceProcessorRpc
             * @instance
             */
            TraceProcessorRpc.prototype.metricDescriptors = null;

            /**
             * TraceProcessorRpc metatrace.
             * @member {perfetto.protos.IDisableAndReadMetatraceResult|null|undefined} metatrace
             * @memberof perfetto.protos.TraceProcessorRpc
             * @instance
             */
            TraceProcessorRpc.prototype.metatrace = null;

            // OneOf field names bound to virtual getters and setters
            var $oneOfFields;

            /**
             * TraceProcessorRpc type.
             * @member {"request"|"response"|"invalidRequest"|undefined} type
             * @memberof perfetto.protos.TraceProcessorRpc
             * @instance
             */
            Object.defineProperty(TraceProcessorRpc.prototype, "type", {
                get: $util.oneOfGetter($oneOfFields = ["request", "response", "invalidRequest"]),
                set: $util.oneOfSetter($oneOfFields)
            });

            /**
             * TraceProcessorRpc args.
             * @member {"appendTraceData"|"queryArgs"|"rawQueryArgs"|"computeMetricArgs"|"appendResult"|"queryResult"|"rawQueryResult"|"metricResult"|"metricDescriptors"|"metatrace"|undefined} args
             * @memberof perfetto.protos.TraceProcessorRpc
             * @instance
             */
            Object.defineProperty(TraceProcessorRpc.prototype, "args", {
                get: $util.oneOfGetter($oneOfFields = ["appendTraceData", "queryArgs", "rawQueryArgs", "computeMetricArgs", "appendResult", "queryResult", "rawQueryResult", "metricResult", "metricDescriptors", "metatrace"]),
                set: $util.oneOfSetter($oneOfFields)
            });

            /**
             * Creates a new TraceProcessorRpc instance using the specified properties.
             * @function create
             * @memberof perfetto.protos.TraceProcessorRpc
             * @static
             * @param {perfetto.protos.ITraceProcessorRpc=} [properties] Properties to set
             * @returns {perfetto.protos.TraceProcessorRpc} TraceProcessorRpc instance
             */
            TraceProcessorRpc.create = function create(properties) {
                return new TraceProcessorRpc(properties);
            };

            /**
             * Encodes the specified TraceProcessorRpc message. Does not implicitly {@link perfetto.protos.TraceProcessorRpc.verify|verify} messages.
             * @function encode
             * @memberof perfetto.protos.TraceProcessorRpc
             * @static
             * @param {perfetto.protos.ITraceProcessorRpc} message TraceProcessorRpc message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            TraceProcessorRpc.encode = function encode(message, writer) {
                if (!writer)
                    writer = $Writer.create();
                if (message.seq != null && Object.hasOwnProperty.call(message, "seq"))
                    writer.uint32(/* id 1, wireType 0 =*/8).int64(message.seq);
                if (message.request != null && Object.hasOwnProperty.call(message, "request"))
                    writer.uint32(/* id 2, wireType 0 =*/16).int32(message.request);
                if (message.response != null && Object.hasOwnProperty.call(message, "response"))
                    writer.uint32(/* id 3, wireType 0 =*/24).int32(message.response);
                if (message.invalidRequest != null && Object.hasOwnProperty.call(message, "invalidRequest"))
                    writer.uint32(/* id 4, wireType 0 =*/32).int32(message.invalidRequest);
                if (message.appendTraceData != null && Object.hasOwnProperty.call(message, "appendTraceData"))
                    writer.uint32(/* id 101, wireType 2 =*/810).bytes(message.appendTraceData);
                if (message.queryArgs != null && Object.hasOwnProperty.call(message, "queryArgs"))
                    $root.perfetto.protos.QueryArgs.encode(message.queryArgs, writer.uint32(/* id 103, wireType 2 =*/826).fork()).ldelim();
                if (message.rawQueryArgs != null && Object.hasOwnProperty.call(message, "rawQueryArgs"))
                    $root.perfetto.protos.RawQueryArgs.encode(message.rawQueryArgs, writer.uint32(/* id 104, wireType 2 =*/834).fork()).ldelim();
                if (message.computeMetricArgs != null && Object.hasOwnProperty.call(message, "computeMetricArgs"))
                    $root.perfetto.protos.ComputeMetricArgs.encode(message.computeMetricArgs, writer.uint32(/* id 105, wireType 2 =*/842).fork()).ldelim();
                if (message.appendResult != null && Object.hasOwnProperty.call(message, "appendResult"))
                    $root.perfetto.protos.AppendTraceDataResult.encode(message.appendResult, writer.uint32(/* id 201, wireType 2 =*/1610).fork()).ldelim();
                if (message.queryResult != null && Object.hasOwnProperty.call(message, "queryResult"))
                    $root.perfetto.protos.QueryResult.encode(message.queryResult, writer.uint32(/* id 203, wireType 2 =*/1626).fork()).ldelim();
                if (message.rawQueryResult != null && Object.hasOwnProperty.call(message, "rawQueryResult"))
                    $root.perfetto.protos.RawQueryResult.encode(message.rawQueryResult, writer.uint32(/* id 204, wireType 2 =*/1634).fork()).ldelim();
                if (message.metricResult != null && Object.hasOwnProperty.call(message, "metricResult"))
                    $root.perfetto.protos.ComputeMetricResult.encode(message.metricResult, writer.uint32(/* id 205, wireType 2 =*/1642).fork()).ldelim();
                if (message.metricDescriptors != null && Object.hasOwnProperty.call(message, "metricDescriptors"))
                    $root.perfetto.protos.DescriptorSet.encode(message.metricDescriptors, writer.uint32(/* id 206, wireType 2 =*/1650).fork()).ldelim();
                if (message.metatrace != null && Object.hasOwnProperty.call(message, "metatrace"))
                    $root.perfetto.protos.DisableAndReadMetatraceResult.encode(message.metatrace, writer.uint32(/* id 209, wireType 2 =*/1674).fork()).ldelim();
                return writer;
            };

            /**
             * Encodes the specified TraceProcessorRpc message, length delimited. Does not implicitly {@link perfetto.protos.TraceProcessorRpc.verify|verify} messages.
             * @function encodeDelimited
             * @memberof perfetto.protos.TraceProcessorRpc
             * @static
             * @param {perfetto.protos.ITraceProcessorRpc} message TraceProcessorRpc message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            TraceProcessorRpc.encodeDelimited = function encodeDelimited(message, writer) {
                return this.encode(message, writer).ldelim();
            };

            /**
             * Decodes a TraceProcessorRpc message from the specified reader or buffer.
             * @function decode
             * @memberof perfetto.protos.TraceProcessorRpc
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @param {number} [length] Message length if known beforehand
             * @returns {perfetto.protos.TraceProcessorRpc} TraceProcessorRpc
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            TraceProcessorRpc.decode = function decode(reader, length) {
                if (!(reader instanceof $Reader))
                    reader = $Reader.create(reader);
                var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.TraceProcessorRpc();
                while (reader.pos < end) {
                    var tag = reader.uint32();
                    switch (tag >>> 3) {
                    case 1:
                        message.seq = reader.int64();
                        break;
                    case 2:
                        message.request = reader.int32();
                        break;
                    case 3:
                        message.response = reader.int32();
                        break;
                    case 4:
                        message.invalidRequest = reader.int32();
                        break;
                    case 101:
                        message.appendTraceData = reader.bytes();
                        break;
                    case 103:
                        message.queryArgs = $root.perfetto.protos.QueryArgs.decode(reader, reader.uint32());
                        break;
                    case 104:
                        message.rawQueryArgs = $root.perfetto.protos.RawQueryArgs.decode(reader, reader.uint32());
                        break;
                    case 105:
                        message.computeMetricArgs = $root.perfetto.protos.ComputeMetricArgs.decode(reader, reader.uint32());
                        break;
                    case 201:
                        message.appendResult = $root.perfetto.protos.AppendTraceDataResult.decode(reader, reader.uint32());
                        break;
                    case 203:
                        message.queryResult = $root.perfetto.protos.QueryResult.decode(reader, reader.uint32());
                        break;
                    case 204:
                        message.rawQueryResult = $root.perfetto.protos.RawQueryResult.decode(reader, reader.uint32());
                        break;
                    case 205:
                        message.metricResult = $root.perfetto.protos.ComputeMetricResult.decode(reader, reader.uint32());
                        break;
                    case 206:
                        message.metricDescriptors = $root.perfetto.protos.DescriptorSet.decode(reader, reader.uint32());
                        break;
                    case 209:
                        message.metatrace = $root.perfetto.protos.DisableAndReadMetatraceResult.decode(reader, reader.uint32());
                        break;
                    default:
                        reader.skipType(tag & 7);
                        break;
                    }
                }
                return message;
            };

            /**
             * Decodes a TraceProcessorRpc message from the specified reader or buffer, length delimited.
             * @function decodeDelimited
             * @memberof perfetto.protos.TraceProcessorRpc
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @returns {perfetto.protos.TraceProcessorRpc} TraceProcessorRpc
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            TraceProcessorRpc.decodeDelimited = function decodeDelimited(reader) {
                if (!(reader instanceof $Reader))
                    reader = new $Reader(reader);
                return this.decode(reader, reader.uint32());
            };

            /**
             * Verifies a TraceProcessorRpc message.
             * @function verify
             * @memberof perfetto.protos.TraceProcessorRpc
             * @static
             * @param {Object.<string,*>} message Plain object to verify
             * @returns {string|null} `null` if valid, otherwise the reason why it is not
             */
            TraceProcessorRpc.verify = function verify(message) {
                if (typeof message !== "object" || message === null)
                    return "object expected";
                var properties = {};
                if (message.seq != null && message.hasOwnProperty("seq"))
                    if (!$util.isInteger(message.seq) && !(message.seq && $util.isInteger(message.seq.low) && $util.isInteger(message.seq.high)))
                        return "seq: integer|Long expected";
                if (message.request != null && message.hasOwnProperty("request")) {
                    properties.type = 1;
                    switch (message.request) {
                    default:
                        return "request: enum value expected";
                    case 0:
                    case 1:
                    case 2:
                    case 3:
                    case 4:
                    case 5:
                    case 6:
                    case 7:
                    case 8:
                    case 9:
                        break;
                    }
                }
                if (message.response != null && message.hasOwnProperty("response")) {
                    if (properties.type === 1)
                        return "type: multiple values";
                    properties.type = 1;
                    switch (message.response) {
                    default:
                        return "response: enum value expected";
                    case 0:
                    case 1:
                    case 2:
                    case 3:
                    case 4:
                    case 5:
                    case 6:
                    case 7:
                    case 8:
                    case 9:
                        break;
                    }
                }
                if (message.invalidRequest != null && message.hasOwnProperty("invalidRequest")) {
                    if (properties.type === 1)
                        return "type: multiple values";
                    properties.type = 1;
                    switch (message.invalidRequest) {
                    default:
                        return "invalidRequest: enum value expected";
                    case 0:
                    case 1:
                    case 2:
                    case 3:
                    case 4:
                    case 5:
                    case 6:
                    case 7:
                    case 8:
                    case 9:
                        break;
                    }
                }
                if (message.appendTraceData != null && message.hasOwnProperty("appendTraceData")) {
                    properties.args = 1;
                    if (!(message.appendTraceData && typeof message.appendTraceData.length === "number" || $util.isString(message.appendTraceData)))
                        return "appendTraceData: buffer expected";
                }
                if (message.queryArgs != null && message.hasOwnProperty("queryArgs")) {
                    if (properties.args === 1)
                        return "args: multiple values";
                    properties.args = 1;
                    {
                        var error = $root.perfetto.protos.QueryArgs.verify(message.queryArgs);
                        if (error)
                            return "queryArgs." + error;
                    }
                }
                if (message.rawQueryArgs != null && message.hasOwnProperty("rawQueryArgs")) {
                    if (properties.args === 1)
                        return "args: multiple values";
                    properties.args = 1;
                    {
                        var error = $root.perfetto.protos.RawQueryArgs.verify(message.rawQueryArgs);
                        if (error)
                            return "rawQueryArgs." + error;
                    }
                }
                if (message.computeMetricArgs != null && message.hasOwnProperty("computeMetricArgs")) {
                    if (properties.args === 1)
                        return "args: multiple values";
                    properties.args = 1;
                    {
                        var error = $root.perfetto.protos.ComputeMetricArgs.verify(message.computeMetricArgs);
                        if (error)
                            return "computeMetricArgs." + error;
                    }
                }
                if (message.appendResult != null && message.hasOwnProperty("appendResult")) {
                    if (properties.args === 1)
                        return "args: multiple values";
                    properties.args = 1;
                    {
                        var error = $root.perfetto.protos.AppendTraceDataResult.verify(message.appendResult);
                        if (error)
                            return "appendResult." + error;
                    }
                }
                if (message.queryResult != null && message.hasOwnProperty("queryResult")) {
                    if (properties.args === 1)
                        return "args: multiple values";
                    properties.args = 1;
                    {
                        var error = $root.perfetto.protos.QueryResult.verify(message.queryResult);
                        if (error)
                            return "queryResult." + error;
                    }
                }
                if (message.rawQueryResult != null && message.hasOwnProperty("rawQueryResult")) {
                    if (properties.args === 1)
                        return "args: multiple values";
                    properties.args = 1;
                    {
                        var error = $root.perfetto.protos.RawQueryResult.verify(message.rawQueryResult);
                        if (error)
                            return "rawQueryResult." + error;
                    }
                }
                if (message.metricResult != null && message.hasOwnProperty("metricResult")) {
                    if (properties.args === 1)
                        return "args: multiple values";
                    properties.args = 1;
                    {
                        var error = $root.perfetto.protos.ComputeMetricResult.verify(message.metricResult);
                        if (error)
                            return "metricResult." + error;
                    }
                }
                if (message.metricDescriptors != null && message.hasOwnProperty("metricDescriptors")) {
                    if (properties.args === 1)
                        return "args: multiple values";
                    properties.args = 1;
                    {
                        var error = $root.perfetto.protos.DescriptorSet.verify(message.metricDescriptors);
                        if (error)
                            return "metricDescriptors." + error;
                    }
                }
                if (message.metatrace != null && message.hasOwnProperty("metatrace")) {
                    if (properties.args === 1)
                        return "args: multiple values";
                    properties.args = 1;
                    {
                        var error = $root.perfetto.protos.DisableAndReadMetatraceResult.verify(message.metatrace);
                        if (error)
                            return "metatrace." + error;
                    }
                }
                return null;
            };

            /**
             * Creates a TraceProcessorRpc message from a plain object. Also converts values to their respective internal types.
             * @function fromObject
             * @memberof perfetto.protos.TraceProcessorRpc
             * @static
             * @param {Object.<string,*>} object Plain object
             * @returns {perfetto.protos.TraceProcessorRpc} TraceProcessorRpc
             */
            TraceProcessorRpc.fromObject = function fromObject(object) {
                if (object instanceof $root.perfetto.protos.TraceProcessorRpc)
                    return object;
                var message = new $root.perfetto.protos.TraceProcessorRpc();
                if (object.seq != null)
                    if ($util.Long)
                        (message.seq = $util.Long.fromValue(object.seq)).unsigned = false;
                    else if (typeof object.seq === "string")
                        message.seq = parseInt(object.seq, 10);
                    else if (typeof object.seq === "number")
                        message.seq = object.seq;
                    else if (typeof object.seq === "object")
                        message.seq = new $util.LongBits(object.seq.low >>> 0, object.seq.high >>> 0).toNumber();
                switch (object.request) {
                case "TPM_UNSPECIFIED":
                case 0:
                    message.request = 0;
                    break;
                case "TPM_APPEND_TRACE_DATA":
                case 1:
                    message.request = 1;
                    break;
                case "TPM_FINALIZE_TRACE_DATA":
                case 2:
                    message.request = 2;
                    break;
                case "TPM_QUERY_STREAMING":
                case 3:
                    message.request = 3;
                    break;
                case "TPM_QUERY_RAW_DEPRECATED":
                case 4:
                    message.request = 4;
                    break;
                case "TPM_COMPUTE_METRIC":
                case 5:
                    message.request = 5;
                    break;
                case "TPM_GET_METRIC_DESCRIPTORS":
                case 6:
                    message.request = 6;
                    break;
                case "TPM_RESTORE_INITIAL_TABLES":
                case 7:
                    message.request = 7;
                    break;
                case "TPM_ENABLE_METATRACE":
                case 8:
                    message.request = 8;
                    break;
                case "TPM_DISABLE_AND_READ_METATRACE":
                case 9:
                    message.request = 9;
                    break;
                }
                switch (object.response) {
                case "TPM_UNSPECIFIED":
                case 0:
                    message.response = 0;
                    break;
                case "TPM_APPEND_TRACE_DATA":
                case 1:
                    message.response = 1;
                    break;
                case "TPM_FINALIZE_TRACE_DATA":
                case 2:
                    message.response = 2;
                    break;
                case "TPM_QUERY_STREAMING":
                case 3:
                    message.response = 3;
                    break;
                case "TPM_QUERY_RAW_DEPRECATED":
                case 4:
                    message.response = 4;
                    break;
                case "TPM_COMPUTE_METRIC":
                case 5:
                    message.response = 5;
                    break;
                case "TPM_GET_METRIC_DESCRIPTORS":
                case 6:
                    message.response = 6;
                    break;
                case "TPM_RESTORE_INITIAL_TABLES":
                case 7:
                    message.response = 7;
                    break;
                case "TPM_ENABLE_METATRACE":
                case 8:
                    message.response = 8;
                    break;
                case "TPM_DISABLE_AND_READ_METATRACE":
                case 9:
                    message.response = 9;
                    break;
                }
                switch (object.invalidRequest) {
                case "TPM_UNSPECIFIED":
                case 0:
                    message.invalidRequest = 0;
                    break;
                case "TPM_APPEND_TRACE_DATA":
                case 1:
                    message.invalidRequest = 1;
                    break;
                case "TPM_FINALIZE_TRACE_DATA":
                case 2:
                    message.invalidRequest = 2;
                    break;
                case "TPM_QUERY_STREAMING":
                case 3:
                    message.invalidRequest = 3;
                    break;
                case "TPM_QUERY_RAW_DEPRECATED":
                case 4:
                    message.invalidRequest = 4;
                    break;
                case "TPM_COMPUTE_METRIC":
                case 5:
                    message.invalidRequest = 5;
                    break;
                case "TPM_GET_METRIC_DESCRIPTORS":
                case 6:
                    message.invalidRequest = 6;
                    break;
                case "TPM_RESTORE_INITIAL_TABLES":
                case 7:
                    message.invalidRequest = 7;
                    break;
                case "TPM_ENABLE_METATRACE":
                case 8:
                    message.invalidRequest = 8;
                    break;
                case "TPM_DISABLE_AND_READ_METATRACE":
                case 9:
                    message.invalidRequest = 9;
                    break;
                }
                if (object.appendTraceData != null)
                    if (typeof object.appendTraceData === "string")
                        $util.base64.decode(object.appendTraceData, message.appendTraceData = $util.newBuffer($util.base64.length(object.appendTraceData)), 0);
                    else if (object.appendTraceData.length)
                        message.appendTraceData = object.appendTraceData;
                if (object.queryArgs != null) {
                    if (typeof object.queryArgs !== "object")
                        throw TypeError(".perfetto.protos.TraceProcessorRpc.queryArgs: object expected");
                    message.queryArgs = $root.perfetto.protos.QueryArgs.fromObject(object.queryArgs);
                }
                if (object.rawQueryArgs != null) {
                    if (typeof object.rawQueryArgs !== "object")
                        throw TypeError(".perfetto.protos.TraceProcessorRpc.rawQueryArgs: object expected");
                    message.rawQueryArgs = $root.perfetto.protos.RawQueryArgs.fromObject(object.rawQueryArgs);
                }
                if (object.computeMetricArgs != null) {
                    if (typeof object.computeMetricArgs !== "object")
                        throw TypeError(".perfetto.protos.TraceProcessorRpc.computeMetricArgs: object expected");
                    message.computeMetricArgs = $root.perfetto.protos.ComputeMetricArgs.fromObject(object.computeMetricArgs);
                }
                if (object.appendResult != null) {
                    if (typeof object.appendResult !== "object")
                        throw TypeError(".perfetto.protos.TraceProcessorRpc.appendResult: object expected");
                    message.appendResult = $root.perfetto.protos.AppendTraceDataResult.fromObject(object.appendResult);
                }
                if (object.queryResult != null) {
                    if (typeof object.queryResult !== "object")
                        throw TypeError(".perfetto.protos.TraceProcessorRpc.queryResult: object expected");
                    message.queryResult = $root.perfetto.protos.QueryResult.fromObject(object.queryResult);
                }
                if (object.rawQueryResult != null) {
                    if (typeof object.rawQueryResult !== "object")
                        throw TypeError(".perfetto.protos.TraceProcessorRpc.rawQueryResult: object expected");
                    message.rawQueryResult = $root.perfetto.protos.RawQueryResult.fromObject(object.rawQueryResult);
                }
                if (object.metricResult != null) {
                    if (typeof object.metricResult !== "object")
                        throw TypeError(".perfetto.protos.TraceProcessorRpc.metricResult: object expected");
                    message.metricResult = $root.perfetto.protos.ComputeMetricResult.fromObject(object.metricResult);
                }
                if (object.metricDescriptors != null) {
                    if (typeof object.metricDescriptors !== "object")
                        throw TypeError(".perfetto.protos.TraceProcessorRpc.metricDescriptors: object expected");
                    message.metricDescriptors = $root.perfetto.protos.DescriptorSet.fromObject(object.metricDescriptors);
                }
                if (object.metatrace != null) {
                    if (typeof object.metatrace !== "object")
                        throw TypeError(".perfetto.protos.TraceProcessorRpc.metatrace: object expected");
                    message.metatrace = $root.perfetto.protos.DisableAndReadMetatraceResult.fromObject(object.metatrace);
                }
                return message;
            };

            /**
             * Creates a plain object from a TraceProcessorRpc message. Also converts values to other types if specified.
             * @function toObject
             * @memberof perfetto.protos.TraceProcessorRpc
             * @static
             * @param {perfetto.protos.TraceProcessorRpc} message TraceProcessorRpc
             * @param {$protobuf.IConversionOptions} [options] Conversion options
             * @returns {Object.<string,*>} Plain object
             */
            TraceProcessorRpc.toObject = function toObject(message, options) {
                if (!options)
                    options = {};
                var object = {};
                if (options.defaults)
                    if ($util.Long) {
                        var long = new $util.Long(0, 0, false);
                        object.seq = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
                    } else
                        object.seq = options.longs === String ? "0" : 0;
                if (message.seq != null && message.hasOwnProperty("seq"))
                    if (typeof message.seq === "number")
                        object.seq = options.longs === String ? String(message.seq) : message.seq;
                    else
                        object.seq = options.longs === String ? $util.Long.prototype.toString.call(message.seq) : options.longs === Number ? new $util.LongBits(message.seq.low >>> 0, message.seq.high >>> 0).toNumber() : message.seq;
                if (message.request != null && message.hasOwnProperty("request")) {
                    object.request = options.enums === String ? $root.perfetto.protos.TraceProcessorRpc.TraceProcessorMethod[message.request] : message.request;
                    if (options.oneofs)
                        object.type = "request";
                }
                if (message.response != null && message.hasOwnProperty("response")) {
                    object.response = options.enums === String ? $root.perfetto.protos.TraceProcessorRpc.TraceProcessorMethod[message.response] : message.response;
                    if (options.oneofs)
                        object.type = "response";
                }
                if (message.invalidRequest != null && message.hasOwnProperty("invalidRequest")) {
                    object.invalidRequest = options.enums === String ? $root.perfetto.protos.TraceProcessorRpc.TraceProcessorMethod[message.invalidRequest] : message.invalidRequest;
                    if (options.oneofs)
                        object.type = "invalidRequest";
                }
                if (message.appendTraceData != null && message.hasOwnProperty("appendTraceData")) {
                    object.appendTraceData = options.bytes === String ? $util.base64.encode(message.appendTraceData, 0, message.appendTraceData.length) : options.bytes === Array ? Array.prototype.slice.call(message.appendTraceData) : message.appendTraceData;
                    if (options.oneofs)
                        object.args = "appendTraceData";
                }
                if (message.queryArgs != null && message.hasOwnProperty("queryArgs")) {
                    object.queryArgs = $root.perfetto.protos.QueryArgs.toObject(message.queryArgs, options);
                    if (options.oneofs)
                        object.args = "queryArgs";
                }
                if (message.rawQueryArgs != null && message.hasOwnProperty("rawQueryArgs")) {
                    object.rawQueryArgs = $root.perfetto.protos.RawQueryArgs.toObject(message.rawQueryArgs, options);
                    if (options.oneofs)
                        object.args = "rawQueryArgs";
                }
                if (message.computeMetricArgs != null && message.hasOwnProperty("computeMetricArgs")) {
                    object.computeMetricArgs = $root.perfetto.protos.ComputeMetricArgs.toObject(message.computeMetricArgs, options);
                    if (options.oneofs)
                        object.args = "computeMetricArgs";
                }
                if (message.appendResult != null && message.hasOwnProperty("appendResult")) {
                    object.appendResult = $root.perfetto.protos.AppendTraceDataResult.toObject(message.appendResult, options);
                    if (options.oneofs)
                        object.args = "appendResult";
                }
                if (message.queryResult != null && message.hasOwnProperty("queryResult")) {
                    object.queryResult = $root.perfetto.protos.QueryResult.toObject(message.queryResult, options);
                    if (options.oneofs)
                        object.args = "queryResult";
                }
                if (message.rawQueryResult != null && message.hasOwnProperty("rawQueryResult")) {
                    object.rawQueryResult = $root.perfetto.protos.RawQueryResult.toObject(message.rawQueryResult, options);
                    if (options.oneofs)
                        object.args = "rawQueryResult";
                }
                if (message.metricResult != null && message.hasOwnProperty("metricResult")) {
                    object.metricResult = $root.perfetto.protos.ComputeMetricResult.toObject(message.metricResult, options);
                    if (options.oneofs)
                        object.args = "metricResult";
                }
                if (message.metricDescriptors != null && message.hasOwnProperty("metricDescriptors")) {
                    object.metricDescriptors = $root.perfetto.protos.DescriptorSet.toObject(message.metricDescriptors, options);
                    if (options.oneofs)
                        object.args = "metricDescriptors";
                }
                if (message.metatrace != null && message.hasOwnProperty("metatrace")) {
                    object.metatrace = $root.perfetto.protos.DisableAndReadMetatraceResult.toObject(message.metatrace, options);
                    if (options.oneofs)
                        object.args = "metatrace";
                }
                return object;
            };

            /**
             * Converts this TraceProcessorRpc to JSON.
             * @function toJSON
             * @memberof perfetto.protos.TraceProcessorRpc
             * @instance
             * @returns {Object.<string,*>} JSON object
             */
            TraceProcessorRpc.prototype.toJSON = function toJSON() {
                return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
            };

            /**
             * TraceProcessorMethod enum.
             * @name perfetto.protos.TraceProcessorRpc.TraceProcessorMethod
             * @enum {number}
             * @property {number} TPM_UNSPECIFIED=0 TPM_UNSPECIFIED value
             * @property {number} TPM_APPEND_TRACE_DATA=1 TPM_APPEND_TRACE_DATA value
             * @property {number} TPM_FINALIZE_TRACE_DATA=2 TPM_FINALIZE_TRACE_DATA value
             * @property {number} TPM_QUERY_STREAMING=3 TPM_QUERY_STREAMING value
             * @property {number} TPM_QUERY_RAW_DEPRECATED=4 TPM_QUERY_RAW_DEPRECATED value
             * @property {number} TPM_COMPUTE_METRIC=5 TPM_COMPUTE_METRIC value
             * @property {number} TPM_GET_METRIC_DESCRIPTORS=6 TPM_GET_METRIC_DESCRIPTORS value
             * @property {number} TPM_RESTORE_INITIAL_TABLES=7 TPM_RESTORE_INITIAL_TABLES value
             * @property {number} TPM_ENABLE_METATRACE=8 TPM_ENABLE_METATRACE value
             * @property {number} TPM_DISABLE_AND_READ_METATRACE=9 TPM_DISABLE_AND_READ_METATRACE value
             */
            TraceProcessorRpc.TraceProcessorMethod = (function() {
                var valuesById = {}, values = Object.create(valuesById);
                values[valuesById[0] = "TPM_UNSPECIFIED"] = 0;
                values[valuesById[1] = "TPM_APPEND_TRACE_DATA"] = 1;
                values[valuesById[2] = "TPM_FINALIZE_TRACE_DATA"] = 2;
                values[valuesById[3] = "TPM_QUERY_STREAMING"] = 3;
                values[valuesById[4] = "TPM_QUERY_RAW_DEPRECATED"] = 4;
                values[valuesById[5] = "TPM_COMPUTE_METRIC"] = 5;
                values[valuesById[6] = "TPM_GET_METRIC_DESCRIPTORS"] = 6;
                values[valuesById[7] = "TPM_RESTORE_INITIAL_TABLES"] = 7;
                values[valuesById[8] = "TPM_ENABLE_METATRACE"] = 8;
                values[valuesById[9] = "TPM_DISABLE_AND_READ_METATRACE"] = 9;
                return values;
            })();

            return TraceProcessorRpc;
        })();

        protos.AppendTraceDataResult = (function() {

            /**
             * Properties of an AppendTraceDataResult.
             * @memberof perfetto.protos
             * @interface IAppendTraceDataResult
             * @property {number|null} [totalBytesParsed] AppendTraceDataResult totalBytesParsed
             * @property {string|null} [error] AppendTraceDataResult error
             */

            /**
             * Constructs a new AppendTraceDataResult.
             * @memberof perfetto.protos
             * @classdesc Represents an AppendTraceDataResult.
             * @implements IAppendTraceDataResult
             * @constructor
             * @param {perfetto.protos.IAppendTraceDataResult=} [properties] Properties to set
             */
            function AppendTraceDataResult(properties) {
                if (properties)
                    for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                        if (properties[keys[i]] != null)
                            this[keys[i]] = properties[keys[i]];
            }

            /**
             * AppendTraceDataResult totalBytesParsed.
             * @member {number} totalBytesParsed
             * @memberof perfetto.protos.AppendTraceDataResult
             * @instance
             */
            AppendTraceDataResult.prototype.totalBytesParsed = $util.Long ? $util.Long.fromBits(0,0,false) : 0;

            /**
             * AppendTraceDataResult error.
             * @member {string} error
             * @memberof perfetto.protos.AppendTraceDataResult
             * @instance
             */
            AppendTraceDataResult.prototype.error = "";

            /**
             * Creates a new AppendTraceDataResult instance using the specified properties.
             * @function create
             * @memberof perfetto.protos.AppendTraceDataResult
             * @static
             * @param {perfetto.protos.IAppendTraceDataResult=} [properties] Properties to set
             * @returns {perfetto.protos.AppendTraceDataResult} AppendTraceDataResult instance
             */
            AppendTraceDataResult.create = function create(properties) {
                return new AppendTraceDataResult(properties);
            };

            /**
             * Encodes the specified AppendTraceDataResult message. Does not implicitly {@link perfetto.protos.AppendTraceDataResult.verify|verify} messages.
             * @function encode
             * @memberof perfetto.protos.AppendTraceDataResult
             * @static
             * @param {perfetto.protos.IAppendTraceDataResult} message AppendTraceDataResult message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            AppendTraceDataResult.encode = function encode(message, writer) {
                if (!writer)
                    writer = $Writer.create();
                if (message.totalBytesParsed != null && Object.hasOwnProperty.call(message, "totalBytesParsed"))
                    writer.uint32(/* id 1, wireType 0 =*/8).int64(message.totalBytesParsed);
                if (message.error != null && Object.hasOwnProperty.call(message, "error"))
                    writer.uint32(/* id 2, wireType 2 =*/18).string(message.error);
                return writer;
            };

            /**
             * Encodes the specified AppendTraceDataResult message, length delimited. Does not implicitly {@link perfetto.protos.AppendTraceDataResult.verify|verify} messages.
             * @function encodeDelimited
             * @memberof perfetto.protos.AppendTraceDataResult
             * @static
             * @param {perfetto.protos.IAppendTraceDataResult} message AppendTraceDataResult message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            AppendTraceDataResult.encodeDelimited = function encodeDelimited(message, writer) {
                return this.encode(message, writer).ldelim();
            };

            /**
             * Decodes an AppendTraceDataResult message from the specified reader or buffer.
             * @function decode
             * @memberof perfetto.protos.AppendTraceDataResult
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @param {number} [length] Message length if known beforehand
             * @returns {perfetto.protos.AppendTraceDataResult} AppendTraceDataResult
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            AppendTraceDataResult.decode = function decode(reader, length) {
                if (!(reader instanceof $Reader))
                    reader = $Reader.create(reader);
                var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.AppendTraceDataResult();
                while (reader.pos < end) {
                    var tag = reader.uint32();
                    switch (tag >>> 3) {
                    case 1:
                        message.totalBytesParsed = reader.int64();
                        break;
                    case 2:
                        message.error = reader.string();
                        break;
                    default:
                        reader.skipType(tag & 7);
                        break;
                    }
                }
                return message;
            };

            /**
             * Decodes an AppendTraceDataResult message from the specified reader or buffer, length delimited.
             * @function decodeDelimited
             * @memberof perfetto.protos.AppendTraceDataResult
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @returns {perfetto.protos.AppendTraceDataResult} AppendTraceDataResult
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            AppendTraceDataResult.decodeDelimited = function decodeDelimited(reader) {
                if (!(reader instanceof $Reader))
                    reader = new $Reader(reader);
                return this.decode(reader, reader.uint32());
            };

            /**
             * Verifies an AppendTraceDataResult message.
             * @function verify
             * @memberof perfetto.protos.AppendTraceDataResult
             * @static
             * @param {Object.<string,*>} message Plain object to verify
             * @returns {string|null} `null` if valid, otherwise the reason why it is not
             */
            AppendTraceDataResult.verify = function verify(message) {
                if (typeof message !== "object" || message === null)
                    return "object expected";
                if (message.totalBytesParsed != null && message.hasOwnProperty("totalBytesParsed"))
                    if (!$util.isInteger(message.totalBytesParsed) && !(message.totalBytesParsed && $util.isInteger(message.totalBytesParsed.low) && $util.isInteger(message.totalBytesParsed.high)))
                        return "totalBytesParsed: integer|Long expected";
                if (message.error != null && message.hasOwnProperty("error"))
                    if (!$util.isString(message.error))
                        return "error: string expected";
                return null;
            };

            /**
             * Creates an AppendTraceDataResult message from a plain object. Also converts values to their respective internal types.
             * @function fromObject
             * @memberof perfetto.protos.AppendTraceDataResult
             * @static
             * @param {Object.<string,*>} object Plain object
             * @returns {perfetto.protos.AppendTraceDataResult} AppendTraceDataResult
             */
            AppendTraceDataResult.fromObject = function fromObject(object) {
                if (object instanceof $root.perfetto.protos.AppendTraceDataResult)
                    return object;
                var message = new $root.perfetto.protos.AppendTraceDataResult();
                if (object.totalBytesParsed != null)
                    if ($util.Long)
                        (message.totalBytesParsed = $util.Long.fromValue(object.totalBytesParsed)).unsigned = false;
                    else if (typeof object.totalBytesParsed === "string")
                        message.totalBytesParsed = parseInt(object.totalBytesParsed, 10);
                    else if (typeof object.totalBytesParsed === "number")
                        message.totalBytesParsed = object.totalBytesParsed;
                    else if (typeof object.totalBytesParsed === "object")
                        message.totalBytesParsed = new $util.LongBits(object.totalBytesParsed.low >>> 0, object.totalBytesParsed.high >>> 0).toNumber();
                if (object.error != null)
                    message.error = String(object.error);
                return message;
            };

            /**
             * Creates a plain object from an AppendTraceDataResult message. Also converts values to other types if specified.
             * @function toObject
             * @memberof perfetto.protos.AppendTraceDataResult
             * @static
             * @param {perfetto.protos.AppendTraceDataResult} message AppendTraceDataResult
             * @param {$protobuf.IConversionOptions} [options] Conversion options
             * @returns {Object.<string,*>} Plain object
             */
            AppendTraceDataResult.toObject = function toObject(message, options) {
                if (!options)
                    options = {};
                var object = {};
                if (options.defaults) {
                    if ($util.Long) {
                        var long = new $util.Long(0, 0, false);
                        object.totalBytesParsed = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
                    } else
                        object.totalBytesParsed = options.longs === String ? "0" : 0;
                    object.error = "";
                }
                if (message.totalBytesParsed != null && message.hasOwnProperty("totalBytesParsed"))
                    if (typeof message.totalBytesParsed === "number")
                        object.totalBytesParsed = options.longs === String ? String(message.totalBytesParsed) : message.totalBytesParsed;
                    else
                        object.totalBytesParsed = options.longs === String ? $util.Long.prototype.toString.call(message.totalBytesParsed) : options.longs === Number ? new $util.LongBits(message.totalBytesParsed.low >>> 0, message.totalBytesParsed.high >>> 0).toNumber() : message.totalBytesParsed;
                if (message.error != null && message.hasOwnProperty("error"))
                    object.error = message.error;
                return object;
            };

            /**
             * Converts this AppendTraceDataResult to JSON.
             * @function toJSON
             * @memberof perfetto.protos.AppendTraceDataResult
             * @instance
             * @returns {Object.<string,*>} JSON object
             */
            AppendTraceDataResult.prototype.toJSON = function toJSON() {
                return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
            };

            return AppendTraceDataResult;
        })();

        protos.QueryArgs = (function() {

            /**
             * Properties of a QueryArgs.
             * @memberof perfetto.protos
             * @interface IQueryArgs
             * @property {string|null} [sqlQuery] QueryArgs sqlQuery
             * @property {number|null} [timeQueuedNs] QueryArgs timeQueuedNs
             */

            /**
             * Constructs a new QueryArgs.
             * @memberof perfetto.protos
             * @classdesc Represents a QueryArgs.
             * @implements IQueryArgs
             * @constructor
             * @param {perfetto.protos.IQueryArgs=} [properties] Properties to set
             */
            function QueryArgs(properties) {
                if (properties)
                    for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                        if (properties[keys[i]] != null)
                            this[keys[i]] = properties[keys[i]];
            }

            /**
             * QueryArgs sqlQuery.
             * @member {string} sqlQuery
             * @memberof perfetto.protos.QueryArgs
             * @instance
             */
            QueryArgs.prototype.sqlQuery = "";

            /**
             * QueryArgs timeQueuedNs.
             * @member {number} timeQueuedNs
             * @memberof perfetto.protos.QueryArgs
             * @instance
             */
            QueryArgs.prototype.timeQueuedNs = $util.Long ? $util.Long.fromBits(0,0,true) : 0;

            /**
             * Creates a new QueryArgs instance using the specified properties.
             * @function create
             * @memberof perfetto.protos.QueryArgs
             * @static
             * @param {perfetto.protos.IQueryArgs=} [properties] Properties to set
             * @returns {perfetto.protos.QueryArgs} QueryArgs instance
             */
            QueryArgs.create = function create(properties) {
                return new QueryArgs(properties);
            };

            /**
             * Encodes the specified QueryArgs message. Does not implicitly {@link perfetto.protos.QueryArgs.verify|verify} messages.
             * @function encode
             * @memberof perfetto.protos.QueryArgs
             * @static
             * @param {perfetto.protos.IQueryArgs} message QueryArgs message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            QueryArgs.encode = function encode(message, writer) {
                if (!writer)
                    writer = $Writer.create();
                if (message.sqlQuery != null && Object.hasOwnProperty.call(message, "sqlQuery"))
                    writer.uint32(/* id 1, wireType 2 =*/10).string(message.sqlQuery);
                if (message.timeQueuedNs != null && Object.hasOwnProperty.call(message, "timeQueuedNs"))
                    writer.uint32(/* id 2, wireType 0 =*/16).uint64(message.timeQueuedNs);
                return writer;
            };

            /**
             * Encodes the specified QueryArgs message, length delimited. Does not implicitly {@link perfetto.protos.QueryArgs.verify|verify} messages.
             * @function encodeDelimited
             * @memberof perfetto.protos.QueryArgs
             * @static
             * @param {perfetto.protos.IQueryArgs} message QueryArgs message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            QueryArgs.encodeDelimited = function encodeDelimited(message, writer) {
                return this.encode(message, writer).ldelim();
            };

            /**
             * Decodes a QueryArgs message from the specified reader or buffer.
             * @function decode
             * @memberof perfetto.protos.QueryArgs
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @param {number} [length] Message length if known beforehand
             * @returns {perfetto.protos.QueryArgs} QueryArgs
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            QueryArgs.decode = function decode(reader, length) {
                if (!(reader instanceof $Reader))
                    reader = $Reader.create(reader);
                var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.QueryArgs();
                while (reader.pos < end) {
                    var tag = reader.uint32();
                    switch (tag >>> 3) {
                    case 1:
                        message.sqlQuery = reader.string();
                        break;
                    case 2:
                        message.timeQueuedNs = reader.uint64();
                        break;
                    default:
                        reader.skipType(tag & 7);
                        break;
                    }
                }
                return message;
            };

            /**
             * Decodes a QueryArgs message from the specified reader or buffer, length delimited.
             * @function decodeDelimited
             * @memberof perfetto.protos.QueryArgs
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @returns {perfetto.protos.QueryArgs} QueryArgs
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            QueryArgs.decodeDelimited = function decodeDelimited(reader) {
                if (!(reader instanceof $Reader))
                    reader = new $Reader(reader);
                return this.decode(reader, reader.uint32());
            };

            /**
             * Verifies a QueryArgs message.
             * @function verify
             * @memberof perfetto.protos.QueryArgs
             * @static
             * @param {Object.<string,*>} message Plain object to verify
             * @returns {string|null} `null` if valid, otherwise the reason why it is not
             */
            QueryArgs.verify = function verify(message) {
                if (typeof message !== "object" || message === null)
                    return "object expected";
                if (message.sqlQuery != null && message.hasOwnProperty("sqlQuery"))
                    if (!$util.isString(message.sqlQuery))
                        return "sqlQuery: string expected";
                if (message.timeQueuedNs != null && message.hasOwnProperty("timeQueuedNs"))
                    if (!$util.isInteger(message.timeQueuedNs) && !(message.timeQueuedNs && $util.isInteger(message.timeQueuedNs.low) && $util.isInteger(message.timeQueuedNs.high)))
                        return "timeQueuedNs: integer|Long expected";
                return null;
            };

            /**
             * Creates a QueryArgs message from a plain object. Also converts values to their respective internal types.
             * @function fromObject
             * @memberof perfetto.protos.QueryArgs
             * @static
             * @param {Object.<string,*>} object Plain object
             * @returns {perfetto.protos.QueryArgs} QueryArgs
             */
            QueryArgs.fromObject = function fromObject(object) {
                if (object instanceof $root.perfetto.protos.QueryArgs)
                    return object;
                var message = new $root.perfetto.protos.QueryArgs();
                if (object.sqlQuery != null)
                    message.sqlQuery = String(object.sqlQuery);
                if (object.timeQueuedNs != null)
                    if ($util.Long)
                        (message.timeQueuedNs = $util.Long.fromValue(object.timeQueuedNs)).unsigned = true;
                    else if (typeof object.timeQueuedNs === "string")
                        message.timeQueuedNs = parseInt(object.timeQueuedNs, 10);
                    else if (typeof object.timeQueuedNs === "number")
                        message.timeQueuedNs = object.timeQueuedNs;
                    else if (typeof object.timeQueuedNs === "object")
                        message.timeQueuedNs = new $util.LongBits(object.timeQueuedNs.low >>> 0, object.timeQueuedNs.high >>> 0).toNumber(true);
                return message;
            };

            /**
             * Creates a plain object from a QueryArgs message. Also converts values to other types if specified.
             * @function toObject
             * @memberof perfetto.protos.QueryArgs
             * @static
             * @param {perfetto.protos.QueryArgs} message QueryArgs
             * @param {$protobuf.IConversionOptions} [options] Conversion options
             * @returns {Object.<string,*>} Plain object
             */
            QueryArgs.toObject = function toObject(message, options) {
                if (!options)
                    options = {};
                var object = {};
                if (options.defaults) {
                    object.sqlQuery = "";
                    if ($util.Long) {
                        var long = new $util.Long(0, 0, true);
                        object.timeQueuedNs = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
                    } else
                        object.timeQueuedNs = options.longs === String ? "0" : 0;
                }
                if (message.sqlQuery != null && message.hasOwnProperty("sqlQuery"))
                    object.sqlQuery = message.sqlQuery;
                if (message.timeQueuedNs != null && message.hasOwnProperty("timeQueuedNs"))
                    if (typeof message.timeQueuedNs === "number")
                        object.timeQueuedNs = options.longs === String ? String(message.timeQueuedNs) : message.timeQueuedNs;
                    else
                        object.timeQueuedNs = options.longs === String ? $util.Long.prototype.toString.call(message.timeQueuedNs) : options.longs === Number ? new $util.LongBits(message.timeQueuedNs.low >>> 0, message.timeQueuedNs.high >>> 0).toNumber(true) : message.timeQueuedNs;
                return object;
            };

            /**
             * Converts this QueryArgs to JSON.
             * @function toJSON
             * @memberof perfetto.protos.QueryArgs
             * @instance
             * @returns {Object.<string,*>} JSON object
             */
            QueryArgs.prototype.toJSON = function toJSON() {
                return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
            };

            return QueryArgs;
        })();

        protos.RawQueryArgs = (function() {

            /**
             * Properties of a RawQueryArgs.
             * @memberof perfetto.protos
             * @interface IRawQueryArgs
             * @property {string|null} [sqlQuery] RawQueryArgs sqlQuery
             * @property {number|null} [timeQueuedNs] RawQueryArgs timeQueuedNs
             */

            /**
             * Constructs a new RawQueryArgs.
             * @memberof perfetto.protos
             * @classdesc Represents a RawQueryArgs.
             * @implements IRawQueryArgs
             * @constructor
             * @param {perfetto.protos.IRawQueryArgs=} [properties] Properties to set
             */
            function RawQueryArgs(properties) {
                if (properties)
                    for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                        if (properties[keys[i]] != null)
                            this[keys[i]] = properties[keys[i]];
            }

            /**
             * RawQueryArgs sqlQuery.
             * @member {string} sqlQuery
             * @memberof perfetto.protos.RawQueryArgs
             * @instance
             */
            RawQueryArgs.prototype.sqlQuery = "";

            /**
             * RawQueryArgs timeQueuedNs.
             * @member {number} timeQueuedNs
             * @memberof perfetto.protos.RawQueryArgs
             * @instance
             */
            RawQueryArgs.prototype.timeQueuedNs = $util.Long ? $util.Long.fromBits(0,0,true) : 0;

            /**
             * Creates a new RawQueryArgs instance using the specified properties.
             * @function create
             * @memberof perfetto.protos.RawQueryArgs
             * @static
             * @param {perfetto.protos.IRawQueryArgs=} [properties] Properties to set
             * @returns {perfetto.protos.RawQueryArgs} RawQueryArgs instance
             */
            RawQueryArgs.create = function create(properties) {
                return new RawQueryArgs(properties);
            };

            /**
             * Encodes the specified RawQueryArgs message. Does not implicitly {@link perfetto.protos.RawQueryArgs.verify|verify} messages.
             * @function encode
             * @memberof perfetto.protos.RawQueryArgs
             * @static
             * @param {perfetto.protos.IRawQueryArgs} message RawQueryArgs message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            RawQueryArgs.encode = function encode(message, writer) {
                if (!writer)
                    writer = $Writer.create();
                if (message.sqlQuery != null && Object.hasOwnProperty.call(message, "sqlQuery"))
                    writer.uint32(/* id 1, wireType 2 =*/10).string(message.sqlQuery);
                if (message.timeQueuedNs != null && Object.hasOwnProperty.call(message, "timeQueuedNs"))
                    writer.uint32(/* id 2, wireType 0 =*/16).uint64(message.timeQueuedNs);
                return writer;
            };

            /**
             * Encodes the specified RawQueryArgs message, length delimited. Does not implicitly {@link perfetto.protos.RawQueryArgs.verify|verify} messages.
             * @function encodeDelimited
             * @memberof perfetto.protos.RawQueryArgs
             * @static
             * @param {perfetto.protos.IRawQueryArgs} message RawQueryArgs message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            RawQueryArgs.encodeDelimited = function encodeDelimited(message, writer) {
                return this.encode(message, writer).ldelim();
            };

            /**
             * Decodes a RawQueryArgs message from the specified reader or buffer.
             * @function decode
             * @memberof perfetto.protos.RawQueryArgs
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @param {number} [length] Message length if known beforehand
             * @returns {perfetto.protos.RawQueryArgs} RawQueryArgs
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            RawQueryArgs.decode = function decode(reader, length) {
                if (!(reader instanceof $Reader))
                    reader = $Reader.create(reader);
                var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.RawQueryArgs();
                while (reader.pos < end) {
                    var tag = reader.uint32();
                    switch (tag >>> 3) {
                    case 1:
                        message.sqlQuery = reader.string();
                        break;
                    case 2:
                        message.timeQueuedNs = reader.uint64();
                        break;
                    default:
                        reader.skipType(tag & 7);
                        break;
                    }
                }
                return message;
            };

            /**
             * Decodes a RawQueryArgs message from the specified reader or buffer, length delimited.
             * @function decodeDelimited
             * @memberof perfetto.protos.RawQueryArgs
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @returns {perfetto.protos.RawQueryArgs} RawQueryArgs
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            RawQueryArgs.decodeDelimited = function decodeDelimited(reader) {
                if (!(reader instanceof $Reader))
                    reader = new $Reader(reader);
                return this.decode(reader, reader.uint32());
            };

            /**
             * Verifies a RawQueryArgs message.
             * @function verify
             * @memberof perfetto.protos.RawQueryArgs
             * @static
             * @param {Object.<string,*>} message Plain object to verify
             * @returns {string|null} `null` if valid, otherwise the reason why it is not
             */
            RawQueryArgs.verify = function verify(message) {
                if (typeof message !== "object" || message === null)
                    return "object expected";
                if (message.sqlQuery != null && message.hasOwnProperty("sqlQuery"))
                    if (!$util.isString(message.sqlQuery))
                        return "sqlQuery: string expected";
                if (message.timeQueuedNs != null && message.hasOwnProperty("timeQueuedNs"))
                    if (!$util.isInteger(message.timeQueuedNs) && !(message.timeQueuedNs && $util.isInteger(message.timeQueuedNs.low) && $util.isInteger(message.timeQueuedNs.high)))
                        return "timeQueuedNs: integer|Long expected";
                return null;
            };

            /**
             * Creates a RawQueryArgs message from a plain object. Also converts values to their respective internal types.
             * @function fromObject
             * @memberof perfetto.protos.RawQueryArgs
             * @static
             * @param {Object.<string,*>} object Plain object
             * @returns {perfetto.protos.RawQueryArgs} RawQueryArgs
             */
            RawQueryArgs.fromObject = function fromObject(object) {
                if (object instanceof $root.perfetto.protos.RawQueryArgs)
                    return object;
                var message = new $root.perfetto.protos.RawQueryArgs();
                if (object.sqlQuery != null)
                    message.sqlQuery = String(object.sqlQuery);
                if (object.timeQueuedNs != null)
                    if ($util.Long)
                        (message.timeQueuedNs = $util.Long.fromValue(object.timeQueuedNs)).unsigned = true;
                    else if (typeof object.timeQueuedNs === "string")
                        message.timeQueuedNs = parseInt(object.timeQueuedNs, 10);
                    else if (typeof object.timeQueuedNs === "number")
                        message.timeQueuedNs = object.timeQueuedNs;
                    else if (typeof object.timeQueuedNs === "object")
                        message.timeQueuedNs = new $util.LongBits(object.timeQueuedNs.low >>> 0, object.timeQueuedNs.high >>> 0).toNumber(true);
                return message;
            };

            /**
             * Creates a plain object from a RawQueryArgs message. Also converts values to other types if specified.
             * @function toObject
             * @memberof perfetto.protos.RawQueryArgs
             * @static
             * @param {perfetto.protos.RawQueryArgs} message RawQueryArgs
             * @param {$protobuf.IConversionOptions} [options] Conversion options
             * @returns {Object.<string,*>} Plain object
             */
            RawQueryArgs.toObject = function toObject(message, options) {
                if (!options)
                    options = {};
                var object = {};
                if (options.defaults) {
                    object.sqlQuery = "";
                    if ($util.Long) {
                        var long = new $util.Long(0, 0, true);
                        object.timeQueuedNs = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
                    } else
                        object.timeQueuedNs = options.longs === String ? "0" : 0;
                }
                if (message.sqlQuery != null && message.hasOwnProperty("sqlQuery"))
                    object.sqlQuery = message.sqlQuery;
                if (message.timeQueuedNs != null && message.hasOwnProperty("timeQueuedNs"))
                    if (typeof message.timeQueuedNs === "number")
                        object.timeQueuedNs = options.longs === String ? String(message.timeQueuedNs) : message.timeQueuedNs;
                    else
                        object.timeQueuedNs = options.longs === String ? $util.Long.prototype.toString.call(message.timeQueuedNs) : options.longs === Number ? new $util.LongBits(message.timeQueuedNs.low >>> 0, message.timeQueuedNs.high >>> 0).toNumber(true) : message.timeQueuedNs;
                return object;
            };

            /**
             * Converts this RawQueryArgs to JSON.
             * @function toJSON
             * @memberof perfetto.protos.RawQueryArgs
             * @instance
             * @returns {Object.<string,*>} JSON object
             */
            RawQueryArgs.prototype.toJSON = function toJSON() {
                return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
            };

            return RawQueryArgs;
        })();

        protos.RawQueryResult = (function() {

            /**
             * Properties of a RawQueryResult.
             * @memberof perfetto.protos
             * @interface IRawQueryResult
             * @property {Array.<perfetto.protos.RawQueryResult.IColumnDesc>|null} [columnDescriptors] RawQueryResult columnDescriptors
             * @property {number|null} [numRecords] RawQueryResult numRecords
             * @property {Array.<perfetto.protos.RawQueryResult.IColumnValues>|null} [columns] RawQueryResult columns
             * @property {string|null} [error] RawQueryResult error
             * @property {number|null} [executionTimeNs] RawQueryResult executionTimeNs
             */

            /**
             * Constructs a new RawQueryResult.
             * @memberof perfetto.protos
             * @classdesc Represents a RawQueryResult.
             * @implements IRawQueryResult
             * @constructor
             * @param {perfetto.protos.IRawQueryResult=} [properties] Properties to set
             */
            function RawQueryResult(properties) {
                this.columnDescriptors = [];
                this.columns = [];
                if (properties)
                    for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                        if (properties[keys[i]] != null)
                            this[keys[i]] = properties[keys[i]];
            }

            /**
             * RawQueryResult columnDescriptors.
             * @member {Array.<perfetto.protos.RawQueryResult.IColumnDesc>} columnDescriptors
             * @memberof perfetto.protos.RawQueryResult
             * @instance
             */
            RawQueryResult.prototype.columnDescriptors = $util.emptyArray;

            /**
             * RawQueryResult numRecords.
             * @member {number} numRecords
             * @memberof perfetto.protos.RawQueryResult
             * @instance
             */
            RawQueryResult.prototype.numRecords = $util.Long ? $util.Long.fromBits(0,0,true) : 0;

            /**
             * RawQueryResult columns.
             * @member {Array.<perfetto.protos.RawQueryResult.IColumnValues>} columns
             * @memberof perfetto.protos.RawQueryResult
             * @instance
             */
            RawQueryResult.prototype.columns = $util.emptyArray;

            /**
             * RawQueryResult error.
             * @member {string} error
             * @memberof perfetto.protos.RawQueryResult
             * @instance
             */
            RawQueryResult.prototype.error = "";

            /**
             * RawQueryResult executionTimeNs.
             * @member {number} executionTimeNs
             * @memberof perfetto.protos.RawQueryResult
             * @instance
             */
            RawQueryResult.prototype.executionTimeNs = $util.Long ? $util.Long.fromBits(0,0,true) : 0;

            /**
             * Creates a new RawQueryResult instance using the specified properties.
             * @function create
             * @memberof perfetto.protos.RawQueryResult
             * @static
             * @param {perfetto.protos.IRawQueryResult=} [properties] Properties to set
             * @returns {perfetto.protos.RawQueryResult} RawQueryResult instance
             */
            RawQueryResult.create = function create(properties) {
                return new RawQueryResult(properties);
            };

            /**
             * Encodes the specified RawQueryResult message. Does not implicitly {@link perfetto.protos.RawQueryResult.verify|verify} messages.
             * @function encode
             * @memberof perfetto.protos.RawQueryResult
             * @static
             * @param {perfetto.protos.IRawQueryResult} message RawQueryResult message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            RawQueryResult.encode = function encode(message, writer) {
                if (!writer)
                    writer = $Writer.create();
                if (message.columnDescriptors != null && message.columnDescriptors.length)
                    for (var i = 0; i < message.columnDescriptors.length; ++i)
                        $root.perfetto.protos.RawQueryResult.ColumnDesc.encode(message.columnDescriptors[i], writer.uint32(/* id 1, wireType 2 =*/10).fork()).ldelim();
                if (message.numRecords != null && Object.hasOwnProperty.call(message, "numRecords"))
                    writer.uint32(/* id 2, wireType 0 =*/16).uint64(message.numRecords);
                if (message.columns != null && message.columns.length)
                    for (var i = 0; i < message.columns.length; ++i)
                        $root.perfetto.protos.RawQueryResult.ColumnValues.encode(message.columns[i], writer.uint32(/* id 3, wireType 2 =*/26).fork()).ldelim();
                if (message.error != null && Object.hasOwnProperty.call(message, "error"))
                    writer.uint32(/* id 4, wireType 2 =*/34).string(message.error);
                if (message.executionTimeNs != null && Object.hasOwnProperty.call(message, "executionTimeNs"))
                    writer.uint32(/* id 5, wireType 0 =*/40).uint64(message.executionTimeNs);
                return writer;
            };

            /**
             * Encodes the specified RawQueryResult message, length delimited. Does not implicitly {@link perfetto.protos.RawQueryResult.verify|verify} messages.
             * @function encodeDelimited
             * @memberof perfetto.protos.RawQueryResult
             * @static
             * @param {perfetto.protos.IRawQueryResult} message RawQueryResult message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            RawQueryResult.encodeDelimited = function encodeDelimited(message, writer) {
                return this.encode(message, writer).ldelim();
            };

            /**
             * Decodes a RawQueryResult message from the specified reader or buffer.
             * @function decode
             * @memberof perfetto.protos.RawQueryResult
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @param {number} [length] Message length if known beforehand
             * @returns {perfetto.protos.RawQueryResult} RawQueryResult
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            RawQueryResult.decode = function decode(reader, length) {
                if (!(reader instanceof $Reader))
                    reader = $Reader.create(reader);
                var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.RawQueryResult();
                while (reader.pos < end) {
                    var tag = reader.uint32();
                    switch (tag >>> 3) {
                    case 1:
                        if (!(message.columnDescriptors && message.columnDescriptors.length))
                            message.columnDescriptors = [];
                        message.columnDescriptors.push($root.perfetto.protos.RawQueryResult.ColumnDesc.decode(reader, reader.uint32()));
                        break;
                    case 2:
                        message.numRecords = reader.uint64();
                        break;
                    case 3:
                        if (!(message.columns && message.columns.length))
                            message.columns = [];
                        message.columns.push($root.perfetto.protos.RawQueryResult.ColumnValues.decode(reader, reader.uint32()));
                        break;
                    case 4:
                        message.error = reader.string();
                        break;
                    case 5:
                        message.executionTimeNs = reader.uint64();
                        break;
                    default:
                        reader.skipType(tag & 7);
                        break;
                    }
                }
                return message;
            };

            /**
             * Decodes a RawQueryResult message from the specified reader or buffer, length delimited.
             * @function decodeDelimited
             * @memberof perfetto.protos.RawQueryResult
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @returns {perfetto.protos.RawQueryResult} RawQueryResult
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            RawQueryResult.decodeDelimited = function decodeDelimited(reader) {
                if (!(reader instanceof $Reader))
                    reader = new $Reader(reader);
                return this.decode(reader, reader.uint32());
            };

            /**
             * Verifies a RawQueryResult message.
             * @function verify
             * @memberof perfetto.protos.RawQueryResult
             * @static
             * @param {Object.<string,*>} message Plain object to verify
             * @returns {string|null} `null` if valid, otherwise the reason why it is not
             */
            RawQueryResult.verify = function verify(message) {
                if (typeof message !== "object" || message === null)
                    return "object expected";
                if (message.columnDescriptors != null && message.hasOwnProperty("columnDescriptors")) {
                    if (!Array.isArray(message.columnDescriptors))
                        return "columnDescriptors: array expected";
                    for (var i = 0; i < message.columnDescriptors.length; ++i) {
                        var error = $root.perfetto.protos.RawQueryResult.ColumnDesc.verify(message.columnDescriptors[i]);
                        if (error)
                            return "columnDescriptors." + error;
                    }
                }
                if (message.numRecords != null && message.hasOwnProperty("numRecords"))
                    if (!$util.isInteger(message.numRecords) && !(message.numRecords && $util.isInteger(message.numRecords.low) && $util.isInteger(message.numRecords.high)))
                        return "numRecords: integer|Long expected";
                if (message.columns != null && message.hasOwnProperty("columns")) {
                    if (!Array.isArray(message.columns))
                        return "columns: array expected";
                    for (var i = 0; i < message.columns.length; ++i) {
                        var error = $root.perfetto.protos.RawQueryResult.ColumnValues.verify(message.columns[i]);
                        if (error)
                            return "columns." + error;
                    }
                }
                if (message.error != null && message.hasOwnProperty("error"))
                    if (!$util.isString(message.error))
                        return "error: string expected";
                if (message.executionTimeNs != null && message.hasOwnProperty("executionTimeNs"))
                    if (!$util.isInteger(message.executionTimeNs) && !(message.executionTimeNs && $util.isInteger(message.executionTimeNs.low) && $util.isInteger(message.executionTimeNs.high)))
                        return "executionTimeNs: integer|Long expected";
                return null;
            };

            /**
             * Creates a RawQueryResult message from a plain object. Also converts values to their respective internal types.
             * @function fromObject
             * @memberof perfetto.protos.RawQueryResult
             * @static
             * @param {Object.<string,*>} object Plain object
             * @returns {perfetto.protos.RawQueryResult} RawQueryResult
             */
            RawQueryResult.fromObject = function fromObject(object) {
                if (object instanceof $root.perfetto.protos.RawQueryResult)
                    return object;
                var message = new $root.perfetto.protos.RawQueryResult();
                if (object.columnDescriptors) {
                    if (!Array.isArray(object.columnDescriptors))
                        throw TypeError(".perfetto.protos.RawQueryResult.columnDescriptors: array expected");
                    message.columnDescriptors = [];
                    for (var i = 0; i < object.columnDescriptors.length; ++i) {
                        if (typeof object.columnDescriptors[i] !== "object")
                            throw TypeError(".perfetto.protos.RawQueryResult.columnDescriptors: object expected");
                        message.columnDescriptors[i] = $root.perfetto.protos.RawQueryResult.ColumnDesc.fromObject(object.columnDescriptors[i]);
                    }
                }
                if (object.numRecords != null)
                    if ($util.Long)
                        (message.numRecords = $util.Long.fromValue(object.numRecords)).unsigned = true;
                    else if (typeof object.numRecords === "string")
                        message.numRecords = parseInt(object.numRecords, 10);
                    else if (typeof object.numRecords === "number")
                        message.numRecords = object.numRecords;
                    else if (typeof object.numRecords === "object")
                        message.numRecords = new $util.LongBits(object.numRecords.low >>> 0, object.numRecords.high >>> 0).toNumber(true);
                if (object.columns) {
                    if (!Array.isArray(object.columns))
                        throw TypeError(".perfetto.protos.RawQueryResult.columns: array expected");
                    message.columns = [];
                    for (var i = 0; i < object.columns.length; ++i) {
                        if (typeof object.columns[i] !== "object")
                            throw TypeError(".perfetto.protos.RawQueryResult.columns: object expected");
                        message.columns[i] = $root.perfetto.protos.RawQueryResult.ColumnValues.fromObject(object.columns[i]);
                    }
                }
                if (object.error != null)
                    message.error = String(object.error);
                if (object.executionTimeNs != null)
                    if ($util.Long)
                        (message.executionTimeNs = $util.Long.fromValue(object.executionTimeNs)).unsigned = true;
                    else if (typeof object.executionTimeNs === "string")
                        message.executionTimeNs = parseInt(object.executionTimeNs, 10);
                    else if (typeof object.executionTimeNs === "number")
                        message.executionTimeNs = object.executionTimeNs;
                    else if (typeof object.executionTimeNs === "object")
                        message.executionTimeNs = new $util.LongBits(object.executionTimeNs.low >>> 0, object.executionTimeNs.high >>> 0).toNumber(true);
                return message;
            };

            /**
             * Creates a plain object from a RawQueryResult message. Also converts values to other types if specified.
             * @function toObject
             * @memberof perfetto.protos.RawQueryResult
             * @static
             * @param {perfetto.protos.RawQueryResult} message RawQueryResult
             * @param {$protobuf.IConversionOptions} [options] Conversion options
             * @returns {Object.<string,*>} Plain object
             */
            RawQueryResult.toObject = function toObject(message, options) {
                if (!options)
                    options = {};
                var object = {};
                if (options.arrays || options.defaults) {
                    object.columnDescriptors = [];
                    object.columns = [];
                }
                if (options.defaults) {
                    if ($util.Long) {
                        var long = new $util.Long(0, 0, true);
                        object.numRecords = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
                    } else
                        object.numRecords = options.longs === String ? "0" : 0;
                    object.error = "";
                    if ($util.Long) {
                        var long = new $util.Long(0, 0, true);
                        object.executionTimeNs = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
                    } else
                        object.executionTimeNs = options.longs === String ? "0" : 0;
                }
                if (message.columnDescriptors && message.columnDescriptors.length) {
                    object.columnDescriptors = [];
                    for (var j = 0; j < message.columnDescriptors.length; ++j)
                        object.columnDescriptors[j] = $root.perfetto.protos.RawQueryResult.ColumnDesc.toObject(message.columnDescriptors[j], options);
                }
                if (message.numRecords != null && message.hasOwnProperty("numRecords"))
                    if (typeof message.numRecords === "number")
                        object.numRecords = options.longs === String ? String(message.numRecords) : message.numRecords;
                    else
                        object.numRecords = options.longs === String ? $util.Long.prototype.toString.call(message.numRecords) : options.longs === Number ? new $util.LongBits(message.numRecords.low >>> 0, message.numRecords.high >>> 0).toNumber(true) : message.numRecords;
                if (message.columns && message.columns.length) {
                    object.columns = [];
                    for (var j = 0; j < message.columns.length; ++j)
                        object.columns[j] = $root.perfetto.protos.RawQueryResult.ColumnValues.toObject(message.columns[j], options);
                }
                if (message.error != null && message.hasOwnProperty("error"))
                    object.error = message.error;
                if (message.executionTimeNs != null && message.hasOwnProperty("executionTimeNs"))
                    if (typeof message.executionTimeNs === "number")
                        object.executionTimeNs = options.longs === String ? String(message.executionTimeNs) : message.executionTimeNs;
                    else
                        object.executionTimeNs = options.longs === String ? $util.Long.prototype.toString.call(message.executionTimeNs) : options.longs === Number ? new $util.LongBits(message.executionTimeNs.low >>> 0, message.executionTimeNs.high >>> 0).toNumber(true) : message.executionTimeNs;
                return object;
            };

            /**
             * Converts this RawQueryResult to JSON.
             * @function toJSON
             * @memberof perfetto.protos.RawQueryResult
             * @instance
             * @returns {Object.<string,*>} JSON object
             */
            RawQueryResult.prototype.toJSON = function toJSON() {
                return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
            };

            RawQueryResult.ColumnDesc = (function() {

                /**
                 * Properties of a ColumnDesc.
                 * @memberof perfetto.protos.RawQueryResult
                 * @interface IColumnDesc
                 * @property {string|null} [name] ColumnDesc name
                 * @property {perfetto.protos.RawQueryResult.ColumnDesc.Type|null} [type] ColumnDesc type
                 */

                /**
                 * Constructs a new ColumnDesc.
                 * @memberof perfetto.protos.RawQueryResult
                 * @classdesc Represents a ColumnDesc.
                 * @implements IColumnDesc
                 * @constructor
                 * @param {perfetto.protos.RawQueryResult.IColumnDesc=} [properties] Properties to set
                 */
                function ColumnDesc(properties) {
                    if (properties)
                        for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                            if (properties[keys[i]] != null)
                                this[keys[i]] = properties[keys[i]];
                }

                /**
                 * ColumnDesc name.
                 * @member {string} name
                 * @memberof perfetto.protos.RawQueryResult.ColumnDesc
                 * @instance
                 */
                ColumnDesc.prototype.name = "";

                /**
                 * ColumnDesc type.
                 * @member {perfetto.protos.RawQueryResult.ColumnDesc.Type} type
                 * @memberof perfetto.protos.RawQueryResult.ColumnDesc
                 * @instance
                 */
                ColumnDesc.prototype.type = 0;

                /**
                 * Creates a new ColumnDesc instance using the specified properties.
                 * @function create
                 * @memberof perfetto.protos.RawQueryResult.ColumnDesc
                 * @static
                 * @param {perfetto.protos.RawQueryResult.IColumnDesc=} [properties] Properties to set
                 * @returns {perfetto.protos.RawQueryResult.ColumnDesc} ColumnDesc instance
                 */
                ColumnDesc.create = function create(properties) {
                    return new ColumnDesc(properties);
                };

                /**
                 * Encodes the specified ColumnDesc message. Does not implicitly {@link perfetto.protos.RawQueryResult.ColumnDesc.verify|verify} messages.
                 * @function encode
                 * @memberof perfetto.protos.RawQueryResult.ColumnDesc
                 * @static
                 * @param {perfetto.protos.RawQueryResult.IColumnDesc} message ColumnDesc message or plain object to encode
                 * @param {$protobuf.Writer} [writer] Writer to encode to
                 * @returns {$protobuf.Writer} Writer
                 */
                ColumnDesc.encode = function encode(message, writer) {
                    if (!writer)
                        writer = $Writer.create();
                    if (message.name != null && Object.hasOwnProperty.call(message, "name"))
                        writer.uint32(/* id 1, wireType 2 =*/10).string(message.name);
                    if (message.type != null && Object.hasOwnProperty.call(message, "type"))
                        writer.uint32(/* id 2, wireType 0 =*/16).int32(message.type);
                    return writer;
                };

                /**
                 * Encodes the specified ColumnDesc message, length delimited. Does not implicitly {@link perfetto.protos.RawQueryResult.ColumnDesc.verify|verify} messages.
                 * @function encodeDelimited
                 * @memberof perfetto.protos.RawQueryResult.ColumnDesc
                 * @static
                 * @param {perfetto.protos.RawQueryResult.IColumnDesc} message ColumnDesc message or plain object to encode
                 * @param {$protobuf.Writer} [writer] Writer to encode to
                 * @returns {$protobuf.Writer} Writer
                 */
                ColumnDesc.encodeDelimited = function encodeDelimited(message, writer) {
                    return this.encode(message, writer).ldelim();
                };

                /**
                 * Decodes a ColumnDesc message from the specified reader or buffer.
                 * @function decode
                 * @memberof perfetto.protos.RawQueryResult.ColumnDesc
                 * @static
                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                 * @param {number} [length] Message length if known beforehand
                 * @returns {perfetto.protos.RawQueryResult.ColumnDesc} ColumnDesc
                 * @throws {Error} If the payload is not a reader or valid buffer
                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
                 */
                ColumnDesc.decode = function decode(reader, length) {
                    if (!(reader instanceof $Reader))
                        reader = $Reader.create(reader);
                    var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.RawQueryResult.ColumnDesc();
                    while (reader.pos < end) {
                        var tag = reader.uint32();
                        switch (tag >>> 3) {
                        case 1:
                            message.name = reader.string();
                            break;
                        case 2:
                            message.type = reader.int32();
                            break;
                        default:
                            reader.skipType(tag & 7);
                            break;
                        }
                    }
                    return message;
                };

                /**
                 * Decodes a ColumnDesc message from the specified reader or buffer, length delimited.
                 * @function decodeDelimited
                 * @memberof perfetto.protos.RawQueryResult.ColumnDesc
                 * @static
                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                 * @returns {perfetto.protos.RawQueryResult.ColumnDesc} ColumnDesc
                 * @throws {Error} If the payload is not a reader or valid buffer
                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
                 */
                ColumnDesc.decodeDelimited = function decodeDelimited(reader) {
                    if (!(reader instanceof $Reader))
                        reader = new $Reader(reader);
                    return this.decode(reader, reader.uint32());
                };

                /**
                 * Verifies a ColumnDesc message.
                 * @function verify
                 * @memberof perfetto.protos.RawQueryResult.ColumnDesc
                 * @static
                 * @param {Object.<string,*>} message Plain object to verify
                 * @returns {string|null} `null` if valid, otherwise the reason why it is not
                 */
                ColumnDesc.verify = function verify(message) {
                    if (typeof message !== "object" || message === null)
                        return "object expected";
                    if (message.name != null && message.hasOwnProperty("name"))
                        if (!$util.isString(message.name))
                            return "name: string expected";
                    if (message.type != null && message.hasOwnProperty("type"))
                        switch (message.type) {
                        default:
                            return "type: enum value expected";
                        case 0:
                        case 1:
                        case 2:
                        case 3:
                            break;
                        }
                    return null;
                };

                /**
                 * Creates a ColumnDesc message from a plain object. Also converts values to their respective internal types.
                 * @function fromObject
                 * @memberof perfetto.protos.RawQueryResult.ColumnDesc
                 * @static
                 * @param {Object.<string,*>} object Plain object
                 * @returns {perfetto.protos.RawQueryResult.ColumnDesc} ColumnDesc
                 */
                ColumnDesc.fromObject = function fromObject(object) {
                    if (object instanceof $root.perfetto.protos.RawQueryResult.ColumnDesc)
                        return object;
                    var message = new $root.perfetto.protos.RawQueryResult.ColumnDesc();
                    if (object.name != null)
                        message.name = String(object.name);
                    switch (object.type) {
                    case "UNKNOWN":
                    case 0:
                        message.type = 0;
                        break;
                    case "LONG":
                    case 1:
                        message.type = 1;
                        break;
                    case "DOUBLE":
                    case 2:
                        message.type = 2;
                        break;
                    case "STRING":
                    case 3:
                        message.type = 3;
                        break;
                    }
                    return message;
                };

                /**
                 * Creates a plain object from a ColumnDesc message. Also converts values to other types if specified.
                 * @function toObject
                 * @memberof perfetto.protos.RawQueryResult.ColumnDesc
                 * @static
                 * @param {perfetto.protos.RawQueryResult.ColumnDesc} message ColumnDesc
                 * @param {$protobuf.IConversionOptions} [options] Conversion options
                 * @returns {Object.<string,*>} Plain object
                 */
                ColumnDesc.toObject = function toObject(message, options) {
                    if (!options)
                        options = {};
                    var object = {};
                    if (options.defaults) {
                        object.name = "";
                        object.type = options.enums === String ? "UNKNOWN" : 0;
                    }
                    if (message.name != null && message.hasOwnProperty("name"))
                        object.name = message.name;
                    if (message.type != null && message.hasOwnProperty("type"))
                        object.type = options.enums === String ? $root.perfetto.protos.RawQueryResult.ColumnDesc.Type[message.type] : message.type;
                    return object;
                };

                /**
                 * Converts this ColumnDesc to JSON.
                 * @function toJSON
                 * @memberof perfetto.protos.RawQueryResult.ColumnDesc
                 * @instance
                 * @returns {Object.<string,*>} JSON object
                 */
                ColumnDesc.prototype.toJSON = function toJSON() {
                    return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
                };

                /**
                 * Type enum.
                 * @name perfetto.protos.RawQueryResult.ColumnDesc.Type
                 * @enum {number}
                 * @property {number} UNKNOWN=0 UNKNOWN value
                 * @property {number} LONG=1 LONG value
                 * @property {number} DOUBLE=2 DOUBLE value
                 * @property {number} STRING=3 STRING value
                 */
                ColumnDesc.Type = (function() {
                    var valuesById = {}, values = Object.create(valuesById);
                    values[valuesById[0] = "UNKNOWN"] = 0;
                    values[valuesById[1] = "LONG"] = 1;
                    values[valuesById[2] = "DOUBLE"] = 2;
                    values[valuesById[3] = "STRING"] = 3;
                    return values;
                })();

                return ColumnDesc;
            })();

            RawQueryResult.ColumnValues = (function() {

                /**
                 * Properties of a ColumnValues.
                 * @memberof perfetto.protos.RawQueryResult
                 * @interface IColumnValues
                 * @property {Array.<number>|null} [longValues] ColumnValues longValues
                 * @property {Array.<number>|null} [doubleValues] ColumnValues doubleValues
                 * @property {Array.<string>|null} [stringValues] ColumnValues stringValues
                 * @property {Array.<boolean>|null} [isNulls] ColumnValues isNulls
                 */

                /**
                 * Constructs a new ColumnValues.
                 * @memberof perfetto.protos.RawQueryResult
                 * @classdesc Represents a ColumnValues.
                 * @implements IColumnValues
                 * @constructor
                 * @param {perfetto.protos.RawQueryResult.IColumnValues=} [properties] Properties to set
                 */
                function ColumnValues(properties) {
                    this.longValues = [];
                    this.doubleValues = [];
                    this.stringValues = [];
                    this.isNulls = [];
                    if (properties)
                        for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                            if (properties[keys[i]] != null)
                                this[keys[i]] = properties[keys[i]];
                }

                /**
                 * ColumnValues longValues.
                 * @member {Array.<number>} longValues
                 * @memberof perfetto.protos.RawQueryResult.ColumnValues
                 * @instance
                 */
                ColumnValues.prototype.longValues = $util.emptyArray;

                /**
                 * ColumnValues doubleValues.
                 * @member {Array.<number>} doubleValues
                 * @memberof perfetto.protos.RawQueryResult.ColumnValues
                 * @instance
                 */
                ColumnValues.prototype.doubleValues = $util.emptyArray;

                /**
                 * ColumnValues stringValues.
                 * @member {Array.<string>} stringValues
                 * @memberof perfetto.protos.RawQueryResult.ColumnValues
                 * @instance
                 */
                ColumnValues.prototype.stringValues = $util.emptyArray;

                /**
                 * ColumnValues isNulls.
                 * @member {Array.<boolean>} isNulls
                 * @memberof perfetto.protos.RawQueryResult.ColumnValues
                 * @instance
                 */
                ColumnValues.prototype.isNulls = $util.emptyArray;

                /**
                 * Creates a new ColumnValues instance using the specified properties.
                 * @function create
                 * @memberof perfetto.protos.RawQueryResult.ColumnValues
                 * @static
                 * @param {perfetto.protos.RawQueryResult.IColumnValues=} [properties] Properties to set
                 * @returns {perfetto.protos.RawQueryResult.ColumnValues} ColumnValues instance
                 */
                ColumnValues.create = function create(properties) {
                    return new ColumnValues(properties);
                };

                /**
                 * Encodes the specified ColumnValues message. Does not implicitly {@link perfetto.protos.RawQueryResult.ColumnValues.verify|verify} messages.
                 * @function encode
                 * @memberof perfetto.protos.RawQueryResult.ColumnValues
                 * @static
                 * @param {perfetto.protos.RawQueryResult.IColumnValues} message ColumnValues message or plain object to encode
                 * @param {$protobuf.Writer} [writer] Writer to encode to
                 * @returns {$protobuf.Writer} Writer
                 */
                ColumnValues.encode = function encode(message, writer) {
                    if (!writer)
                        writer = $Writer.create();
                    if (message.longValues != null && message.longValues.length)
                        for (var i = 0; i < message.longValues.length; ++i)
                            writer.uint32(/* id 1, wireType 0 =*/8).int64(message.longValues[i]);
                    if (message.doubleValues != null && message.doubleValues.length)
                        for (var i = 0; i < message.doubleValues.length; ++i)
                            writer.uint32(/* id 2, wireType 1 =*/17).double(message.doubleValues[i]);
                    if (message.stringValues != null && message.stringValues.length)
                        for (var i = 0; i < message.stringValues.length; ++i)
                            writer.uint32(/* id 3, wireType 2 =*/26).string(message.stringValues[i]);
                    if (message.isNulls != null && message.isNulls.length)
                        for (var i = 0; i < message.isNulls.length; ++i)
                            writer.uint32(/* id 4, wireType 0 =*/32).bool(message.isNulls[i]);
                    return writer;
                };

                /**
                 * Encodes the specified ColumnValues message, length delimited. Does not implicitly {@link perfetto.protos.RawQueryResult.ColumnValues.verify|verify} messages.
                 * @function encodeDelimited
                 * @memberof perfetto.protos.RawQueryResult.ColumnValues
                 * @static
                 * @param {perfetto.protos.RawQueryResult.IColumnValues} message ColumnValues message or plain object to encode
                 * @param {$protobuf.Writer} [writer] Writer to encode to
                 * @returns {$protobuf.Writer} Writer
                 */
                ColumnValues.encodeDelimited = function encodeDelimited(message, writer) {
                    return this.encode(message, writer).ldelim();
                };

                /**
                 * Decodes a ColumnValues message from the specified reader or buffer.
                 * @function decode
                 * @memberof perfetto.protos.RawQueryResult.ColumnValues
                 * @static
                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                 * @param {number} [length] Message length if known beforehand
                 * @returns {perfetto.protos.RawQueryResult.ColumnValues} ColumnValues
                 * @throws {Error} If the payload is not a reader or valid buffer
                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
                 */
                ColumnValues.decode = function decode(reader, length) {
                    if (!(reader instanceof $Reader))
                        reader = $Reader.create(reader);
                    var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.RawQueryResult.ColumnValues();
                    while (reader.pos < end) {
                        var tag = reader.uint32();
                        switch (tag >>> 3) {
                        case 1:
                            if (!(message.longValues && message.longValues.length))
                                message.longValues = [];
                            if ((tag & 7) === 2) {
                                var end2 = reader.uint32() + reader.pos;
                                while (reader.pos < end2)
                                    message.longValues.push(reader.int64());
                            } else
                                message.longValues.push(reader.int64());
                            break;
                        case 2:
                            if (!(message.doubleValues && message.doubleValues.length))
                                message.doubleValues = [];
                            if ((tag & 7) === 2) {
                                var end2 = reader.uint32() + reader.pos;
                                while (reader.pos < end2)
                                    message.doubleValues.push(reader.double());
                            } else
                                message.doubleValues.push(reader.double());
                            break;
                        case 3:
                            if (!(message.stringValues && message.stringValues.length))
                                message.stringValues = [];
                            message.stringValues.push(reader.string());
                            break;
                        case 4:
                            if (!(message.isNulls && message.isNulls.length))
                                message.isNulls = [];
                            if ((tag & 7) === 2) {
                                var end2 = reader.uint32() + reader.pos;
                                while (reader.pos < end2)
                                    message.isNulls.push(reader.bool());
                            } else
                                message.isNulls.push(reader.bool());
                            break;
                        default:
                            reader.skipType(tag & 7);
                            break;
                        }
                    }
                    return message;
                };

                /**
                 * Decodes a ColumnValues message from the specified reader or buffer, length delimited.
                 * @function decodeDelimited
                 * @memberof perfetto.protos.RawQueryResult.ColumnValues
                 * @static
                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                 * @returns {perfetto.protos.RawQueryResult.ColumnValues} ColumnValues
                 * @throws {Error} If the payload is not a reader or valid buffer
                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
                 */
                ColumnValues.decodeDelimited = function decodeDelimited(reader) {
                    if (!(reader instanceof $Reader))
                        reader = new $Reader(reader);
                    return this.decode(reader, reader.uint32());
                };

                /**
                 * Verifies a ColumnValues message.
                 * @function verify
                 * @memberof perfetto.protos.RawQueryResult.ColumnValues
                 * @static
                 * @param {Object.<string,*>} message Plain object to verify
                 * @returns {string|null} `null` if valid, otherwise the reason why it is not
                 */
                ColumnValues.verify = function verify(message) {
                    if (typeof message !== "object" || message === null)
                        return "object expected";
                    if (message.longValues != null && message.hasOwnProperty("longValues")) {
                        if (!Array.isArray(message.longValues))
                            return "longValues: array expected";
                        for (var i = 0; i < message.longValues.length; ++i)
                            if (!$util.isInteger(message.longValues[i]) && !(message.longValues[i] && $util.isInteger(message.longValues[i].low) && $util.isInteger(message.longValues[i].high)))
                                return "longValues: integer|Long[] expected";
                    }
                    if (message.doubleValues != null && message.hasOwnProperty("doubleValues")) {
                        if (!Array.isArray(message.doubleValues))
                            return "doubleValues: array expected";
                        for (var i = 0; i < message.doubleValues.length; ++i)
                            if (typeof message.doubleValues[i] !== "number")
                                return "doubleValues: number[] expected";
                    }
                    if (message.stringValues != null && message.hasOwnProperty("stringValues")) {
                        if (!Array.isArray(message.stringValues))
                            return "stringValues: array expected";
                        for (var i = 0; i < message.stringValues.length; ++i)
                            if (!$util.isString(message.stringValues[i]))
                                return "stringValues: string[] expected";
                    }
                    if (message.isNulls != null && message.hasOwnProperty("isNulls")) {
                        if (!Array.isArray(message.isNulls))
                            return "isNulls: array expected";
                        for (var i = 0; i < message.isNulls.length; ++i)
                            if (typeof message.isNulls[i] !== "boolean")
                                return "isNulls: boolean[] expected";
                    }
                    return null;
                };

                /**
                 * Creates a ColumnValues message from a plain object. Also converts values to their respective internal types.
                 * @function fromObject
                 * @memberof perfetto.protos.RawQueryResult.ColumnValues
                 * @static
                 * @param {Object.<string,*>} object Plain object
                 * @returns {perfetto.protos.RawQueryResult.ColumnValues} ColumnValues
                 */
                ColumnValues.fromObject = function fromObject(object) {
                    if (object instanceof $root.perfetto.protos.RawQueryResult.ColumnValues)
                        return object;
                    var message = new $root.perfetto.protos.RawQueryResult.ColumnValues();
                    if (object.longValues) {
                        if (!Array.isArray(object.longValues))
                            throw TypeError(".perfetto.protos.RawQueryResult.ColumnValues.longValues: array expected");
                        message.longValues = [];
                        for (var i = 0; i < object.longValues.length; ++i)
                            if ($util.Long)
                                (message.longValues[i] = $util.Long.fromValue(object.longValues[i])).unsigned = false;
                            else if (typeof object.longValues[i] === "string")
                                message.longValues[i] = parseInt(object.longValues[i], 10);
                            else if (typeof object.longValues[i] === "number")
                                message.longValues[i] = object.longValues[i];
                            else if (typeof object.longValues[i] === "object")
                                message.longValues[i] = new $util.LongBits(object.longValues[i].low >>> 0, object.longValues[i].high >>> 0).toNumber();
                    }
                    if (object.doubleValues) {
                        if (!Array.isArray(object.doubleValues))
                            throw TypeError(".perfetto.protos.RawQueryResult.ColumnValues.doubleValues: array expected");
                        message.doubleValues = [];
                        for (var i = 0; i < object.doubleValues.length; ++i)
                            message.doubleValues[i] = Number(object.doubleValues[i]);
                    }
                    if (object.stringValues) {
                        if (!Array.isArray(object.stringValues))
                            throw TypeError(".perfetto.protos.RawQueryResult.ColumnValues.stringValues: array expected");
                        message.stringValues = [];
                        for (var i = 0; i < object.stringValues.length; ++i)
                            message.stringValues[i] = String(object.stringValues[i]);
                    }
                    if (object.isNulls) {
                        if (!Array.isArray(object.isNulls))
                            throw TypeError(".perfetto.protos.RawQueryResult.ColumnValues.isNulls: array expected");
                        message.isNulls = [];
                        for (var i = 0; i < object.isNulls.length; ++i)
                            message.isNulls[i] = Boolean(object.isNulls[i]);
                    }
                    return message;
                };

                /**
                 * Creates a plain object from a ColumnValues message. Also converts values to other types if specified.
                 * @function toObject
                 * @memberof perfetto.protos.RawQueryResult.ColumnValues
                 * @static
                 * @param {perfetto.protos.RawQueryResult.ColumnValues} message ColumnValues
                 * @param {$protobuf.IConversionOptions} [options] Conversion options
                 * @returns {Object.<string,*>} Plain object
                 */
                ColumnValues.toObject = function toObject(message, options) {
                    if (!options)
                        options = {};
                    var object = {};
                    if (options.arrays || options.defaults) {
                        object.longValues = [];
                        object.doubleValues = [];
                        object.stringValues = [];
                        object.isNulls = [];
                    }
                    if (message.longValues && message.longValues.length) {
                        object.longValues = [];
                        for (var j = 0; j < message.longValues.length; ++j)
                            if (typeof message.longValues[j] === "number")
                                object.longValues[j] = options.longs === String ? String(message.longValues[j]) : message.longValues[j];
                            else
                                object.longValues[j] = options.longs === String ? $util.Long.prototype.toString.call(message.longValues[j]) : options.longs === Number ? new $util.LongBits(message.longValues[j].low >>> 0, message.longValues[j].high >>> 0).toNumber() : message.longValues[j];
                    }
                    if (message.doubleValues && message.doubleValues.length) {
                        object.doubleValues = [];
                        for (var j = 0; j < message.doubleValues.length; ++j)
                            object.doubleValues[j] = options.json && !isFinite(message.doubleValues[j]) ? String(message.doubleValues[j]) : message.doubleValues[j];
                    }
                    if (message.stringValues && message.stringValues.length) {
                        object.stringValues = [];
                        for (var j = 0; j < message.stringValues.length; ++j)
                            object.stringValues[j] = message.stringValues[j];
                    }
                    if (message.isNulls && message.isNulls.length) {
                        object.isNulls = [];
                        for (var j = 0; j < message.isNulls.length; ++j)
                            object.isNulls[j] = message.isNulls[j];
                    }
                    return object;
                };

                /**
                 * Converts this ColumnValues to JSON.
                 * @function toJSON
                 * @memberof perfetto.protos.RawQueryResult.ColumnValues
                 * @instance
                 * @returns {Object.<string,*>} JSON object
                 */
                ColumnValues.prototype.toJSON = function toJSON() {
                    return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
                };

                return ColumnValues;
            })();

            return RawQueryResult;
        })();

        protos.QueryResult = (function() {

            /**
             * Properties of a QueryResult.
             * @memberof perfetto.protos
             * @interface IQueryResult
             * @property {Array.<string>|null} [columnNames] QueryResult columnNames
             * @property {string|null} [error] QueryResult error
             * @property {Array.<perfetto.protos.QueryResult.ICellsBatch>|null} [batch] QueryResult batch
             */

            /**
             * Constructs a new QueryResult.
             * @memberof perfetto.protos
             * @classdesc Represents a QueryResult.
             * @implements IQueryResult
             * @constructor
             * @param {perfetto.protos.IQueryResult=} [properties] Properties to set
             */
            function QueryResult(properties) {
                this.columnNames = [];
                this.batch = [];
                if (properties)
                    for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                        if (properties[keys[i]] != null)
                            this[keys[i]] = properties[keys[i]];
            }

            /**
             * QueryResult columnNames.
             * @member {Array.<string>} columnNames
             * @memberof perfetto.protos.QueryResult
             * @instance
             */
            QueryResult.prototype.columnNames = $util.emptyArray;

            /**
             * QueryResult error.
             * @member {string} error
             * @memberof perfetto.protos.QueryResult
             * @instance
             */
            QueryResult.prototype.error = "";

            /**
             * QueryResult batch.
             * @member {Array.<perfetto.protos.QueryResult.ICellsBatch>} batch
             * @memberof perfetto.protos.QueryResult
             * @instance
             */
            QueryResult.prototype.batch = $util.emptyArray;

            /**
             * Creates a new QueryResult instance using the specified properties.
             * @function create
             * @memberof perfetto.protos.QueryResult
             * @static
             * @param {perfetto.protos.IQueryResult=} [properties] Properties to set
             * @returns {perfetto.protos.QueryResult} QueryResult instance
             */
            QueryResult.create = function create(properties) {
                return new QueryResult(properties);
            };

            /**
             * Encodes the specified QueryResult message. Does not implicitly {@link perfetto.protos.QueryResult.verify|verify} messages.
             * @function encode
             * @memberof perfetto.protos.QueryResult
             * @static
             * @param {perfetto.protos.IQueryResult} message QueryResult message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            QueryResult.encode = function encode(message, writer) {
                if (!writer)
                    writer = $Writer.create();
                if (message.columnNames != null && message.columnNames.length)
                    for (var i = 0; i < message.columnNames.length; ++i)
                        writer.uint32(/* id 1, wireType 2 =*/10).string(message.columnNames[i]);
                if (message.error != null && Object.hasOwnProperty.call(message, "error"))
                    writer.uint32(/* id 2, wireType 2 =*/18).string(message.error);
                if (message.batch != null && message.batch.length)
                    for (var i = 0; i < message.batch.length; ++i)
                        $root.perfetto.protos.QueryResult.CellsBatch.encode(message.batch[i], writer.uint32(/* id 3, wireType 2 =*/26).fork()).ldelim();
                return writer;
            };

            /**
             * Encodes the specified QueryResult message, length delimited. Does not implicitly {@link perfetto.protos.QueryResult.verify|verify} messages.
             * @function encodeDelimited
             * @memberof perfetto.protos.QueryResult
             * @static
             * @param {perfetto.protos.IQueryResult} message QueryResult message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            QueryResult.encodeDelimited = function encodeDelimited(message, writer) {
                return this.encode(message, writer).ldelim();
            };

            /**
             * Decodes a QueryResult message from the specified reader or buffer.
             * @function decode
             * @memberof perfetto.protos.QueryResult
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @param {number} [length] Message length if known beforehand
             * @returns {perfetto.protos.QueryResult} QueryResult
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            QueryResult.decode = function decode(reader, length) {
                if (!(reader instanceof $Reader))
                    reader = $Reader.create(reader);
                var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.QueryResult();
                while (reader.pos < end) {
                    var tag = reader.uint32();
                    switch (tag >>> 3) {
                    case 1:
                        if (!(message.columnNames && message.columnNames.length))
                            message.columnNames = [];
                        message.columnNames.push(reader.string());
                        break;
                    case 2:
                        message.error = reader.string();
                        break;
                    case 3:
                        if (!(message.batch && message.batch.length))
                            message.batch = [];
                        message.batch.push($root.perfetto.protos.QueryResult.CellsBatch.decode(reader, reader.uint32()));
                        break;
                    default:
                        reader.skipType(tag & 7);
                        break;
                    }
                }
                return message;
            };

            /**
             * Decodes a QueryResult message from the specified reader or buffer, length delimited.
             * @function decodeDelimited
             * @memberof perfetto.protos.QueryResult
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @returns {perfetto.protos.QueryResult} QueryResult
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            QueryResult.decodeDelimited = function decodeDelimited(reader) {
                if (!(reader instanceof $Reader))
                    reader = new $Reader(reader);
                return this.decode(reader, reader.uint32());
            };

            /**
             * Verifies a QueryResult message.
             * @function verify
             * @memberof perfetto.protos.QueryResult
             * @static
             * @param {Object.<string,*>} message Plain object to verify
             * @returns {string|null} `null` if valid, otherwise the reason why it is not
             */
            QueryResult.verify = function verify(message) {
                if (typeof message !== "object" || message === null)
                    return "object expected";
                if (message.columnNames != null && message.hasOwnProperty("columnNames")) {
                    if (!Array.isArray(message.columnNames))
                        return "columnNames: array expected";
                    for (var i = 0; i < message.columnNames.length; ++i)
                        if (!$util.isString(message.columnNames[i]))
                            return "columnNames: string[] expected";
                }
                if (message.error != null && message.hasOwnProperty("error"))
                    if (!$util.isString(message.error))
                        return "error: string expected";
                if (message.batch != null && message.hasOwnProperty("batch")) {
                    if (!Array.isArray(message.batch))
                        return "batch: array expected";
                    for (var i = 0; i < message.batch.length; ++i) {
                        var error = $root.perfetto.protos.QueryResult.CellsBatch.verify(message.batch[i]);
                        if (error)
                            return "batch." + error;
                    }
                }
                return null;
            };

            /**
             * Creates a QueryResult message from a plain object. Also converts values to their respective internal types.
             * @function fromObject
             * @memberof perfetto.protos.QueryResult
             * @static
             * @param {Object.<string,*>} object Plain object
             * @returns {perfetto.protos.QueryResult} QueryResult
             */
            QueryResult.fromObject = function fromObject(object) {
                if (object instanceof $root.perfetto.protos.QueryResult)
                    return object;
                var message = new $root.perfetto.protos.QueryResult();
                if (object.columnNames) {
                    if (!Array.isArray(object.columnNames))
                        throw TypeError(".perfetto.protos.QueryResult.columnNames: array expected");
                    message.columnNames = [];
                    for (var i = 0; i < object.columnNames.length; ++i)
                        message.columnNames[i] = String(object.columnNames[i]);
                }
                if (object.error != null)
                    message.error = String(object.error);
                if (object.batch) {
                    if (!Array.isArray(object.batch))
                        throw TypeError(".perfetto.protos.QueryResult.batch: array expected");
                    message.batch = [];
                    for (var i = 0; i < object.batch.length; ++i) {
                        if (typeof object.batch[i] !== "object")
                            throw TypeError(".perfetto.protos.QueryResult.batch: object expected");
                        message.batch[i] = $root.perfetto.protos.QueryResult.CellsBatch.fromObject(object.batch[i]);
                    }
                }
                return message;
            };

            /**
             * Creates a plain object from a QueryResult message. Also converts values to other types if specified.
             * @function toObject
             * @memberof perfetto.protos.QueryResult
             * @static
             * @param {perfetto.protos.QueryResult} message QueryResult
             * @param {$protobuf.IConversionOptions} [options] Conversion options
             * @returns {Object.<string,*>} Plain object
             */
            QueryResult.toObject = function toObject(message, options) {
                if (!options)
                    options = {};
                var object = {};
                if (options.arrays || options.defaults) {
                    object.columnNames = [];
                    object.batch = [];
                }
                if (options.defaults)
                    object.error = "";
                if (message.columnNames && message.columnNames.length) {
                    object.columnNames = [];
                    for (var j = 0; j < message.columnNames.length; ++j)
                        object.columnNames[j] = message.columnNames[j];
                }
                if (message.error != null && message.hasOwnProperty("error"))
                    object.error = message.error;
                if (message.batch && message.batch.length) {
                    object.batch = [];
                    for (var j = 0; j < message.batch.length; ++j)
                        object.batch[j] = $root.perfetto.protos.QueryResult.CellsBatch.toObject(message.batch[j], options);
                }
                return object;
            };

            /**
             * Converts this QueryResult to JSON.
             * @function toJSON
             * @memberof perfetto.protos.QueryResult
             * @instance
             * @returns {Object.<string,*>} JSON object
             */
            QueryResult.prototype.toJSON = function toJSON() {
                return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
            };

            QueryResult.CellsBatch = (function() {

                /**
                 * Properties of a CellsBatch.
                 * @memberof perfetto.protos.QueryResult
                 * @interface ICellsBatch
                 * @property {Array.<perfetto.protos.QueryResult.CellsBatch.CellType>|null} [cells] CellsBatch cells
                 * @property {Array.<number>|null} [varintCells] CellsBatch varintCells
                 * @property {Array.<number>|null} [float64Cells] CellsBatch float64Cells
                 * @property {Array.<Uint8Array>|null} [blobCells] CellsBatch blobCells
                 * @property {string|null} [stringCells] CellsBatch stringCells
                 * @property {boolean|null} [isLastBatch] CellsBatch isLastBatch
                 */

                /**
                 * Constructs a new CellsBatch.
                 * @memberof perfetto.protos.QueryResult
                 * @classdesc Represents a CellsBatch.
                 * @implements ICellsBatch
                 * @constructor
                 * @param {perfetto.protos.QueryResult.ICellsBatch=} [properties] Properties to set
                 */
                function CellsBatch(properties) {
                    this.cells = [];
                    this.varintCells = [];
                    this.float64Cells = [];
                    this.blobCells = [];
                    if (properties)
                        for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                            if (properties[keys[i]] != null)
                                this[keys[i]] = properties[keys[i]];
                }

                /**
                 * CellsBatch cells.
                 * @member {Array.<perfetto.protos.QueryResult.CellsBatch.CellType>} cells
                 * @memberof perfetto.protos.QueryResult.CellsBatch
                 * @instance
                 */
                CellsBatch.prototype.cells = $util.emptyArray;

                /**
                 * CellsBatch varintCells.
                 * @member {Array.<number>} varintCells
                 * @memberof perfetto.protos.QueryResult.CellsBatch
                 * @instance
                 */
                CellsBatch.prototype.varintCells = $util.emptyArray;

                /**
                 * CellsBatch float64Cells.
                 * @member {Array.<number>} float64Cells
                 * @memberof perfetto.protos.QueryResult.CellsBatch
                 * @instance
                 */
                CellsBatch.prototype.float64Cells = $util.emptyArray;

                /**
                 * CellsBatch blobCells.
                 * @member {Array.<Uint8Array>} blobCells
                 * @memberof perfetto.protos.QueryResult.CellsBatch
                 * @instance
                 */
                CellsBatch.prototype.blobCells = $util.emptyArray;

                /**
                 * CellsBatch stringCells.
                 * @member {string} stringCells
                 * @memberof perfetto.protos.QueryResult.CellsBatch
                 * @instance
                 */
                CellsBatch.prototype.stringCells = "";

                /**
                 * CellsBatch isLastBatch.
                 * @member {boolean} isLastBatch
                 * @memberof perfetto.protos.QueryResult.CellsBatch
                 * @instance
                 */
                CellsBatch.prototype.isLastBatch = false;

                /**
                 * Creates a new CellsBatch instance using the specified properties.
                 * @function create
                 * @memberof perfetto.protos.QueryResult.CellsBatch
                 * @static
                 * @param {perfetto.protos.QueryResult.ICellsBatch=} [properties] Properties to set
                 * @returns {perfetto.protos.QueryResult.CellsBatch} CellsBatch instance
                 */
                CellsBatch.create = function create(properties) {
                    return new CellsBatch(properties);
                };

                /**
                 * Encodes the specified CellsBatch message. Does not implicitly {@link perfetto.protos.QueryResult.CellsBatch.verify|verify} messages.
                 * @function encode
                 * @memberof perfetto.protos.QueryResult.CellsBatch
                 * @static
                 * @param {perfetto.protos.QueryResult.ICellsBatch} message CellsBatch message or plain object to encode
                 * @param {$protobuf.Writer} [writer] Writer to encode to
                 * @returns {$protobuf.Writer} Writer
                 */
                CellsBatch.encode = function encode(message, writer) {
                    if (!writer)
                        writer = $Writer.create();
                    if (message.cells != null && message.cells.length) {
                        writer.uint32(/* id 1, wireType 2 =*/10).fork();
                        for (var i = 0; i < message.cells.length; ++i)
                            writer.int32(message.cells[i]);
                        writer.ldelim();
                    }
                    if (message.varintCells != null && message.varintCells.length) {
                        writer.uint32(/* id 2, wireType 2 =*/18).fork();
                        for (var i = 0; i < message.varintCells.length; ++i)
                            writer.int64(message.varintCells[i]);
                        writer.ldelim();
                    }
                    if (message.float64Cells != null && message.float64Cells.length) {
                        writer.uint32(/* id 3, wireType 2 =*/26).fork();
                        for (var i = 0; i < message.float64Cells.length; ++i)
                            writer.double(message.float64Cells[i]);
                        writer.ldelim();
                    }
                    if (message.blobCells != null && message.blobCells.length)
                        for (var i = 0; i < message.blobCells.length; ++i)
                            writer.uint32(/* id 4, wireType 2 =*/34).bytes(message.blobCells[i]);
                    if (message.stringCells != null && Object.hasOwnProperty.call(message, "stringCells"))
                        writer.uint32(/* id 5, wireType 2 =*/42).string(message.stringCells);
                    if (message.isLastBatch != null && Object.hasOwnProperty.call(message, "isLastBatch"))
                        writer.uint32(/* id 6, wireType 0 =*/48).bool(message.isLastBatch);
                    return writer;
                };

                /**
                 * Encodes the specified CellsBatch message, length delimited. Does not implicitly {@link perfetto.protos.QueryResult.CellsBatch.verify|verify} messages.
                 * @function encodeDelimited
                 * @memberof perfetto.protos.QueryResult.CellsBatch
                 * @static
                 * @param {perfetto.protos.QueryResult.ICellsBatch} message CellsBatch message or plain object to encode
                 * @param {$protobuf.Writer} [writer] Writer to encode to
                 * @returns {$protobuf.Writer} Writer
                 */
                CellsBatch.encodeDelimited = function encodeDelimited(message, writer) {
                    return this.encode(message, writer).ldelim();
                };

                /**
                 * Decodes a CellsBatch message from the specified reader or buffer.
                 * @function decode
                 * @memberof perfetto.protos.QueryResult.CellsBatch
                 * @static
                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                 * @param {number} [length] Message length if known beforehand
                 * @returns {perfetto.protos.QueryResult.CellsBatch} CellsBatch
                 * @throws {Error} If the payload is not a reader or valid buffer
                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
                 */
                CellsBatch.decode = function decode(reader, length) {
                    if (!(reader instanceof $Reader))
                        reader = $Reader.create(reader);
                    var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.QueryResult.CellsBatch();
                    while (reader.pos < end) {
                        var tag = reader.uint32();
                        switch (tag >>> 3) {
                        case 1:
                            if (!(message.cells && message.cells.length))
                                message.cells = [];
                            if ((tag & 7) === 2) {
                                var end2 = reader.uint32() + reader.pos;
                                while (reader.pos < end2)
                                    message.cells.push(reader.int32());
                            } else
                                message.cells.push(reader.int32());
                            break;
                        case 2:
                            if (!(message.varintCells && message.varintCells.length))
                                message.varintCells = [];
                            if ((tag & 7) === 2) {
                                var end2 = reader.uint32() + reader.pos;
                                while (reader.pos < end2)
                                    message.varintCells.push(reader.int64());
                            } else
                                message.varintCells.push(reader.int64());
                            break;
                        case 3:
                            if (!(message.float64Cells && message.float64Cells.length))
                                message.float64Cells = [];
                            if ((tag & 7) === 2) {
                                var end2 = reader.uint32() + reader.pos;
                                while (reader.pos < end2)
                                    message.float64Cells.push(reader.double());
                            } else
                                message.float64Cells.push(reader.double());
                            break;
                        case 4:
                            if (!(message.blobCells && message.blobCells.length))
                                message.blobCells = [];
                            message.blobCells.push(reader.bytes());
                            break;
                        case 5:
                            message.stringCells = reader.string();
                            break;
                        case 6:
                            message.isLastBatch = reader.bool();
                            break;
                        default:
                            reader.skipType(tag & 7);
                            break;
                        }
                    }
                    return message;
                };

                /**
                 * Decodes a CellsBatch message from the specified reader or buffer, length delimited.
                 * @function decodeDelimited
                 * @memberof perfetto.protos.QueryResult.CellsBatch
                 * @static
                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                 * @returns {perfetto.protos.QueryResult.CellsBatch} CellsBatch
                 * @throws {Error} If the payload is not a reader or valid buffer
                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
                 */
                CellsBatch.decodeDelimited = function decodeDelimited(reader) {
                    if (!(reader instanceof $Reader))
                        reader = new $Reader(reader);
                    return this.decode(reader, reader.uint32());
                };

                /**
                 * Verifies a CellsBatch message.
                 * @function verify
                 * @memberof perfetto.protos.QueryResult.CellsBatch
                 * @static
                 * @param {Object.<string,*>} message Plain object to verify
                 * @returns {string|null} `null` if valid, otherwise the reason why it is not
                 */
                CellsBatch.verify = function verify(message) {
                    if (typeof message !== "object" || message === null)
                        return "object expected";
                    if (message.cells != null && message.hasOwnProperty("cells")) {
                        if (!Array.isArray(message.cells))
                            return "cells: array expected";
                        for (var i = 0; i < message.cells.length; ++i)
                            switch (message.cells[i]) {
                            default:
                                return "cells: enum value[] expected";
                            case 0:
                            case 1:
                            case 2:
                            case 3:
                            case 4:
                            case 5:
                                break;
                            }
                    }
                    if (message.varintCells != null && message.hasOwnProperty("varintCells")) {
                        if (!Array.isArray(message.varintCells))
                            return "varintCells: array expected";
                        for (var i = 0; i < message.varintCells.length; ++i)
                            if (!$util.isInteger(message.varintCells[i]) && !(message.varintCells[i] && $util.isInteger(message.varintCells[i].low) && $util.isInteger(message.varintCells[i].high)))
                                return "varintCells: integer|Long[] expected";
                    }
                    if (message.float64Cells != null && message.hasOwnProperty("float64Cells")) {
                        if (!Array.isArray(message.float64Cells))
                            return "float64Cells: array expected";
                        for (var i = 0; i < message.float64Cells.length; ++i)
                            if (typeof message.float64Cells[i] !== "number")
                                return "float64Cells: number[] expected";
                    }
                    if (message.blobCells != null && message.hasOwnProperty("blobCells")) {
                        if (!Array.isArray(message.blobCells))
                            return "blobCells: array expected";
                        for (var i = 0; i < message.blobCells.length; ++i)
                            if (!(message.blobCells[i] && typeof message.blobCells[i].length === "number" || $util.isString(message.blobCells[i])))
                                return "blobCells: buffer[] expected";
                    }
                    if (message.stringCells != null && message.hasOwnProperty("stringCells"))
                        if (!$util.isString(message.stringCells))
                            return "stringCells: string expected";
                    if (message.isLastBatch != null && message.hasOwnProperty("isLastBatch"))
                        if (typeof message.isLastBatch !== "boolean")
                            return "isLastBatch: boolean expected";
                    return null;
                };

                /**
                 * Creates a CellsBatch message from a plain object. Also converts values to their respective internal types.
                 * @function fromObject
                 * @memberof perfetto.protos.QueryResult.CellsBatch
                 * @static
                 * @param {Object.<string,*>} object Plain object
                 * @returns {perfetto.protos.QueryResult.CellsBatch} CellsBatch
                 */
                CellsBatch.fromObject = function fromObject(object) {
                    if (object instanceof $root.perfetto.protos.QueryResult.CellsBatch)
                        return object;
                    var message = new $root.perfetto.protos.QueryResult.CellsBatch();
                    if (object.cells) {
                        if (!Array.isArray(object.cells))
                            throw TypeError(".perfetto.protos.QueryResult.CellsBatch.cells: array expected");
                        message.cells = [];
                        for (var i = 0; i < object.cells.length; ++i)
                            switch (object.cells[i]) {
                            default:
                            case "CELL_INVALID":
                            case 0:
                                message.cells[i] = 0;
                                break;
                            case "CELL_NULL":
                            case 1:
                                message.cells[i] = 1;
                                break;
                            case "CELL_VARINT":
                            case 2:
                                message.cells[i] = 2;
                                break;
                            case "CELL_FLOAT64":
                            case 3:
                                message.cells[i] = 3;
                                break;
                            case "CELL_STRING":
                            case 4:
                                message.cells[i] = 4;
                                break;
                            case "CELL_BLOB":
                            case 5:
                                message.cells[i] = 5;
                                break;
                            }
                    }
                    if (object.varintCells) {
                        if (!Array.isArray(object.varintCells))
                            throw TypeError(".perfetto.protos.QueryResult.CellsBatch.varintCells: array expected");
                        message.varintCells = [];
                        for (var i = 0; i < object.varintCells.length; ++i)
                            if ($util.Long)
                                (message.varintCells[i] = $util.Long.fromValue(object.varintCells[i])).unsigned = false;
                            else if (typeof object.varintCells[i] === "string")
                                message.varintCells[i] = parseInt(object.varintCells[i], 10);
                            else if (typeof object.varintCells[i] === "number")
                                message.varintCells[i] = object.varintCells[i];
                            else if (typeof object.varintCells[i] === "object")
                                message.varintCells[i] = new $util.LongBits(object.varintCells[i].low >>> 0, object.varintCells[i].high >>> 0).toNumber();
                    }
                    if (object.float64Cells) {
                        if (!Array.isArray(object.float64Cells))
                            throw TypeError(".perfetto.protos.QueryResult.CellsBatch.float64Cells: array expected");
                        message.float64Cells = [];
                        for (var i = 0; i < object.float64Cells.length; ++i)
                            message.float64Cells[i] = Number(object.float64Cells[i]);
                    }
                    if (object.blobCells) {
                        if (!Array.isArray(object.blobCells))
                            throw TypeError(".perfetto.protos.QueryResult.CellsBatch.blobCells: array expected");
                        message.blobCells = [];
                        for (var i = 0; i < object.blobCells.length; ++i)
                            if (typeof object.blobCells[i] === "string")
                                $util.base64.decode(object.blobCells[i], message.blobCells[i] = $util.newBuffer($util.base64.length(object.blobCells[i])), 0);
                            else if (object.blobCells[i].length)
                                message.blobCells[i] = object.blobCells[i];
                    }
                    if (object.stringCells != null)
                        message.stringCells = String(object.stringCells);
                    if (object.isLastBatch != null)
                        message.isLastBatch = Boolean(object.isLastBatch);
                    return message;
                };

                /**
                 * Creates a plain object from a CellsBatch message. Also converts values to other types if specified.
                 * @function toObject
                 * @memberof perfetto.protos.QueryResult.CellsBatch
                 * @static
                 * @param {perfetto.protos.QueryResult.CellsBatch} message CellsBatch
                 * @param {$protobuf.IConversionOptions} [options] Conversion options
                 * @returns {Object.<string,*>} Plain object
                 */
                CellsBatch.toObject = function toObject(message, options) {
                    if (!options)
                        options = {};
                    var object = {};
                    if (options.arrays || options.defaults) {
                        object.cells = [];
                        object.varintCells = [];
                        object.float64Cells = [];
                        object.blobCells = [];
                    }
                    if (options.defaults) {
                        object.stringCells = "";
                        object.isLastBatch = false;
                    }
                    if (message.cells && message.cells.length) {
                        object.cells = [];
                        for (var j = 0; j < message.cells.length; ++j)
                            object.cells[j] = options.enums === String ? $root.perfetto.protos.QueryResult.CellsBatch.CellType[message.cells[j]] : message.cells[j];
                    }
                    if (message.varintCells && message.varintCells.length) {
                        object.varintCells = [];
                        for (var j = 0; j < message.varintCells.length; ++j)
                            if (typeof message.varintCells[j] === "number")
                                object.varintCells[j] = options.longs === String ? String(message.varintCells[j]) : message.varintCells[j];
                            else
                                object.varintCells[j] = options.longs === String ? $util.Long.prototype.toString.call(message.varintCells[j]) : options.longs === Number ? new $util.LongBits(message.varintCells[j].low >>> 0, message.varintCells[j].high >>> 0).toNumber() : message.varintCells[j];
                    }
                    if (message.float64Cells && message.float64Cells.length) {
                        object.float64Cells = [];
                        for (var j = 0; j < message.float64Cells.length; ++j)
                            object.float64Cells[j] = options.json && !isFinite(message.float64Cells[j]) ? String(message.float64Cells[j]) : message.float64Cells[j];
                    }
                    if (message.blobCells && message.blobCells.length) {
                        object.blobCells = [];
                        for (var j = 0; j < message.blobCells.length; ++j)
                            object.blobCells[j] = options.bytes === String ? $util.base64.encode(message.blobCells[j], 0, message.blobCells[j].length) : options.bytes === Array ? Array.prototype.slice.call(message.blobCells[j]) : message.blobCells[j];
                    }
                    if (message.stringCells != null && message.hasOwnProperty("stringCells"))
                        object.stringCells = message.stringCells;
                    if (message.isLastBatch != null && message.hasOwnProperty("isLastBatch"))
                        object.isLastBatch = message.isLastBatch;
                    return object;
                };

                /**
                 * Converts this CellsBatch to JSON.
                 * @function toJSON
                 * @memberof perfetto.protos.QueryResult.CellsBatch
                 * @instance
                 * @returns {Object.<string,*>} JSON object
                 */
                CellsBatch.prototype.toJSON = function toJSON() {
                    return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
                };

                /**
                 * CellType enum.
                 * @name perfetto.protos.QueryResult.CellsBatch.CellType
                 * @enum {number}
                 * @property {number} CELL_INVALID=0 CELL_INVALID value
                 * @property {number} CELL_NULL=1 CELL_NULL value
                 * @property {number} CELL_VARINT=2 CELL_VARINT value
                 * @property {number} CELL_FLOAT64=3 CELL_FLOAT64 value
                 * @property {number} CELL_STRING=4 CELL_STRING value
                 * @property {number} CELL_BLOB=5 CELL_BLOB value
                 */
                CellsBatch.CellType = (function() {
                    var valuesById = {}, values = Object.create(valuesById);
                    values[valuesById[0] = "CELL_INVALID"] = 0;
                    values[valuesById[1] = "CELL_NULL"] = 1;
                    values[valuesById[2] = "CELL_VARINT"] = 2;
                    values[valuesById[3] = "CELL_FLOAT64"] = 3;
                    values[valuesById[4] = "CELL_STRING"] = 4;
                    values[valuesById[5] = "CELL_BLOB"] = 5;
                    return values;
                })();

                return CellsBatch;
            })();

            return QueryResult;
        })();

        protos.StatusArgs = (function() {

            /**
             * Properties of a StatusArgs.
             * @memberof perfetto.protos
             * @interface IStatusArgs
             */

            /**
             * Constructs a new StatusArgs.
             * @memberof perfetto.protos
             * @classdesc Represents a StatusArgs.
             * @implements IStatusArgs
             * @constructor
             * @param {perfetto.protos.IStatusArgs=} [properties] Properties to set
             */
            function StatusArgs(properties) {
                if (properties)
                    for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                        if (properties[keys[i]] != null)
                            this[keys[i]] = properties[keys[i]];
            }

            /**
             * Creates a new StatusArgs instance using the specified properties.
             * @function create
             * @memberof perfetto.protos.StatusArgs
             * @static
             * @param {perfetto.protos.IStatusArgs=} [properties] Properties to set
             * @returns {perfetto.protos.StatusArgs} StatusArgs instance
             */
            StatusArgs.create = function create(properties) {
                return new StatusArgs(properties);
            };

            /**
             * Encodes the specified StatusArgs message. Does not implicitly {@link perfetto.protos.StatusArgs.verify|verify} messages.
             * @function encode
             * @memberof perfetto.protos.StatusArgs
             * @static
             * @param {perfetto.protos.IStatusArgs} message StatusArgs message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            StatusArgs.encode = function encode(message, writer) {
                if (!writer)
                    writer = $Writer.create();
                return writer;
            };

            /**
             * Encodes the specified StatusArgs message, length delimited. Does not implicitly {@link perfetto.protos.StatusArgs.verify|verify} messages.
             * @function encodeDelimited
             * @memberof perfetto.protos.StatusArgs
             * @static
             * @param {perfetto.protos.IStatusArgs} message StatusArgs message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            StatusArgs.encodeDelimited = function encodeDelimited(message, writer) {
                return this.encode(message, writer).ldelim();
            };

            /**
             * Decodes a StatusArgs message from the specified reader or buffer.
             * @function decode
             * @memberof perfetto.protos.StatusArgs
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @param {number} [length] Message length if known beforehand
             * @returns {perfetto.protos.StatusArgs} StatusArgs
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            StatusArgs.decode = function decode(reader, length) {
                if (!(reader instanceof $Reader))
                    reader = $Reader.create(reader);
                var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.StatusArgs();
                while (reader.pos < end) {
                    var tag = reader.uint32();
                    switch (tag >>> 3) {
                    default:
                        reader.skipType(tag & 7);
                        break;
                    }
                }
                return message;
            };

            /**
             * Decodes a StatusArgs message from the specified reader or buffer, length delimited.
             * @function decodeDelimited
             * @memberof perfetto.protos.StatusArgs
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @returns {perfetto.protos.StatusArgs} StatusArgs
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            StatusArgs.decodeDelimited = function decodeDelimited(reader) {
                if (!(reader instanceof $Reader))
                    reader = new $Reader(reader);
                return this.decode(reader, reader.uint32());
            };

            /**
             * Verifies a StatusArgs message.
             * @function verify
             * @memberof perfetto.protos.StatusArgs
             * @static
             * @param {Object.<string,*>} message Plain object to verify
             * @returns {string|null} `null` if valid, otherwise the reason why it is not
             */
            StatusArgs.verify = function verify(message) {
                if (typeof message !== "object" || message === null)
                    return "object expected";
                return null;
            };

            /**
             * Creates a StatusArgs message from a plain object. Also converts values to their respective internal types.
             * @function fromObject
             * @memberof perfetto.protos.StatusArgs
             * @static
             * @param {Object.<string,*>} object Plain object
             * @returns {perfetto.protos.StatusArgs} StatusArgs
             */
            StatusArgs.fromObject = function fromObject(object) {
                if (object instanceof $root.perfetto.protos.StatusArgs)
                    return object;
                return new $root.perfetto.protos.StatusArgs();
            };

            /**
             * Creates a plain object from a StatusArgs message. Also converts values to other types if specified.
             * @function toObject
             * @memberof perfetto.protos.StatusArgs
             * @static
             * @param {perfetto.protos.StatusArgs} message StatusArgs
             * @param {$protobuf.IConversionOptions} [options] Conversion options
             * @returns {Object.<string,*>} Plain object
             */
            StatusArgs.toObject = function toObject() {
                return {};
            };

            /**
             * Converts this StatusArgs to JSON.
             * @function toJSON
             * @memberof perfetto.protos.StatusArgs
             * @instance
             * @returns {Object.<string,*>} JSON object
             */
            StatusArgs.prototype.toJSON = function toJSON() {
                return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
            };

            return StatusArgs;
        })();

        protos.StatusResult = (function() {

            /**
             * Properties of a StatusResult.
             * @memberof perfetto.protos
             * @interface IStatusResult
             * @property {string|null} [loadedTraceName] StatusResult loadedTraceName
             */

            /**
             * Constructs a new StatusResult.
             * @memberof perfetto.protos
             * @classdesc Represents a StatusResult.
             * @implements IStatusResult
             * @constructor
             * @param {perfetto.protos.IStatusResult=} [properties] Properties to set
             */
            function StatusResult(properties) {
                if (properties)
                    for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                        if (properties[keys[i]] != null)
                            this[keys[i]] = properties[keys[i]];
            }

            /**
             * StatusResult loadedTraceName.
             * @member {string} loadedTraceName
             * @memberof perfetto.protos.StatusResult
             * @instance
             */
            StatusResult.prototype.loadedTraceName = "";

            /**
             * Creates a new StatusResult instance using the specified properties.
             * @function create
             * @memberof perfetto.protos.StatusResult
             * @static
             * @param {perfetto.protos.IStatusResult=} [properties] Properties to set
             * @returns {perfetto.protos.StatusResult} StatusResult instance
             */
            StatusResult.create = function create(properties) {
                return new StatusResult(properties);
            };

            /**
             * Encodes the specified StatusResult message. Does not implicitly {@link perfetto.protos.StatusResult.verify|verify} messages.
             * @function encode
             * @memberof perfetto.protos.StatusResult
             * @static
             * @param {perfetto.protos.IStatusResult} message StatusResult message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            StatusResult.encode = function encode(message, writer) {
                if (!writer)
                    writer = $Writer.create();
                if (message.loadedTraceName != null && Object.hasOwnProperty.call(message, "loadedTraceName"))
                    writer.uint32(/* id 1, wireType 2 =*/10).string(message.loadedTraceName);
                return writer;
            };

            /**
             * Encodes the specified StatusResult message, length delimited. Does not implicitly {@link perfetto.protos.StatusResult.verify|verify} messages.
             * @function encodeDelimited
             * @memberof perfetto.protos.StatusResult
             * @static
             * @param {perfetto.protos.IStatusResult} message StatusResult message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            StatusResult.encodeDelimited = function encodeDelimited(message, writer) {
                return this.encode(message, writer).ldelim();
            };

            /**
             * Decodes a StatusResult message from the specified reader or buffer.
             * @function decode
             * @memberof perfetto.protos.StatusResult
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @param {number} [length] Message length if known beforehand
             * @returns {perfetto.protos.StatusResult} StatusResult
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            StatusResult.decode = function decode(reader, length) {
                if (!(reader instanceof $Reader))
                    reader = $Reader.create(reader);
                var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.StatusResult();
                while (reader.pos < end) {
                    var tag = reader.uint32();
                    switch (tag >>> 3) {
                    case 1:
                        message.loadedTraceName = reader.string();
                        break;
                    default:
                        reader.skipType(tag & 7);
                        break;
                    }
                }
                return message;
            };

            /**
             * Decodes a StatusResult message from the specified reader or buffer, length delimited.
             * @function decodeDelimited
             * @memberof perfetto.protos.StatusResult
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @returns {perfetto.protos.StatusResult} StatusResult
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            StatusResult.decodeDelimited = function decodeDelimited(reader) {
                if (!(reader instanceof $Reader))
                    reader = new $Reader(reader);
                return this.decode(reader, reader.uint32());
            };

            /**
             * Verifies a StatusResult message.
             * @function verify
             * @memberof perfetto.protos.StatusResult
             * @static
             * @param {Object.<string,*>} message Plain object to verify
             * @returns {string|null} `null` if valid, otherwise the reason why it is not
             */
            StatusResult.verify = function verify(message) {
                if (typeof message !== "object" || message === null)
                    return "object expected";
                if (message.loadedTraceName != null && message.hasOwnProperty("loadedTraceName"))
                    if (!$util.isString(message.loadedTraceName))
                        return "loadedTraceName: string expected";
                return null;
            };

            /**
             * Creates a StatusResult message from a plain object. Also converts values to their respective internal types.
             * @function fromObject
             * @memberof perfetto.protos.StatusResult
             * @static
             * @param {Object.<string,*>} object Plain object
             * @returns {perfetto.protos.StatusResult} StatusResult
             */
            StatusResult.fromObject = function fromObject(object) {
                if (object instanceof $root.perfetto.protos.StatusResult)
                    return object;
                var message = new $root.perfetto.protos.StatusResult();
                if (object.loadedTraceName != null)
                    message.loadedTraceName = String(object.loadedTraceName);
                return message;
            };

            /**
             * Creates a plain object from a StatusResult message. Also converts values to other types if specified.
             * @function toObject
             * @memberof perfetto.protos.StatusResult
             * @static
             * @param {perfetto.protos.StatusResult} message StatusResult
             * @param {$protobuf.IConversionOptions} [options] Conversion options
             * @returns {Object.<string,*>} Plain object
             */
            StatusResult.toObject = function toObject(message, options) {
                if (!options)
                    options = {};
                var object = {};
                if (options.defaults)
                    object.loadedTraceName = "";
                if (message.loadedTraceName != null && message.hasOwnProperty("loadedTraceName"))
                    object.loadedTraceName = message.loadedTraceName;
                return object;
            };

            /**
             * Converts this StatusResult to JSON.
             * @function toJSON
             * @memberof perfetto.protos.StatusResult
             * @instance
             * @returns {Object.<string,*>} JSON object
             */
            StatusResult.prototype.toJSON = function toJSON() {
                return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
            };

            return StatusResult;
        })();

        protos.ComputeMetricArgs = (function() {

            /**
             * Properties of a ComputeMetricArgs.
             * @memberof perfetto.protos
             * @interface IComputeMetricArgs
             * @property {Array.<string>|null} [metricNames] ComputeMetricArgs metricNames
             * @property {perfetto.protos.ComputeMetricArgs.ResultFormat|null} [format] ComputeMetricArgs format
             */

            /**
             * Constructs a new ComputeMetricArgs.
             * @memberof perfetto.protos
             * @classdesc Represents a ComputeMetricArgs.
             * @implements IComputeMetricArgs
             * @constructor
             * @param {perfetto.protos.IComputeMetricArgs=} [properties] Properties to set
             */
            function ComputeMetricArgs(properties) {
                this.metricNames = [];
                if (properties)
                    for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                        if (properties[keys[i]] != null)
                            this[keys[i]] = properties[keys[i]];
            }

            /**
             * ComputeMetricArgs metricNames.
             * @member {Array.<string>} metricNames
             * @memberof perfetto.protos.ComputeMetricArgs
             * @instance
             */
            ComputeMetricArgs.prototype.metricNames = $util.emptyArray;

            /**
             * ComputeMetricArgs format.
             * @member {perfetto.protos.ComputeMetricArgs.ResultFormat} format
             * @memberof perfetto.protos.ComputeMetricArgs
             * @instance
             */
            ComputeMetricArgs.prototype.format = 0;

            /**
             * Creates a new ComputeMetricArgs instance using the specified properties.
             * @function create
             * @memberof perfetto.protos.ComputeMetricArgs
             * @static
             * @param {perfetto.protos.IComputeMetricArgs=} [properties] Properties to set
             * @returns {perfetto.protos.ComputeMetricArgs} ComputeMetricArgs instance
             */
            ComputeMetricArgs.create = function create(properties) {
                return new ComputeMetricArgs(properties);
            };

            /**
             * Encodes the specified ComputeMetricArgs message. Does not implicitly {@link perfetto.protos.ComputeMetricArgs.verify|verify} messages.
             * @function encode
             * @memberof perfetto.protos.ComputeMetricArgs
             * @static
             * @param {perfetto.protos.IComputeMetricArgs} message ComputeMetricArgs message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            ComputeMetricArgs.encode = function encode(message, writer) {
                if (!writer)
                    writer = $Writer.create();
                if (message.metricNames != null && message.metricNames.length)
                    for (var i = 0; i < message.metricNames.length; ++i)
                        writer.uint32(/* id 1, wireType 2 =*/10).string(message.metricNames[i]);
                if (message.format != null && Object.hasOwnProperty.call(message, "format"))
                    writer.uint32(/* id 2, wireType 0 =*/16).int32(message.format);
                return writer;
            };

            /**
             * Encodes the specified ComputeMetricArgs message, length delimited. Does not implicitly {@link perfetto.protos.ComputeMetricArgs.verify|verify} messages.
             * @function encodeDelimited
             * @memberof perfetto.protos.ComputeMetricArgs
             * @static
             * @param {perfetto.protos.IComputeMetricArgs} message ComputeMetricArgs message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            ComputeMetricArgs.encodeDelimited = function encodeDelimited(message, writer) {
                return this.encode(message, writer).ldelim();
            };

            /**
             * Decodes a ComputeMetricArgs message from the specified reader or buffer.
             * @function decode
             * @memberof perfetto.protos.ComputeMetricArgs
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @param {number} [length] Message length if known beforehand
             * @returns {perfetto.protos.ComputeMetricArgs} ComputeMetricArgs
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            ComputeMetricArgs.decode = function decode(reader, length) {
                if (!(reader instanceof $Reader))
                    reader = $Reader.create(reader);
                var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.ComputeMetricArgs();
                while (reader.pos < end) {
                    var tag = reader.uint32();
                    switch (tag >>> 3) {
                    case 1:
                        if (!(message.metricNames && message.metricNames.length))
                            message.metricNames = [];
                        message.metricNames.push(reader.string());
                        break;
                    case 2:
                        message.format = reader.int32();
                        break;
                    default:
                        reader.skipType(tag & 7);
                        break;
                    }
                }
                return message;
            };

            /**
             * Decodes a ComputeMetricArgs message from the specified reader or buffer, length delimited.
             * @function decodeDelimited
             * @memberof perfetto.protos.ComputeMetricArgs
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @returns {perfetto.protos.ComputeMetricArgs} ComputeMetricArgs
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            ComputeMetricArgs.decodeDelimited = function decodeDelimited(reader) {
                if (!(reader instanceof $Reader))
                    reader = new $Reader(reader);
                return this.decode(reader, reader.uint32());
            };

            /**
             * Verifies a ComputeMetricArgs message.
             * @function verify
             * @memberof perfetto.protos.ComputeMetricArgs
             * @static
             * @param {Object.<string,*>} message Plain object to verify
             * @returns {string|null} `null` if valid, otherwise the reason why it is not
             */
            ComputeMetricArgs.verify = function verify(message) {
                if (typeof message !== "object" || message === null)
                    return "object expected";
                if (message.metricNames != null && message.hasOwnProperty("metricNames")) {
                    if (!Array.isArray(message.metricNames))
                        return "metricNames: array expected";
                    for (var i = 0; i < message.metricNames.length; ++i)
                        if (!$util.isString(message.metricNames[i]))
                            return "metricNames: string[] expected";
                }
                if (message.format != null && message.hasOwnProperty("format"))
                    switch (message.format) {
                    default:
                        return "format: enum value expected";
                    case 0:
                    case 1:
                        break;
                    }
                return null;
            };

            /**
             * Creates a ComputeMetricArgs message from a plain object. Also converts values to their respective internal types.
             * @function fromObject
             * @memberof perfetto.protos.ComputeMetricArgs
             * @static
             * @param {Object.<string,*>} object Plain object
             * @returns {perfetto.protos.ComputeMetricArgs} ComputeMetricArgs
             */
            ComputeMetricArgs.fromObject = function fromObject(object) {
                if (object instanceof $root.perfetto.protos.ComputeMetricArgs)
                    return object;
                var message = new $root.perfetto.protos.ComputeMetricArgs();
                if (object.metricNames) {
                    if (!Array.isArray(object.metricNames))
                        throw TypeError(".perfetto.protos.ComputeMetricArgs.metricNames: array expected");
                    message.metricNames = [];
                    for (var i = 0; i < object.metricNames.length; ++i)
                        message.metricNames[i] = String(object.metricNames[i]);
                }
                switch (object.format) {
                case "BINARY_PROTOBUF":
                case 0:
                    message.format = 0;
                    break;
                case "TEXTPROTO":
                case 1:
                    message.format = 1;
                    break;
                }
                return message;
            };

            /**
             * Creates a plain object from a ComputeMetricArgs message. Also converts values to other types if specified.
             * @function toObject
             * @memberof perfetto.protos.ComputeMetricArgs
             * @static
             * @param {perfetto.protos.ComputeMetricArgs} message ComputeMetricArgs
             * @param {$protobuf.IConversionOptions} [options] Conversion options
             * @returns {Object.<string,*>} Plain object
             */
            ComputeMetricArgs.toObject = function toObject(message, options) {
                if (!options)
                    options = {};
                var object = {};
                if (options.arrays || options.defaults)
                    object.metricNames = [];
                if (options.defaults)
                    object.format = options.enums === String ? "BINARY_PROTOBUF" : 0;
                if (message.metricNames && message.metricNames.length) {
                    object.metricNames = [];
                    for (var j = 0; j < message.metricNames.length; ++j)
                        object.metricNames[j] = message.metricNames[j];
                }
                if (message.format != null && message.hasOwnProperty("format"))
                    object.format = options.enums === String ? $root.perfetto.protos.ComputeMetricArgs.ResultFormat[message.format] : message.format;
                return object;
            };

            /**
             * Converts this ComputeMetricArgs to JSON.
             * @function toJSON
             * @memberof perfetto.protos.ComputeMetricArgs
             * @instance
             * @returns {Object.<string,*>} JSON object
             */
            ComputeMetricArgs.prototype.toJSON = function toJSON() {
                return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
            };

            /**
             * ResultFormat enum.
             * @name perfetto.protos.ComputeMetricArgs.ResultFormat
             * @enum {number}
             * @property {number} BINARY_PROTOBUF=0 BINARY_PROTOBUF value
             * @property {number} TEXTPROTO=1 TEXTPROTO value
             */
            ComputeMetricArgs.ResultFormat = (function() {
                var valuesById = {}, values = Object.create(valuesById);
                values[valuesById[0] = "BINARY_PROTOBUF"] = 0;
                values[valuesById[1] = "TEXTPROTO"] = 1;
                return values;
            })();

            return ComputeMetricArgs;
        })();

        protos.ComputeMetricResult = (function() {

            /**
             * Properties of a ComputeMetricResult.
             * @memberof perfetto.protos
             * @interface IComputeMetricResult
             * @property {Uint8Array|null} [metrics] ComputeMetricResult metrics
             * @property {string|null} [metricsAsPrototext] ComputeMetricResult metricsAsPrototext
             * @property {string|null} [error] ComputeMetricResult error
             */

            /**
             * Constructs a new ComputeMetricResult.
             * @memberof perfetto.protos
             * @classdesc Represents a ComputeMetricResult.
             * @implements IComputeMetricResult
             * @constructor
             * @param {perfetto.protos.IComputeMetricResult=} [properties] Properties to set
             */
            function ComputeMetricResult(properties) {
                if (properties)
                    for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                        if (properties[keys[i]] != null)
                            this[keys[i]] = properties[keys[i]];
            }

            /**
             * ComputeMetricResult metrics.
             * @member {Uint8Array} metrics
             * @memberof perfetto.protos.ComputeMetricResult
             * @instance
             */
            ComputeMetricResult.prototype.metrics = $util.newBuffer([]);

            /**
             * ComputeMetricResult metricsAsPrototext.
             * @member {string} metricsAsPrototext
             * @memberof perfetto.protos.ComputeMetricResult
             * @instance
             */
            ComputeMetricResult.prototype.metricsAsPrototext = "";

            /**
             * ComputeMetricResult error.
             * @member {string} error
             * @memberof perfetto.protos.ComputeMetricResult
             * @instance
             */
            ComputeMetricResult.prototype.error = "";

            // OneOf field names bound to virtual getters and setters
            var $oneOfFields;

            /**
             * ComputeMetricResult result.
             * @member {"metrics"|"metricsAsPrototext"|undefined} result
             * @memberof perfetto.protos.ComputeMetricResult
             * @instance
             */
            Object.defineProperty(ComputeMetricResult.prototype, "result", {
                get: $util.oneOfGetter($oneOfFields = ["metrics", "metricsAsPrototext"]),
                set: $util.oneOfSetter($oneOfFields)
            });

            /**
             * Creates a new ComputeMetricResult instance using the specified properties.
             * @function create
             * @memberof perfetto.protos.ComputeMetricResult
             * @static
             * @param {perfetto.protos.IComputeMetricResult=} [properties] Properties to set
             * @returns {perfetto.protos.ComputeMetricResult} ComputeMetricResult instance
             */
            ComputeMetricResult.create = function create(properties) {
                return new ComputeMetricResult(properties);
            };

            /**
             * Encodes the specified ComputeMetricResult message. Does not implicitly {@link perfetto.protos.ComputeMetricResult.verify|verify} messages.
             * @function encode
             * @memberof perfetto.protos.ComputeMetricResult
             * @static
             * @param {perfetto.protos.IComputeMetricResult} message ComputeMetricResult message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            ComputeMetricResult.encode = function encode(message, writer) {
                if (!writer)
                    writer = $Writer.create();
                if (message.metrics != null && Object.hasOwnProperty.call(message, "metrics"))
                    writer.uint32(/* id 1, wireType 2 =*/10).bytes(message.metrics);
                if (message.error != null && Object.hasOwnProperty.call(message, "error"))
                    writer.uint32(/* id 2, wireType 2 =*/18).string(message.error);
                if (message.metricsAsPrototext != null && Object.hasOwnProperty.call(message, "metricsAsPrototext"))
                    writer.uint32(/* id 3, wireType 2 =*/26).string(message.metricsAsPrototext);
                return writer;
            };

            /**
             * Encodes the specified ComputeMetricResult message, length delimited. Does not implicitly {@link perfetto.protos.ComputeMetricResult.verify|verify} messages.
             * @function encodeDelimited
             * @memberof perfetto.protos.ComputeMetricResult
             * @static
             * @param {perfetto.protos.IComputeMetricResult} message ComputeMetricResult message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            ComputeMetricResult.encodeDelimited = function encodeDelimited(message, writer) {
                return this.encode(message, writer).ldelim();
            };

            /**
             * Decodes a ComputeMetricResult message from the specified reader or buffer.
             * @function decode
             * @memberof perfetto.protos.ComputeMetricResult
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @param {number} [length] Message length if known beforehand
             * @returns {perfetto.protos.ComputeMetricResult} ComputeMetricResult
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            ComputeMetricResult.decode = function decode(reader, length) {
                if (!(reader instanceof $Reader))
                    reader = $Reader.create(reader);
                var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.ComputeMetricResult();
                while (reader.pos < end) {
                    var tag = reader.uint32();
                    switch (tag >>> 3) {
                    case 1:
                        message.metrics = reader.bytes();
                        break;
                    case 3:
                        message.metricsAsPrototext = reader.string();
                        break;
                    case 2:
                        message.error = reader.string();
                        break;
                    default:
                        reader.skipType(tag & 7);
                        break;
                    }
                }
                return message;
            };

            /**
             * Decodes a ComputeMetricResult message from the specified reader or buffer, length delimited.
             * @function decodeDelimited
             * @memberof perfetto.protos.ComputeMetricResult
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @returns {perfetto.protos.ComputeMetricResult} ComputeMetricResult
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            ComputeMetricResult.decodeDelimited = function decodeDelimited(reader) {
                if (!(reader instanceof $Reader))
                    reader = new $Reader(reader);
                return this.decode(reader, reader.uint32());
            };

            /**
             * Verifies a ComputeMetricResult message.
             * @function verify
             * @memberof perfetto.protos.ComputeMetricResult
             * @static
             * @param {Object.<string,*>} message Plain object to verify
             * @returns {string|null} `null` if valid, otherwise the reason why it is not
             */
            ComputeMetricResult.verify = function verify(message) {
                if (typeof message !== "object" || message === null)
                    return "object expected";
                var properties = {};
                if (message.metrics != null && message.hasOwnProperty("metrics")) {
                    properties.result = 1;
                    if (!(message.metrics && typeof message.metrics.length === "number" || $util.isString(message.metrics)))
                        return "metrics: buffer expected";
                }
                if (message.metricsAsPrototext != null && message.hasOwnProperty("metricsAsPrototext")) {
                    if (properties.result === 1)
                        return "result: multiple values";
                    properties.result = 1;
                    if (!$util.isString(message.metricsAsPrototext))
                        return "metricsAsPrototext: string expected";
                }
                if (message.error != null && message.hasOwnProperty("error"))
                    if (!$util.isString(message.error))
                        return "error: string expected";
                return null;
            };

            /**
             * Creates a ComputeMetricResult message from a plain object. Also converts values to their respective internal types.
             * @function fromObject
             * @memberof perfetto.protos.ComputeMetricResult
             * @static
             * @param {Object.<string,*>} object Plain object
             * @returns {perfetto.protos.ComputeMetricResult} ComputeMetricResult
             */
            ComputeMetricResult.fromObject = function fromObject(object) {
                if (object instanceof $root.perfetto.protos.ComputeMetricResult)
                    return object;
                var message = new $root.perfetto.protos.ComputeMetricResult();
                if (object.metrics != null)
                    if (typeof object.metrics === "string")
                        $util.base64.decode(object.metrics, message.metrics = $util.newBuffer($util.base64.length(object.metrics)), 0);
                    else if (object.metrics.length)
                        message.metrics = object.metrics;
                if (object.metricsAsPrototext != null)
                    message.metricsAsPrototext = String(object.metricsAsPrototext);
                if (object.error != null)
                    message.error = String(object.error);
                return message;
            };

            /**
             * Creates a plain object from a ComputeMetricResult message. Also converts values to other types if specified.
             * @function toObject
             * @memberof perfetto.protos.ComputeMetricResult
             * @static
             * @param {perfetto.protos.ComputeMetricResult} message ComputeMetricResult
             * @param {$protobuf.IConversionOptions} [options] Conversion options
             * @returns {Object.<string,*>} Plain object
             */
            ComputeMetricResult.toObject = function toObject(message, options) {
                if (!options)
                    options = {};
                var object = {};
                if (options.defaults)
                    object.error = "";
                if (message.metrics != null && message.hasOwnProperty("metrics")) {
                    object.metrics = options.bytes === String ? $util.base64.encode(message.metrics, 0, message.metrics.length) : options.bytes === Array ? Array.prototype.slice.call(message.metrics) : message.metrics;
                    if (options.oneofs)
                        object.result = "metrics";
                }
                if (message.error != null && message.hasOwnProperty("error"))
                    object.error = message.error;
                if (message.metricsAsPrototext != null && message.hasOwnProperty("metricsAsPrototext")) {
                    object.metricsAsPrototext = message.metricsAsPrototext;
                    if (options.oneofs)
                        object.result = "metricsAsPrototext";
                }
                return object;
            };

            /**
             * Converts this ComputeMetricResult to JSON.
             * @function toJSON
             * @memberof perfetto.protos.ComputeMetricResult
             * @instance
             * @returns {Object.<string,*>} JSON object
             */
            ComputeMetricResult.prototype.toJSON = function toJSON() {
                return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
            };

            return ComputeMetricResult;
        })();

        protos.EnableMetatraceArgs = (function() {

            /**
             * Properties of an EnableMetatraceArgs.
             * @memberof perfetto.protos
             * @interface IEnableMetatraceArgs
             */

            /**
             * Constructs a new EnableMetatraceArgs.
             * @memberof perfetto.protos
             * @classdesc Represents an EnableMetatraceArgs.
             * @implements IEnableMetatraceArgs
             * @constructor
             * @param {perfetto.protos.IEnableMetatraceArgs=} [properties] Properties to set
             */
            function EnableMetatraceArgs(properties) {
                if (properties)
                    for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                        if (properties[keys[i]] != null)
                            this[keys[i]] = properties[keys[i]];
            }

            /**
             * Creates a new EnableMetatraceArgs instance using the specified properties.
             * @function create
             * @memberof perfetto.protos.EnableMetatraceArgs
             * @static
             * @param {perfetto.protos.IEnableMetatraceArgs=} [properties] Properties to set
             * @returns {perfetto.protos.EnableMetatraceArgs} EnableMetatraceArgs instance
             */
            EnableMetatraceArgs.create = function create(properties) {
                return new EnableMetatraceArgs(properties);
            };

            /**
             * Encodes the specified EnableMetatraceArgs message. Does not implicitly {@link perfetto.protos.EnableMetatraceArgs.verify|verify} messages.
             * @function encode
             * @memberof perfetto.protos.EnableMetatraceArgs
             * @static
             * @param {perfetto.protos.IEnableMetatraceArgs} message EnableMetatraceArgs message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            EnableMetatraceArgs.encode = function encode(message, writer) {
                if (!writer)
                    writer = $Writer.create();
                return writer;
            };

            /**
             * Encodes the specified EnableMetatraceArgs message, length delimited. Does not implicitly {@link perfetto.protos.EnableMetatraceArgs.verify|verify} messages.
             * @function encodeDelimited
             * @memberof perfetto.protos.EnableMetatraceArgs
             * @static
             * @param {perfetto.protos.IEnableMetatraceArgs} message EnableMetatraceArgs message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            EnableMetatraceArgs.encodeDelimited = function encodeDelimited(message, writer) {
                return this.encode(message, writer).ldelim();
            };

            /**
             * Decodes an EnableMetatraceArgs message from the specified reader or buffer.
             * @function decode
             * @memberof perfetto.protos.EnableMetatraceArgs
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @param {number} [length] Message length if known beforehand
             * @returns {perfetto.protos.EnableMetatraceArgs} EnableMetatraceArgs
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            EnableMetatraceArgs.decode = function decode(reader, length) {
                if (!(reader instanceof $Reader))
                    reader = $Reader.create(reader);
                var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.EnableMetatraceArgs();
                while (reader.pos < end) {
                    var tag = reader.uint32();
                    switch (tag >>> 3) {
                    default:
                        reader.skipType(tag & 7);
                        break;
                    }
                }
                return message;
            };

            /**
             * Decodes an EnableMetatraceArgs message from the specified reader or buffer, length delimited.
             * @function decodeDelimited
             * @memberof perfetto.protos.EnableMetatraceArgs
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @returns {perfetto.protos.EnableMetatraceArgs} EnableMetatraceArgs
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            EnableMetatraceArgs.decodeDelimited = function decodeDelimited(reader) {
                if (!(reader instanceof $Reader))
                    reader = new $Reader(reader);
                return this.decode(reader, reader.uint32());
            };

            /**
             * Verifies an EnableMetatraceArgs message.
             * @function verify
             * @memberof perfetto.protos.EnableMetatraceArgs
             * @static
             * @param {Object.<string,*>} message Plain object to verify
             * @returns {string|null} `null` if valid, otherwise the reason why it is not
             */
            EnableMetatraceArgs.verify = function verify(message) {
                if (typeof message !== "object" || message === null)
                    return "object expected";
                return null;
            };

            /**
             * Creates an EnableMetatraceArgs message from a plain object. Also converts values to their respective internal types.
             * @function fromObject
             * @memberof perfetto.protos.EnableMetatraceArgs
             * @static
             * @param {Object.<string,*>} object Plain object
             * @returns {perfetto.protos.EnableMetatraceArgs} EnableMetatraceArgs
             */
            EnableMetatraceArgs.fromObject = function fromObject(object) {
                if (object instanceof $root.perfetto.protos.EnableMetatraceArgs)
                    return object;
                return new $root.perfetto.protos.EnableMetatraceArgs();
            };

            /**
             * Creates a plain object from an EnableMetatraceArgs message. Also converts values to other types if specified.
             * @function toObject
             * @memberof perfetto.protos.EnableMetatraceArgs
             * @static
             * @param {perfetto.protos.EnableMetatraceArgs} message EnableMetatraceArgs
             * @param {$protobuf.IConversionOptions} [options] Conversion options
             * @returns {Object.<string,*>} Plain object
             */
            EnableMetatraceArgs.toObject = function toObject() {
                return {};
            };

            /**
             * Converts this EnableMetatraceArgs to JSON.
             * @function toJSON
             * @memberof perfetto.protos.EnableMetatraceArgs
             * @instance
             * @returns {Object.<string,*>} JSON object
             */
            EnableMetatraceArgs.prototype.toJSON = function toJSON() {
                return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
            };

            return EnableMetatraceArgs;
        })();

        protos.EnableMetatraceResult = (function() {

            /**
             * Properties of an EnableMetatraceResult.
             * @memberof perfetto.protos
             * @interface IEnableMetatraceResult
             */

            /**
             * Constructs a new EnableMetatraceResult.
             * @memberof perfetto.protos
             * @classdesc Represents an EnableMetatraceResult.
             * @implements IEnableMetatraceResult
             * @constructor
             * @param {perfetto.protos.IEnableMetatraceResult=} [properties] Properties to set
             */
            function EnableMetatraceResult(properties) {
                if (properties)
                    for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                        if (properties[keys[i]] != null)
                            this[keys[i]] = properties[keys[i]];
            }

            /**
             * Creates a new EnableMetatraceResult instance using the specified properties.
             * @function create
             * @memberof perfetto.protos.EnableMetatraceResult
             * @static
             * @param {perfetto.protos.IEnableMetatraceResult=} [properties] Properties to set
             * @returns {perfetto.protos.EnableMetatraceResult} EnableMetatraceResult instance
             */
            EnableMetatraceResult.create = function create(properties) {
                return new EnableMetatraceResult(properties);
            };

            /**
             * Encodes the specified EnableMetatraceResult message. Does not implicitly {@link perfetto.protos.EnableMetatraceResult.verify|verify} messages.
             * @function encode
             * @memberof perfetto.protos.EnableMetatraceResult
             * @static
             * @param {perfetto.protos.IEnableMetatraceResult} message EnableMetatraceResult message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            EnableMetatraceResult.encode = function encode(message, writer) {
                if (!writer)
                    writer = $Writer.create();
                return writer;
            };

            /**
             * Encodes the specified EnableMetatraceResult message, length delimited. Does not implicitly {@link perfetto.protos.EnableMetatraceResult.verify|verify} messages.
             * @function encodeDelimited
             * @memberof perfetto.protos.EnableMetatraceResult
             * @static
             * @param {perfetto.protos.IEnableMetatraceResult} message EnableMetatraceResult message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            EnableMetatraceResult.encodeDelimited = function encodeDelimited(message, writer) {
                return this.encode(message, writer).ldelim();
            };

            /**
             * Decodes an EnableMetatraceResult message from the specified reader or buffer.
             * @function decode
             * @memberof perfetto.protos.EnableMetatraceResult
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @param {number} [length] Message length if known beforehand
             * @returns {perfetto.protos.EnableMetatraceResult} EnableMetatraceResult
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            EnableMetatraceResult.decode = function decode(reader, length) {
                if (!(reader instanceof $Reader))
                    reader = $Reader.create(reader);
                var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.EnableMetatraceResult();
                while (reader.pos < end) {
                    var tag = reader.uint32();
                    switch (tag >>> 3) {
                    default:
                        reader.skipType(tag & 7);
                        break;
                    }
                }
                return message;
            };

            /**
             * Decodes an EnableMetatraceResult message from the specified reader or buffer, length delimited.
             * @function decodeDelimited
             * @memberof perfetto.protos.EnableMetatraceResult
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @returns {perfetto.protos.EnableMetatraceResult} EnableMetatraceResult
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            EnableMetatraceResult.decodeDelimited = function decodeDelimited(reader) {
                if (!(reader instanceof $Reader))
                    reader = new $Reader(reader);
                return this.decode(reader, reader.uint32());
            };

            /**
             * Verifies an EnableMetatraceResult message.
             * @function verify
             * @memberof perfetto.protos.EnableMetatraceResult
             * @static
             * @param {Object.<string,*>} message Plain object to verify
             * @returns {string|null} `null` if valid, otherwise the reason why it is not
             */
            EnableMetatraceResult.verify = function verify(message) {
                if (typeof message !== "object" || message === null)
                    return "object expected";
                return null;
            };

            /**
             * Creates an EnableMetatraceResult message from a plain object. Also converts values to their respective internal types.
             * @function fromObject
             * @memberof perfetto.protos.EnableMetatraceResult
             * @static
             * @param {Object.<string,*>} object Plain object
             * @returns {perfetto.protos.EnableMetatraceResult} EnableMetatraceResult
             */
            EnableMetatraceResult.fromObject = function fromObject(object) {
                if (object instanceof $root.perfetto.protos.EnableMetatraceResult)
                    return object;
                return new $root.perfetto.protos.EnableMetatraceResult();
            };

            /**
             * Creates a plain object from an EnableMetatraceResult message. Also converts values to other types if specified.
             * @function toObject
             * @memberof perfetto.protos.EnableMetatraceResult
             * @static
             * @param {perfetto.protos.EnableMetatraceResult} message EnableMetatraceResult
             * @param {$protobuf.IConversionOptions} [options] Conversion options
             * @returns {Object.<string,*>} Plain object
             */
            EnableMetatraceResult.toObject = function toObject() {
                return {};
            };

            /**
             * Converts this EnableMetatraceResult to JSON.
             * @function toJSON
             * @memberof perfetto.protos.EnableMetatraceResult
             * @instance
             * @returns {Object.<string,*>} JSON object
             */
            EnableMetatraceResult.prototype.toJSON = function toJSON() {
                return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
            };

            return EnableMetatraceResult;
        })();

        protos.DisableAndReadMetatraceArgs = (function() {

            /**
             * Properties of a DisableAndReadMetatraceArgs.
             * @memberof perfetto.protos
             * @interface IDisableAndReadMetatraceArgs
             */

            /**
             * Constructs a new DisableAndReadMetatraceArgs.
             * @memberof perfetto.protos
             * @classdesc Represents a DisableAndReadMetatraceArgs.
             * @implements IDisableAndReadMetatraceArgs
             * @constructor
             * @param {perfetto.protos.IDisableAndReadMetatraceArgs=} [properties] Properties to set
             */
            function DisableAndReadMetatraceArgs(properties) {
                if (properties)
                    for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                        if (properties[keys[i]] != null)
                            this[keys[i]] = properties[keys[i]];
            }

            /**
             * Creates a new DisableAndReadMetatraceArgs instance using the specified properties.
             * @function create
             * @memberof perfetto.protos.DisableAndReadMetatraceArgs
             * @static
             * @param {perfetto.protos.IDisableAndReadMetatraceArgs=} [properties] Properties to set
             * @returns {perfetto.protos.DisableAndReadMetatraceArgs} DisableAndReadMetatraceArgs instance
             */
            DisableAndReadMetatraceArgs.create = function create(properties) {
                return new DisableAndReadMetatraceArgs(properties);
            };

            /**
             * Encodes the specified DisableAndReadMetatraceArgs message. Does not implicitly {@link perfetto.protos.DisableAndReadMetatraceArgs.verify|verify} messages.
             * @function encode
             * @memberof perfetto.protos.DisableAndReadMetatraceArgs
             * @static
             * @param {perfetto.protos.IDisableAndReadMetatraceArgs} message DisableAndReadMetatraceArgs message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            DisableAndReadMetatraceArgs.encode = function encode(message, writer) {
                if (!writer)
                    writer = $Writer.create();
                return writer;
            };

            /**
             * Encodes the specified DisableAndReadMetatraceArgs message, length delimited. Does not implicitly {@link perfetto.protos.DisableAndReadMetatraceArgs.verify|verify} messages.
             * @function encodeDelimited
             * @memberof perfetto.protos.DisableAndReadMetatraceArgs
             * @static
             * @param {perfetto.protos.IDisableAndReadMetatraceArgs} message DisableAndReadMetatraceArgs message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            DisableAndReadMetatraceArgs.encodeDelimited = function encodeDelimited(message, writer) {
                return this.encode(message, writer).ldelim();
            };

            /**
             * Decodes a DisableAndReadMetatraceArgs message from the specified reader or buffer.
             * @function decode
             * @memberof perfetto.protos.DisableAndReadMetatraceArgs
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @param {number} [length] Message length if known beforehand
             * @returns {perfetto.protos.DisableAndReadMetatraceArgs} DisableAndReadMetatraceArgs
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            DisableAndReadMetatraceArgs.decode = function decode(reader, length) {
                if (!(reader instanceof $Reader))
                    reader = $Reader.create(reader);
                var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.DisableAndReadMetatraceArgs();
                while (reader.pos < end) {
                    var tag = reader.uint32();
                    switch (tag >>> 3) {
                    default:
                        reader.skipType(tag & 7);
                        break;
                    }
                }
                return message;
            };

            /**
             * Decodes a DisableAndReadMetatraceArgs message from the specified reader or buffer, length delimited.
             * @function decodeDelimited
             * @memberof perfetto.protos.DisableAndReadMetatraceArgs
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @returns {perfetto.protos.DisableAndReadMetatraceArgs} DisableAndReadMetatraceArgs
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            DisableAndReadMetatraceArgs.decodeDelimited = function decodeDelimited(reader) {
                if (!(reader instanceof $Reader))
                    reader = new $Reader(reader);
                return this.decode(reader, reader.uint32());
            };

            /**
             * Verifies a DisableAndReadMetatraceArgs message.
             * @function verify
             * @memberof perfetto.protos.DisableAndReadMetatraceArgs
             * @static
             * @param {Object.<string,*>} message Plain object to verify
             * @returns {string|null} `null` if valid, otherwise the reason why it is not
             */
            DisableAndReadMetatraceArgs.verify = function verify(message) {
                if (typeof message !== "object" || message === null)
                    return "object expected";
                return null;
            };

            /**
             * Creates a DisableAndReadMetatraceArgs message from a plain object. Also converts values to their respective internal types.
             * @function fromObject
             * @memberof perfetto.protos.DisableAndReadMetatraceArgs
             * @static
             * @param {Object.<string,*>} object Plain object
             * @returns {perfetto.protos.DisableAndReadMetatraceArgs} DisableAndReadMetatraceArgs
             */
            DisableAndReadMetatraceArgs.fromObject = function fromObject(object) {
                if (object instanceof $root.perfetto.protos.DisableAndReadMetatraceArgs)
                    return object;
                return new $root.perfetto.protos.DisableAndReadMetatraceArgs();
            };

            /**
             * Creates a plain object from a DisableAndReadMetatraceArgs message. Also converts values to other types if specified.
             * @function toObject
             * @memberof perfetto.protos.DisableAndReadMetatraceArgs
             * @static
             * @param {perfetto.protos.DisableAndReadMetatraceArgs} message DisableAndReadMetatraceArgs
             * @param {$protobuf.IConversionOptions} [options] Conversion options
             * @returns {Object.<string,*>} Plain object
             */
            DisableAndReadMetatraceArgs.toObject = function toObject() {
                return {};
            };

            /**
             * Converts this DisableAndReadMetatraceArgs to JSON.
             * @function toJSON
             * @memberof perfetto.protos.DisableAndReadMetatraceArgs
             * @instance
             * @returns {Object.<string,*>} JSON object
             */
            DisableAndReadMetatraceArgs.prototype.toJSON = function toJSON() {
                return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
            };

            return DisableAndReadMetatraceArgs;
        })();

        protos.DisableAndReadMetatraceResult = (function() {

            /**
             * Properties of a DisableAndReadMetatraceResult.
             * @memberof perfetto.protos
             * @interface IDisableAndReadMetatraceResult
             * @property {Uint8Array|null} [metatrace] DisableAndReadMetatraceResult metatrace
             * @property {string|null} [error] DisableAndReadMetatraceResult error
             */

            /**
             * Constructs a new DisableAndReadMetatraceResult.
             * @memberof perfetto.protos
             * @classdesc Represents a DisableAndReadMetatraceResult.
             * @implements IDisableAndReadMetatraceResult
             * @constructor
             * @param {perfetto.protos.IDisableAndReadMetatraceResult=} [properties] Properties to set
             */
            function DisableAndReadMetatraceResult(properties) {
                if (properties)
                    for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                        if (properties[keys[i]] != null)
                            this[keys[i]] = properties[keys[i]];
            }

            /**
             * DisableAndReadMetatraceResult metatrace.
             * @member {Uint8Array} metatrace
             * @memberof perfetto.protos.DisableAndReadMetatraceResult
             * @instance
             */
            DisableAndReadMetatraceResult.prototype.metatrace = $util.newBuffer([]);

            /**
             * DisableAndReadMetatraceResult error.
             * @member {string} error
             * @memberof perfetto.protos.DisableAndReadMetatraceResult
             * @instance
             */
            DisableAndReadMetatraceResult.prototype.error = "";

            /**
             * Creates a new DisableAndReadMetatraceResult instance using the specified properties.
             * @function create
             * @memberof perfetto.protos.DisableAndReadMetatraceResult
             * @static
             * @param {perfetto.protos.IDisableAndReadMetatraceResult=} [properties] Properties to set
             * @returns {perfetto.protos.DisableAndReadMetatraceResult} DisableAndReadMetatraceResult instance
             */
            DisableAndReadMetatraceResult.create = function create(properties) {
                return new DisableAndReadMetatraceResult(properties);
            };

            /**
             * Encodes the specified DisableAndReadMetatraceResult message. Does not implicitly {@link perfetto.protos.DisableAndReadMetatraceResult.verify|verify} messages.
             * @function encode
             * @memberof perfetto.protos.DisableAndReadMetatraceResult
             * @static
             * @param {perfetto.protos.IDisableAndReadMetatraceResult} message DisableAndReadMetatraceResult message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            DisableAndReadMetatraceResult.encode = function encode(message, writer) {
                if (!writer)
                    writer = $Writer.create();
                if (message.metatrace != null && Object.hasOwnProperty.call(message, "metatrace"))
                    writer.uint32(/* id 1, wireType 2 =*/10).bytes(message.metatrace);
                if (message.error != null && Object.hasOwnProperty.call(message, "error"))
                    writer.uint32(/* id 2, wireType 2 =*/18).string(message.error);
                return writer;
            };

            /**
             * Encodes the specified DisableAndReadMetatraceResult message, length delimited. Does not implicitly {@link perfetto.protos.DisableAndReadMetatraceResult.verify|verify} messages.
             * @function encodeDelimited
             * @memberof perfetto.protos.DisableAndReadMetatraceResult
             * @static
             * @param {perfetto.protos.IDisableAndReadMetatraceResult} message DisableAndReadMetatraceResult message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            DisableAndReadMetatraceResult.encodeDelimited = function encodeDelimited(message, writer) {
                return this.encode(message, writer).ldelim();
            };

            /**
             * Decodes a DisableAndReadMetatraceResult message from the specified reader or buffer.
             * @function decode
             * @memberof perfetto.protos.DisableAndReadMetatraceResult
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @param {number} [length] Message length if known beforehand
             * @returns {perfetto.protos.DisableAndReadMetatraceResult} DisableAndReadMetatraceResult
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            DisableAndReadMetatraceResult.decode = function decode(reader, length) {
                if (!(reader instanceof $Reader))
                    reader = $Reader.create(reader);
                var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.DisableAndReadMetatraceResult();
                while (reader.pos < end) {
                    var tag = reader.uint32();
                    switch (tag >>> 3) {
                    case 1:
                        message.metatrace = reader.bytes();
                        break;
                    case 2:
                        message.error = reader.string();
                        break;
                    default:
                        reader.skipType(tag & 7);
                        break;
                    }
                }
                return message;
            };

            /**
             * Decodes a DisableAndReadMetatraceResult message from the specified reader or buffer, length delimited.
             * @function decodeDelimited
             * @memberof perfetto.protos.DisableAndReadMetatraceResult
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @returns {perfetto.protos.DisableAndReadMetatraceResult} DisableAndReadMetatraceResult
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            DisableAndReadMetatraceResult.decodeDelimited = function decodeDelimited(reader) {
                if (!(reader instanceof $Reader))
                    reader = new $Reader(reader);
                return this.decode(reader, reader.uint32());
            };

            /**
             * Verifies a DisableAndReadMetatraceResult message.
             * @function verify
             * @memberof perfetto.protos.DisableAndReadMetatraceResult
             * @static
             * @param {Object.<string,*>} message Plain object to verify
             * @returns {string|null} `null` if valid, otherwise the reason why it is not
             */
            DisableAndReadMetatraceResult.verify = function verify(message) {
                if (typeof message !== "object" || message === null)
                    return "object expected";
                if (message.metatrace != null && message.hasOwnProperty("metatrace"))
                    if (!(message.metatrace && typeof message.metatrace.length === "number" || $util.isString(message.metatrace)))
                        return "metatrace: buffer expected";
                if (message.error != null && message.hasOwnProperty("error"))
                    if (!$util.isString(message.error))
                        return "error: string expected";
                return null;
            };

            /**
             * Creates a DisableAndReadMetatraceResult message from a plain object. Also converts values to their respective internal types.
             * @function fromObject
             * @memberof perfetto.protos.DisableAndReadMetatraceResult
             * @static
             * @param {Object.<string,*>} object Plain object
             * @returns {perfetto.protos.DisableAndReadMetatraceResult} DisableAndReadMetatraceResult
             */
            DisableAndReadMetatraceResult.fromObject = function fromObject(object) {
                if (object instanceof $root.perfetto.protos.DisableAndReadMetatraceResult)
                    return object;
                var message = new $root.perfetto.protos.DisableAndReadMetatraceResult();
                if (object.metatrace != null)
                    if (typeof object.metatrace === "string")
                        $util.base64.decode(object.metatrace, message.metatrace = $util.newBuffer($util.base64.length(object.metatrace)), 0);
                    else if (object.metatrace.length)
                        message.metatrace = object.metatrace;
                if (object.error != null)
                    message.error = String(object.error);
                return message;
            };

            /**
             * Creates a plain object from a DisableAndReadMetatraceResult message. Also converts values to other types if specified.
             * @function toObject
             * @memberof perfetto.protos.DisableAndReadMetatraceResult
             * @static
             * @param {perfetto.protos.DisableAndReadMetatraceResult} message DisableAndReadMetatraceResult
             * @param {$protobuf.IConversionOptions} [options] Conversion options
             * @returns {Object.<string,*>} Plain object
             */
            DisableAndReadMetatraceResult.toObject = function toObject(message, options) {
                if (!options)
                    options = {};
                var object = {};
                if (options.defaults) {
                    if (options.bytes === String)
                        object.metatrace = "";
                    else {
                        object.metatrace = [];
                        if (options.bytes !== Array)
                            object.metatrace = $util.newBuffer(object.metatrace);
                    }
                    object.error = "";
                }
                if (message.metatrace != null && message.hasOwnProperty("metatrace"))
                    object.metatrace = options.bytes === String ? $util.base64.encode(message.metatrace, 0, message.metatrace.length) : options.bytes === Array ? Array.prototype.slice.call(message.metatrace) : message.metatrace;
                if (message.error != null && message.hasOwnProperty("error"))
                    object.error = message.error;
                return object;
            };

            /**
             * Converts this DisableAndReadMetatraceResult to JSON.
             * @function toJSON
             * @memberof perfetto.protos.DisableAndReadMetatraceResult
             * @instance
             * @returns {Object.<string,*>} JSON object
             */
            DisableAndReadMetatraceResult.prototype.toJSON = function toJSON() {
                return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
            };

            return DisableAndReadMetatraceResult;
        })();

        protos.DescriptorSet = (function() {

            /**
             * Properties of a DescriptorSet.
             * @memberof perfetto.protos
             * @interface IDescriptorSet
             * @property {Array.<perfetto.protos.IDescriptorProto>|null} [descriptors] DescriptorSet descriptors
             */

            /**
             * Constructs a new DescriptorSet.
             * @memberof perfetto.protos
             * @classdesc Represents a DescriptorSet.
             * @implements IDescriptorSet
             * @constructor
             * @param {perfetto.protos.IDescriptorSet=} [properties] Properties to set
             */
            function DescriptorSet(properties) {
                this.descriptors = [];
                if (properties)
                    for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                        if (properties[keys[i]] != null)
                            this[keys[i]] = properties[keys[i]];
            }

            /**
             * DescriptorSet descriptors.
             * @member {Array.<perfetto.protos.IDescriptorProto>} descriptors
             * @memberof perfetto.protos.DescriptorSet
             * @instance
             */
            DescriptorSet.prototype.descriptors = $util.emptyArray;

            /**
             * Creates a new DescriptorSet instance using the specified properties.
             * @function create
             * @memberof perfetto.protos.DescriptorSet
             * @static
             * @param {perfetto.protos.IDescriptorSet=} [properties] Properties to set
             * @returns {perfetto.protos.DescriptorSet} DescriptorSet instance
             */
            DescriptorSet.create = function create(properties) {
                return new DescriptorSet(properties);
            };

            /**
             * Encodes the specified DescriptorSet message. Does not implicitly {@link perfetto.protos.DescriptorSet.verify|verify} messages.
             * @function encode
             * @memberof perfetto.protos.DescriptorSet
             * @static
             * @param {perfetto.protos.IDescriptorSet} message DescriptorSet message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            DescriptorSet.encode = function encode(message, writer) {
                if (!writer)
                    writer = $Writer.create();
                if (message.descriptors != null && message.descriptors.length)
                    for (var i = 0; i < message.descriptors.length; ++i)
                        $root.perfetto.protos.DescriptorProto.encode(message.descriptors[i], writer.uint32(/* id 1, wireType 2 =*/10).fork()).ldelim();
                return writer;
            };

            /**
             * Encodes the specified DescriptorSet message, length delimited. Does not implicitly {@link perfetto.protos.DescriptorSet.verify|verify} messages.
             * @function encodeDelimited
             * @memberof perfetto.protos.DescriptorSet
             * @static
             * @param {perfetto.protos.IDescriptorSet} message DescriptorSet message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            DescriptorSet.encodeDelimited = function encodeDelimited(message, writer) {
                return this.encode(message, writer).ldelim();
            };

            /**
             * Decodes a DescriptorSet message from the specified reader or buffer.
             * @function decode
             * @memberof perfetto.protos.DescriptorSet
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @param {number} [length] Message length if known beforehand
             * @returns {perfetto.protos.DescriptorSet} DescriptorSet
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            DescriptorSet.decode = function decode(reader, length) {
                if (!(reader instanceof $Reader))
                    reader = $Reader.create(reader);
                var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.DescriptorSet();
                while (reader.pos < end) {
                    var tag = reader.uint32();
                    switch (tag >>> 3) {
                    case 1:
                        if (!(message.descriptors && message.descriptors.length))
                            message.descriptors = [];
                        message.descriptors.push($root.perfetto.protos.DescriptorProto.decode(reader, reader.uint32()));
                        break;
                    default:
                        reader.skipType(tag & 7);
                        break;
                    }
                }
                return message;
            };

            /**
             * Decodes a DescriptorSet message from the specified reader or buffer, length delimited.
             * @function decodeDelimited
             * @memberof perfetto.protos.DescriptorSet
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @returns {perfetto.protos.DescriptorSet} DescriptorSet
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            DescriptorSet.decodeDelimited = function decodeDelimited(reader) {
                if (!(reader instanceof $Reader))
                    reader = new $Reader(reader);
                return this.decode(reader, reader.uint32());
            };

            /**
             * Verifies a DescriptorSet message.
             * @function verify
             * @memberof perfetto.protos.DescriptorSet
             * @static
             * @param {Object.<string,*>} message Plain object to verify
             * @returns {string|null} `null` if valid, otherwise the reason why it is not
             */
            DescriptorSet.verify = function verify(message) {
                if (typeof message !== "object" || message === null)
                    return "object expected";
                if (message.descriptors != null && message.hasOwnProperty("descriptors")) {
                    if (!Array.isArray(message.descriptors))
                        return "descriptors: array expected";
                    for (var i = 0; i < message.descriptors.length; ++i) {
                        var error = $root.perfetto.protos.DescriptorProto.verify(message.descriptors[i]);
                        if (error)
                            return "descriptors." + error;
                    }
                }
                return null;
            };

            /**
             * Creates a DescriptorSet message from a plain object. Also converts values to their respective internal types.
             * @function fromObject
             * @memberof perfetto.protos.DescriptorSet
             * @static
             * @param {Object.<string,*>} object Plain object
             * @returns {perfetto.protos.DescriptorSet} DescriptorSet
             */
            DescriptorSet.fromObject = function fromObject(object) {
                if (object instanceof $root.perfetto.protos.DescriptorSet)
                    return object;
                var message = new $root.perfetto.protos.DescriptorSet();
                if (object.descriptors) {
                    if (!Array.isArray(object.descriptors))
                        throw TypeError(".perfetto.protos.DescriptorSet.descriptors: array expected");
                    message.descriptors = [];
                    for (var i = 0; i < object.descriptors.length; ++i) {
                        if (typeof object.descriptors[i] !== "object")
                            throw TypeError(".perfetto.protos.DescriptorSet.descriptors: object expected");
                        message.descriptors[i] = $root.perfetto.protos.DescriptorProto.fromObject(object.descriptors[i]);
                    }
                }
                return message;
            };

            /**
             * Creates a plain object from a DescriptorSet message. Also converts values to other types if specified.
             * @function toObject
             * @memberof perfetto.protos.DescriptorSet
             * @static
             * @param {perfetto.protos.DescriptorSet} message DescriptorSet
             * @param {$protobuf.IConversionOptions} [options] Conversion options
             * @returns {Object.<string,*>} Plain object
             */
            DescriptorSet.toObject = function toObject(message, options) {
                if (!options)
                    options = {};
                var object = {};
                if (options.arrays || options.defaults)
                    object.descriptors = [];
                if (message.descriptors && message.descriptors.length) {
                    object.descriptors = [];
                    for (var j = 0; j < message.descriptors.length; ++j)
                        object.descriptors[j] = $root.perfetto.protos.DescriptorProto.toObject(message.descriptors[j], options);
                }
                return object;
            };

            /**
             * Converts this DescriptorSet to JSON.
             * @function toJSON
             * @memberof perfetto.protos.DescriptorSet
             * @instance
             * @returns {Object.<string,*>} JSON object
             */
            DescriptorSet.prototype.toJSON = function toJSON() {
                return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
            };

            return DescriptorSet;
        })();

        protos.FileDescriptorSet = (function() {

            /**
             * Properties of a FileDescriptorSet.
             * @memberof perfetto.protos
             * @interface IFileDescriptorSet
             * @property {Array.<perfetto.protos.IFileDescriptorProto>|null} [file] FileDescriptorSet file
             */

            /**
             * Constructs a new FileDescriptorSet.
             * @memberof perfetto.protos
             * @classdesc Represents a FileDescriptorSet.
             * @implements IFileDescriptorSet
             * @constructor
             * @param {perfetto.protos.IFileDescriptorSet=} [properties] Properties to set
             */
            function FileDescriptorSet(properties) {
                this.file = [];
                if (properties)
                    for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                        if (properties[keys[i]] != null)
                            this[keys[i]] = properties[keys[i]];
            }

            /**
             * FileDescriptorSet file.
             * @member {Array.<perfetto.protos.IFileDescriptorProto>} file
             * @memberof perfetto.protos.FileDescriptorSet
             * @instance
             */
            FileDescriptorSet.prototype.file = $util.emptyArray;

            /**
             * Creates a new FileDescriptorSet instance using the specified properties.
             * @function create
             * @memberof perfetto.protos.FileDescriptorSet
             * @static
             * @param {perfetto.protos.IFileDescriptorSet=} [properties] Properties to set
             * @returns {perfetto.protos.FileDescriptorSet} FileDescriptorSet instance
             */
            FileDescriptorSet.create = function create(properties) {
                return new FileDescriptorSet(properties);
            };

            /**
             * Encodes the specified FileDescriptorSet message. Does not implicitly {@link perfetto.protos.FileDescriptorSet.verify|verify} messages.
             * @function encode
             * @memberof perfetto.protos.FileDescriptorSet
             * @static
             * @param {perfetto.protos.IFileDescriptorSet} message FileDescriptorSet message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            FileDescriptorSet.encode = function encode(message, writer) {
                if (!writer)
                    writer = $Writer.create();
                if (message.file != null && message.file.length)
                    for (var i = 0; i < message.file.length; ++i)
                        $root.perfetto.protos.FileDescriptorProto.encode(message.file[i], writer.uint32(/* id 1, wireType 2 =*/10).fork()).ldelim();
                return writer;
            };

            /**
             * Encodes the specified FileDescriptorSet message, length delimited. Does not implicitly {@link perfetto.protos.FileDescriptorSet.verify|verify} messages.
             * @function encodeDelimited
             * @memberof perfetto.protos.FileDescriptorSet
             * @static
             * @param {perfetto.protos.IFileDescriptorSet} message FileDescriptorSet message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            FileDescriptorSet.encodeDelimited = function encodeDelimited(message, writer) {
                return this.encode(message, writer).ldelim();
            };

            /**
             * Decodes a FileDescriptorSet message from the specified reader or buffer.
             * @function decode
             * @memberof perfetto.protos.FileDescriptorSet
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @param {number} [length] Message length if known beforehand
             * @returns {perfetto.protos.FileDescriptorSet} FileDescriptorSet
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            FileDescriptorSet.decode = function decode(reader, length) {
                if (!(reader instanceof $Reader))
                    reader = $Reader.create(reader);
                var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.FileDescriptorSet();
                while (reader.pos < end) {
                    var tag = reader.uint32();
                    switch (tag >>> 3) {
                    case 1:
                        if (!(message.file && message.file.length))
                            message.file = [];
                        message.file.push($root.perfetto.protos.FileDescriptorProto.decode(reader, reader.uint32()));
                        break;
                    default:
                        reader.skipType(tag & 7);
                        break;
                    }
                }
                return message;
            };

            /**
             * Decodes a FileDescriptorSet message from the specified reader or buffer, length delimited.
             * @function decodeDelimited
             * @memberof perfetto.protos.FileDescriptorSet
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @returns {perfetto.protos.FileDescriptorSet} FileDescriptorSet
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            FileDescriptorSet.decodeDelimited = function decodeDelimited(reader) {
                if (!(reader instanceof $Reader))
                    reader = new $Reader(reader);
                return this.decode(reader, reader.uint32());
            };

            /**
             * Verifies a FileDescriptorSet message.
             * @function verify
             * @memberof perfetto.protos.FileDescriptorSet
             * @static
             * @param {Object.<string,*>} message Plain object to verify
             * @returns {string|null} `null` if valid, otherwise the reason why it is not
             */
            FileDescriptorSet.verify = function verify(message) {
                if (typeof message !== "object" || message === null)
                    return "object expected";
                if (message.file != null && message.hasOwnProperty("file")) {
                    if (!Array.isArray(message.file))
                        return "file: array expected";
                    for (var i = 0; i < message.file.length; ++i) {
                        var error = $root.perfetto.protos.FileDescriptorProto.verify(message.file[i]);
                        if (error)
                            return "file." + error;
                    }
                }
                return null;
            };

            /**
             * Creates a FileDescriptorSet message from a plain object. Also converts values to their respective internal types.
             * @function fromObject
             * @memberof perfetto.protos.FileDescriptorSet
             * @static
             * @param {Object.<string,*>} object Plain object
             * @returns {perfetto.protos.FileDescriptorSet} FileDescriptorSet
             */
            FileDescriptorSet.fromObject = function fromObject(object) {
                if (object instanceof $root.perfetto.protos.FileDescriptorSet)
                    return object;
                var message = new $root.perfetto.protos.FileDescriptorSet();
                if (object.file) {
                    if (!Array.isArray(object.file))
                        throw TypeError(".perfetto.protos.FileDescriptorSet.file: array expected");
                    message.file = [];
                    for (var i = 0; i < object.file.length; ++i) {
                        if (typeof object.file[i] !== "object")
                            throw TypeError(".perfetto.protos.FileDescriptorSet.file: object expected");
                        message.file[i] = $root.perfetto.protos.FileDescriptorProto.fromObject(object.file[i]);
                    }
                }
                return message;
            };

            /**
             * Creates a plain object from a FileDescriptorSet message. Also converts values to other types if specified.
             * @function toObject
             * @memberof perfetto.protos.FileDescriptorSet
             * @static
             * @param {perfetto.protos.FileDescriptorSet} message FileDescriptorSet
             * @param {$protobuf.IConversionOptions} [options] Conversion options
             * @returns {Object.<string,*>} Plain object
             */
            FileDescriptorSet.toObject = function toObject(message, options) {
                if (!options)
                    options = {};
                var object = {};
                if (options.arrays || options.defaults)
                    object.file = [];
                if (message.file && message.file.length) {
                    object.file = [];
                    for (var j = 0; j < message.file.length; ++j)
                        object.file[j] = $root.perfetto.protos.FileDescriptorProto.toObject(message.file[j], options);
                }
                return object;
            };

            /**
             * Converts this FileDescriptorSet to JSON.
             * @function toJSON
             * @memberof perfetto.protos.FileDescriptorSet
             * @instance
             * @returns {Object.<string,*>} JSON object
             */
            FileDescriptorSet.prototype.toJSON = function toJSON() {
                return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
            };

            return FileDescriptorSet;
        })();

        protos.FileDescriptorProto = (function() {

            /**
             * Properties of a FileDescriptorProto.
             * @memberof perfetto.protos
             * @interface IFileDescriptorProto
             * @property {string|null} [name] FileDescriptorProto name
             * @property {string|null} ["package"] FileDescriptorProto package
             * @property {Array.<string>|null} [dependency] FileDescriptorProto dependency
             * @property {Array.<number>|null} [publicDependency] FileDescriptorProto publicDependency
             * @property {Array.<number>|null} [weakDependency] FileDescriptorProto weakDependency
             * @property {Array.<perfetto.protos.IDescriptorProto>|null} [messageType] FileDescriptorProto messageType
             * @property {Array.<perfetto.protos.IEnumDescriptorProto>|null} [enumType] FileDescriptorProto enumType
             * @property {Array.<perfetto.protos.IFieldDescriptorProto>|null} [extension] FileDescriptorProto extension
             */

            /**
             * Constructs a new FileDescriptorProto.
             * @memberof perfetto.protos
             * @classdesc Represents a FileDescriptorProto.
             * @implements IFileDescriptorProto
             * @constructor
             * @param {perfetto.protos.IFileDescriptorProto=} [properties] Properties to set
             */
            function FileDescriptorProto(properties) {
                this.dependency = [];
                this.publicDependency = [];
                this.weakDependency = [];
                this.messageType = [];
                this.enumType = [];
                this.extension = [];
                if (properties)
                    for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                        if (properties[keys[i]] != null)
                            this[keys[i]] = properties[keys[i]];
            }

            /**
             * FileDescriptorProto name.
             * @member {string} name
             * @memberof perfetto.protos.FileDescriptorProto
             * @instance
             */
            FileDescriptorProto.prototype.name = "";

            /**
             * FileDescriptorProto package.
             * @member {string} package
             * @memberof perfetto.protos.FileDescriptorProto
             * @instance
             */
            FileDescriptorProto.prototype["package"] = "";

            /**
             * FileDescriptorProto dependency.
             * @member {Array.<string>} dependency
             * @memberof perfetto.protos.FileDescriptorProto
             * @instance
             */
            FileDescriptorProto.prototype.dependency = $util.emptyArray;

            /**
             * FileDescriptorProto publicDependency.
             * @member {Array.<number>} publicDependency
             * @memberof perfetto.protos.FileDescriptorProto
             * @instance
             */
            FileDescriptorProto.prototype.publicDependency = $util.emptyArray;

            /**
             * FileDescriptorProto weakDependency.
             * @member {Array.<number>} weakDependency
             * @memberof perfetto.protos.FileDescriptorProto
             * @instance
             */
            FileDescriptorProto.prototype.weakDependency = $util.emptyArray;

            /**
             * FileDescriptorProto messageType.
             * @member {Array.<perfetto.protos.IDescriptorProto>} messageType
             * @memberof perfetto.protos.FileDescriptorProto
             * @instance
             */
            FileDescriptorProto.prototype.messageType = $util.emptyArray;

            /**
             * FileDescriptorProto enumType.
             * @member {Array.<perfetto.protos.IEnumDescriptorProto>} enumType
             * @memberof perfetto.protos.FileDescriptorProto
             * @instance
             */
            FileDescriptorProto.prototype.enumType = $util.emptyArray;

            /**
             * FileDescriptorProto extension.
             * @member {Array.<perfetto.protos.IFieldDescriptorProto>} extension
             * @memberof perfetto.protos.FileDescriptorProto
             * @instance
             */
            FileDescriptorProto.prototype.extension = $util.emptyArray;

            /**
             * Creates a new FileDescriptorProto instance using the specified properties.
             * @function create
             * @memberof perfetto.protos.FileDescriptorProto
             * @static
             * @param {perfetto.protos.IFileDescriptorProto=} [properties] Properties to set
             * @returns {perfetto.protos.FileDescriptorProto} FileDescriptorProto instance
             */
            FileDescriptorProto.create = function create(properties) {
                return new FileDescriptorProto(properties);
            };

            /**
             * Encodes the specified FileDescriptorProto message. Does not implicitly {@link perfetto.protos.FileDescriptorProto.verify|verify} messages.
             * @function encode
             * @memberof perfetto.protos.FileDescriptorProto
             * @static
             * @param {perfetto.protos.IFileDescriptorProto} message FileDescriptorProto message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            FileDescriptorProto.encode = function encode(message, writer) {
                if (!writer)
                    writer = $Writer.create();
                if (message.name != null && Object.hasOwnProperty.call(message, "name"))
                    writer.uint32(/* id 1, wireType 2 =*/10).string(message.name);
                if (message["package"] != null && Object.hasOwnProperty.call(message, "package"))
                    writer.uint32(/* id 2, wireType 2 =*/18).string(message["package"]);
                if (message.dependency != null && message.dependency.length)
                    for (var i = 0; i < message.dependency.length; ++i)
                        writer.uint32(/* id 3, wireType 2 =*/26).string(message.dependency[i]);
                if (message.messageType != null && message.messageType.length)
                    for (var i = 0; i < message.messageType.length; ++i)
                        $root.perfetto.protos.DescriptorProto.encode(message.messageType[i], writer.uint32(/* id 4, wireType 2 =*/34).fork()).ldelim();
                if (message.enumType != null && message.enumType.length)
                    for (var i = 0; i < message.enumType.length; ++i)
                        $root.perfetto.protos.EnumDescriptorProto.encode(message.enumType[i], writer.uint32(/* id 5, wireType 2 =*/42).fork()).ldelim();
                if (message.extension != null && message.extension.length)
                    for (var i = 0; i < message.extension.length; ++i)
                        $root.perfetto.protos.FieldDescriptorProto.encode(message.extension[i], writer.uint32(/* id 7, wireType 2 =*/58).fork()).ldelim();
                if (message.publicDependency != null && message.publicDependency.length)
                    for (var i = 0; i < message.publicDependency.length; ++i)
                        writer.uint32(/* id 10, wireType 0 =*/80).int32(message.publicDependency[i]);
                if (message.weakDependency != null && message.weakDependency.length)
                    for (var i = 0; i < message.weakDependency.length; ++i)
                        writer.uint32(/* id 11, wireType 0 =*/88).int32(message.weakDependency[i]);
                return writer;
            };

            /**
             * Encodes the specified FileDescriptorProto message, length delimited. Does not implicitly {@link perfetto.protos.FileDescriptorProto.verify|verify} messages.
             * @function encodeDelimited
             * @memberof perfetto.protos.FileDescriptorProto
             * @static
             * @param {perfetto.protos.IFileDescriptorProto} message FileDescriptorProto message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            FileDescriptorProto.encodeDelimited = function encodeDelimited(message, writer) {
                return this.encode(message, writer).ldelim();
            };

            /**
             * Decodes a FileDescriptorProto message from the specified reader or buffer.
             * @function decode
             * @memberof perfetto.protos.FileDescriptorProto
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @param {number} [length] Message length if known beforehand
             * @returns {perfetto.protos.FileDescriptorProto} FileDescriptorProto
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            FileDescriptorProto.decode = function decode(reader, length) {
                if (!(reader instanceof $Reader))
                    reader = $Reader.create(reader);
                var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.FileDescriptorProto();
                while (reader.pos < end) {
                    var tag = reader.uint32();
                    switch (tag >>> 3) {
                    case 1:
                        message.name = reader.string();
                        break;
                    case 2:
                        message["package"] = reader.string();
                        break;
                    case 3:
                        if (!(message.dependency && message.dependency.length))
                            message.dependency = [];
                        message.dependency.push(reader.string());
                        break;
                    case 10:
                        if (!(message.publicDependency && message.publicDependency.length))
                            message.publicDependency = [];
                        if ((tag & 7) === 2) {
                            var end2 = reader.uint32() + reader.pos;
                            while (reader.pos < end2)
                                message.publicDependency.push(reader.int32());
                        } else
                            message.publicDependency.push(reader.int32());
                        break;
                    case 11:
                        if (!(message.weakDependency && message.weakDependency.length))
                            message.weakDependency = [];
                        if ((tag & 7) === 2) {
                            var end2 = reader.uint32() + reader.pos;
                            while (reader.pos < end2)
                                message.weakDependency.push(reader.int32());
                        } else
                            message.weakDependency.push(reader.int32());
                        break;
                    case 4:
                        if (!(message.messageType && message.messageType.length))
                            message.messageType = [];
                        message.messageType.push($root.perfetto.protos.DescriptorProto.decode(reader, reader.uint32()));
                        break;
                    case 5:
                        if (!(message.enumType && message.enumType.length))
                            message.enumType = [];
                        message.enumType.push($root.perfetto.protos.EnumDescriptorProto.decode(reader, reader.uint32()));
                        break;
                    case 7:
                        if (!(message.extension && message.extension.length))
                            message.extension = [];
                        message.extension.push($root.perfetto.protos.FieldDescriptorProto.decode(reader, reader.uint32()));
                        break;
                    default:
                        reader.skipType(tag & 7);
                        break;
                    }
                }
                return message;
            };

            /**
             * Decodes a FileDescriptorProto message from the specified reader or buffer, length delimited.
             * @function decodeDelimited
             * @memberof perfetto.protos.FileDescriptorProto
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @returns {perfetto.protos.FileDescriptorProto} FileDescriptorProto
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            FileDescriptorProto.decodeDelimited = function decodeDelimited(reader) {
                if (!(reader instanceof $Reader))
                    reader = new $Reader(reader);
                return this.decode(reader, reader.uint32());
            };

            /**
             * Verifies a FileDescriptorProto message.
             * @function verify
             * @memberof perfetto.protos.FileDescriptorProto
             * @static
             * @param {Object.<string,*>} message Plain object to verify
             * @returns {string|null} `null` if valid, otherwise the reason why it is not
             */
            FileDescriptorProto.verify = function verify(message) {
                if (typeof message !== "object" || message === null)
                    return "object expected";
                if (message.name != null && message.hasOwnProperty("name"))
                    if (!$util.isString(message.name))
                        return "name: string expected";
                if (message["package"] != null && message.hasOwnProperty("package"))
                    if (!$util.isString(message["package"]))
                        return "package: string expected";
                if (message.dependency != null && message.hasOwnProperty("dependency")) {
                    if (!Array.isArray(message.dependency))
                        return "dependency: array expected";
                    for (var i = 0; i < message.dependency.length; ++i)
                        if (!$util.isString(message.dependency[i]))
                            return "dependency: string[] expected";
                }
                if (message.publicDependency != null && message.hasOwnProperty("publicDependency")) {
                    if (!Array.isArray(message.publicDependency))
                        return "publicDependency: array expected";
                    for (var i = 0; i < message.publicDependency.length; ++i)
                        if (!$util.isInteger(message.publicDependency[i]))
                            return "publicDependency: integer[] expected";
                }
                if (message.weakDependency != null && message.hasOwnProperty("weakDependency")) {
                    if (!Array.isArray(message.weakDependency))
                        return "weakDependency: array expected";
                    for (var i = 0; i < message.weakDependency.length; ++i)
                        if (!$util.isInteger(message.weakDependency[i]))
                            return "weakDependency: integer[] expected";
                }
                if (message.messageType != null && message.hasOwnProperty("messageType")) {
                    if (!Array.isArray(message.messageType))
                        return "messageType: array expected";
                    for (var i = 0; i < message.messageType.length; ++i) {
                        var error = $root.perfetto.protos.DescriptorProto.verify(message.messageType[i]);
                        if (error)
                            return "messageType." + error;
                    }
                }
                if (message.enumType != null && message.hasOwnProperty("enumType")) {
                    if (!Array.isArray(message.enumType))
                        return "enumType: array expected";
                    for (var i = 0; i < message.enumType.length; ++i) {
                        var error = $root.perfetto.protos.EnumDescriptorProto.verify(message.enumType[i]);
                        if (error)
                            return "enumType." + error;
                    }
                }
                if (message.extension != null && message.hasOwnProperty("extension")) {
                    if (!Array.isArray(message.extension))
                        return "extension: array expected";
                    for (var i = 0; i < message.extension.length; ++i) {
                        var error = $root.perfetto.protos.FieldDescriptorProto.verify(message.extension[i]);
                        if (error)
                            return "extension." + error;
                    }
                }
                return null;
            };

            /**
             * Creates a FileDescriptorProto message from a plain object. Also converts values to their respective internal types.
             * @function fromObject
             * @memberof perfetto.protos.FileDescriptorProto
             * @static
             * @param {Object.<string,*>} object Plain object
             * @returns {perfetto.protos.FileDescriptorProto} FileDescriptorProto
             */
            FileDescriptorProto.fromObject = function fromObject(object) {
                if (object instanceof $root.perfetto.protos.FileDescriptorProto)
                    return object;
                var message = new $root.perfetto.protos.FileDescriptorProto();
                if (object.name != null)
                    message.name = String(object.name);
                if (object["package"] != null)
                    message["package"] = String(object["package"]);
                if (object.dependency) {
                    if (!Array.isArray(object.dependency))
                        throw TypeError(".perfetto.protos.FileDescriptorProto.dependency: array expected");
                    message.dependency = [];
                    for (var i = 0; i < object.dependency.length; ++i)
                        message.dependency[i] = String(object.dependency[i]);
                }
                if (object.publicDependency) {
                    if (!Array.isArray(object.publicDependency))
                        throw TypeError(".perfetto.protos.FileDescriptorProto.publicDependency: array expected");
                    message.publicDependency = [];
                    for (var i = 0; i < object.publicDependency.length; ++i)
                        message.publicDependency[i] = object.publicDependency[i] | 0;
                }
                if (object.weakDependency) {
                    if (!Array.isArray(object.weakDependency))
                        throw TypeError(".perfetto.protos.FileDescriptorProto.weakDependency: array expected");
                    message.weakDependency = [];
                    for (var i = 0; i < object.weakDependency.length; ++i)
                        message.weakDependency[i] = object.weakDependency[i] | 0;
                }
                if (object.messageType) {
                    if (!Array.isArray(object.messageType))
                        throw TypeError(".perfetto.protos.FileDescriptorProto.messageType: array expected");
                    message.messageType = [];
                    for (var i = 0; i < object.messageType.length; ++i) {
                        if (typeof object.messageType[i] !== "object")
                            throw TypeError(".perfetto.protos.FileDescriptorProto.messageType: object expected");
                        message.messageType[i] = $root.perfetto.protos.DescriptorProto.fromObject(object.messageType[i]);
                    }
                }
                if (object.enumType) {
                    if (!Array.isArray(object.enumType))
                        throw TypeError(".perfetto.protos.FileDescriptorProto.enumType: array expected");
                    message.enumType = [];
                    for (var i = 0; i < object.enumType.length; ++i) {
                        if (typeof object.enumType[i] !== "object")
                            throw TypeError(".perfetto.protos.FileDescriptorProto.enumType: object expected");
                        message.enumType[i] = $root.perfetto.protos.EnumDescriptorProto.fromObject(object.enumType[i]);
                    }
                }
                if (object.extension) {
                    if (!Array.isArray(object.extension))
                        throw TypeError(".perfetto.protos.FileDescriptorProto.extension: array expected");
                    message.extension = [];
                    for (var i = 0; i < object.extension.length; ++i) {
                        if (typeof object.extension[i] !== "object")
                            throw TypeError(".perfetto.protos.FileDescriptorProto.extension: object expected");
                        message.extension[i] = $root.perfetto.protos.FieldDescriptorProto.fromObject(object.extension[i]);
                    }
                }
                return message;
            };

            /**
             * Creates a plain object from a FileDescriptorProto message. Also converts values to other types if specified.
             * @function toObject
             * @memberof perfetto.protos.FileDescriptorProto
             * @static
             * @param {perfetto.protos.FileDescriptorProto} message FileDescriptorProto
             * @param {$protobuf.IConversionOptions} [options] Conversion options
             * @returns {Object.<string,*>} Plain object
             */
            FileDescriptorProto.toObject = function toObject(message, options) {
                if (!options)
                    options = {};
                var object = {};
                if (options.arrays || options.defaults) {
                    object.dependency = [];
                    object.messageType = [];
                    object.enumType = [];
                    object.extension = [];
                    object.publicDependency = [];
                    object.weakDependency = [];
                }
                if (options.defaults) {
                    object.name = "";
                    object["package"] = "";
                }
                if (message.name != null && message.hasOwnProperty("name"))
                    object.name = message.name;
                if (message["package"] != null && message.hasOwnProperty("package"))
                    object["package"] = message["package"];
                if (message.dependency && message.dependency.length) {
                    object.dependency = [];
                    for (var j = 0; j < message.dependency.length; ++j)
                        object.dependency[j] = message.dependency[j];
                }
                if (message.messageType && message.messageType.length) {
                    object.messageType = [];
                    for (var j = 0; j < message.messageType.length; ++j)
                        object.messageType[j] = $root.perfetto.protos.DescriptorProto.toObject(message.messageType[j], options);
                }
                if (message.enumType && message.enumType.length) {
                    object.enumType = [];
                    for (var j = 0; j < message.enumType.length; ++j)
                        object.enumType[j] = $root.perfetto.protos.EnumDescriptorProto.toObject(message.enumType[j], options);
                }
                if (message.extension && message.extension.length) {
                    object.extension = [];
                    for (var j = 0; j < message.extension.length; ++j)
                        object.extension[j] = $root.perfetto.protos.FieldDescriptorProto.toObject(message.extension[j], options);
                }
                if (message.publicDependency && message.publicDependency.length) {
                    object.publicDependency = [];
                    for (var j = 0; j < message.publicDependency.length; ++j)
                        object.publicDependency[j] = message.publicDependency[j];
                }
                if (message.weakDependency && message.weakDependency.length) {
                    object.weakDependency = [];
                    for (var j = 0; j < message.weakDependency.length; ++j)
                        object.weakDependency[j] = message.weakDependency[j];
                }
                return object;
            };

            /**
             * Converts this FileDescriptorProto to JSON.
             * @function toJSON
             * @memberof perfetto.protos.FileDescriptorProto
             * @instance
             * @returns {Object.<string,*>} JSON object
             */
            FileDescriptorProto.prototype.toJSON = function toJSON() {
                return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
            };

            return FileDescriptorProto;
        })();

        protos.DescriptorProto = (function() {

            /**
             * Properties of a DescriptorProto.
             * @memberof perfetto.protos
             * @interface IDescriptorProto
             * @property {string|null} [name] DescriptorProto name
             * @property {Array.<perfetto.protos.IFieldDescriptorProto>|null} [field] DescriptorProto field
             * @property {Array.<perfetto.protos.IFieldDescriptorProto>|null} [extension] DescriptorProto extension
             * @property {Array.<perfetto.protos.IDescriptorProto>|null} [nestedType] DescriptorProto nestedType
             * @property {Array.<perfetto.protos.IEnumDescriptorProto>|null} [enumType] DescriptorProto enumType
             * @property {Array.<perfetto.protos.IOneofDescriptorProto>|null} [oneofDecl] DescriptorProto oneofDecl
             * @property {Array.<perfetto.protos.DescriptorProto.IReservedRange>|null} [reservedRange] DescriptorProto reservedRange
             * @property {Array.<string>|null} [reservedName] DescriptorProto reservedName
             */

            /**
             * Constructs a new DescriptorProto.
             * @memberof perfetto.protos
             * @classdesc Represents a DescriptorProto.
             * @implements IDescriptorProto
             * @constructor
             * @param {perfetto.protos.IDescriptorProto=} [properties] Properties to set
             */
            function DescriptorProto(properties) {
                this.field = [];
                this.extension = [];
                this.nestedType = [];
                this.enumType = [];
                this.oneofDecl = [];
                this.reservedRange = [];
                this.reservedName = [];
                if (properties)
                    for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                        if (properties[keys[i]] != null)
                            this[keys[i]] = properties[keys[i]];
            }

            /**
             * DescriptorProto name.
             * @member {string} name
             * @memberof perfetto.protos.DescriptorProto
             * @instance
             */
            DescriptorProto.prototype.name = "";

            /**
             * DescriptorProto field.
             * @member {Array.<perfetto.protos.IFieldDescriptorProto>} field
             * @memberof perfetto.protos.DescriptorProto
             * @instance
             */
            DescriptorProto.prototype.field = $util.emptyArray;

            /**
             * DescriptorProto extension.
             * @member {Array.<perfetto.protos.IFieldDescriptorProto>} extension
             * @memberof perfetto.protos.DescriptorProto
             * @instance
             */
            DescriptorProto.prototype.extension = $util.emptyArray;

            /**
             * DescriptorProto nestedType.
             * @member {Array.<perfetto.protos.IDescriptorProto>} nestedType
             * @memberof perfetto.protos.DescriptorProto
             * @instance
             */
            DescriptorProto.prototype.nestedType = $util.emptyArray;

            /**
             * DescriptorProto enumType.
             * @member {Array.<perfetto.protos.IEnumDescriptorProto>} enumType
             * @memberof perfetto.protos.DescriptorProto
             * @instance
             */
            DescriptorProto.prototype.enumType = $util.emptyArray;

            /**
             * DescriptorProto oneofDecl.
             * @member {Array.<perfetto.protos.IOneofDescriptorProto>} oneofDecl
             * @memberof perfetto.protos.DescriptorProto
             * @instance
             */
            DescriptorProto.prototype.oneofDecl = $util.emptyArray;

            /**
             * DescriptorProto reservedRange.
             * @member {Array.<perfetto.protos.DescriptorProto.IReservedRange>} reservedRange
             * @memberof perfetto.protos.DescriptorProto
             * @instance
             */
            DescriptorProto.prototype.reservedRange = $util.emptyArray;

            /**
             * DescriptorProto reservedName.
             * @member {Array.<string>} reservedName
             * @memberof perfetto.protos.DescriptorProto
             * @instance
             */
            DescriptorProto.prototype.reservedName = $util.emptyArray;

            /**
             * Creates a new DescriptorProto instance using the specified properties.
             * @function create
             * @memberof perfetto.protos.DescriptorProto
             * @static
             * @param {perfetto.protos.IDescriptorProto=} [properties] Properties to set
             * @returns {perfetto.protos.DescriptorProto} DescriptorProto instance
             */
            DescriptorProto.create = function create(properties) {
                return new DescriptorProto(properties);
            };

            /**
             * Encodes the specified DescriptorProto message. Does not implicitly {@link perfetto.protos.DescriptorProto.verify|verify} messages.
             * @function encode
             * @memberof perfetto.protos.DescriptorProto
             * @static
             * @param {perfetto.protos.IDescriptorProto} message DescriptorProto message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            DescriptorProto.encode = function encode(message, writer) {
                if (!writer)
                    writer = $Writer.create();
                if (message.name != null && Object.hasOwnProperty.call(message, "name"))
                    writer.uint32(/* id 1, wireType 2 =*/10).string(message.name);
                if (message.field != null && message.field.length)
                    for (var i = 0; i < message.field.length; ++i)
                        $root.perfetto.protos.FieldDescriptorProto.encode(message.field[i], writer.uint32(/* id 2, wireType 2 =*/18).fork()).ldelim();
                if (message.nestedType != null && message.nestedType.length)
                    for (var i = 0; i < message.nestedType.length; ++i)
                        $root.perfetto.protos.DescriptorProto.encode(message.nestedType[i], writer.uint32(/* id 3, wireType 2 =*/26).fork()).ldelim();
                if (message.enumType != null && message.enumType.length)
                    for (var i = 0; i < message.enumType.length; ++i)
                        $root.perfetto.protos.EnumDescriptorProto.encode(message.enumType[i], writer.uint32(/* id 4, wireType 2 =*/34).fork()).ldelim();
                if (message.extension != null && message.extension.length)
                    for (var i = 0; i < message.extension.length; ++i)
                        $root.perfetto.protos.FieldDescriptorProto.encode(message.extension[i], writer.uint32(/* id 6, wireType 2 =*/50).fork()).ldelim();
                if (message.oneofDecl != null && message.oneofDecl.length)
                    for (var i = 0; i < message.oneofDecl.length; ++i)
                        $root.perfetto.protos.OneofDescriptorProto.encode(message.oneofDecl[i], writer.uint32(/* id 8, wireType 2 =*/66).fork()).ldelim();
                if (message.reservedRange != null && message.reservedRange.length)
                    for (var i = 0; i < message.reservedRange.length; ++i)
                        $root.perfetto.protos.DescriptorProto.ReservedRange.encode(message.reservedRange[i], writer.uint32(/* id 9, wireType 2 =*/74).fork()).ldelim();
                if (message.reservedName != null && message.reservedName.length)
                    for (var i = 0; i < message.reservedName.length; ++i)
                        writer.uint32(/* id 10, wireType 2 =*/82).string(message.reservedName[i]);
                return writer;
            };

            /**
             * Encodes the specified DescriptorProto message, length delimited. Does not implicitly {@link perfetto.protos.DescriptorProto.verify|verify} messages.
             * @function encodeDelimited
             * @memberof perfetto.protos.DescriptorProto
             * @static
             * @param {perfetto.protos.IDescriptorProto} message DescriptorProto message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            DescriptorProto.encodeDelimited = function encodeDelimited(message, writer) {
                return this.encode(message, writer).ldelim();
            };

            /**
             * Decodes a DescriptorProto message from the specified reader or buffer.
             * @function decode
             * @memberof perfetto.protos.DescriptorProto
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @param {number} [length] Message length if known beforehand
             * @returns {perfetto.protos.DescriptorProto} DescriptorProto
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            DescriptorProto.decode = function decode(reader, length) {
                if (!(reader instanceof $Reader))
                    reader = $Reader.create(reader);
                var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.DescriptorProto();
                while (reader.pos < end) {
                    var tag = reader.uint32();
                    switch (tag >>> 3) {
                    case 1:
                        message.name = reader.string();
                        break;
                    case 2:
                        if (!(message.field && message.field.length))
                            message.field = [];
                        message.field.push($root.perfetto.protos.FieldDescriptorProto.decode(reader, reader.uint32()));
                        break;
                    case 6:
                        if (!(message.extension && message.extension.length))
                            message.extension = [];
                        message.extension.push($root.perfetto.protos.FieldDescriptorProto.decode(reader, reader.uint32()));
                        break;
                    case 3:
                        if (!(message.nestedType && message.nestedType.length))
                            message.nestedType = [];
                        message.nestedType.push($root.perfetto.protos.DescriptorProto.decode(reader, reader.uint32()));
                        break;
                    case 4:
                        if (!(message.enumType && message.enumType.length))
                            message.enumType = [];
                        message.enumType.push($root.perfetto.protos.EnumDescriptorProto.decode(reader, reader.uint32()));
                        break;
                    case 8:
                        if (!(message.oneofDecl && message.oneofDecl.length))
                            message.oneofDecl = [];
                        message.oneofDecl.push($root.perfetto.protos.OneofDescriptorProto.decode(reader, reader.uint32()));
                        break;
                    case 9:
                        if (!(message.reservedRange && message.reservedRange.length))
                            message.reservedRange = [];
                        message.reservedRange.push($root.perfetto.protos.DescriptorProto.ReservedRange.decode(reader, reader.uint32()));
                        break;
                    case 10:
                        if (!(message.reservedName && message.reservedName.length))
                            message.reservedName = [];
                        message.reservedName.push(reader.string());
                        break;
                    default:
                        reader.skipType(tag & 7);
                        break;
                    }
                }
                return message;
            };

            /**
             * Decodes a DescriptorProto message from the specified reader or buffer, length delimited.
             * @function decodeDelimited
             * @memberof perfetto.protos.DescriptorProto
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @returns {perfetto.protos.DescriptorProto} DescriptorProto
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            DescriptorProto.decodeDelimited = function decodeDelimited(reader) {
                if (!(reader instanceof $Reader))
                    reader = new $Reader(reader);
                return this.decode(reader, reader.uint32());
            };

            /**
             * Verifies a DescriptorProto message.
             * @function verify
             * @memberof perfetto.protos.DescriptorProto
             * @static
             * @param {Object.<string,*>} message Plain object to verify
             * @returns {string|null} `null` if valid, otherwise the reason why it is not
             */
            DescriptorProto.verify = function verify(message) {
                if (typeof message !== "object" || message === null)
                    return "object expected";
                if (message.name != null && message.hasOwnProperty("name"))
                    if (!$util.isString(message.name))
                        return "name: string expected";
                if (message.field != null && message.hasOwnProperty("field")) {
                    if (!Array.isArray(message.field))
                        return "field: array expected";
                    for (var i = 0; i < message.field.length; ++i) {
                        var error = $root.perfetto.protos.FieldDescriptorProto.verify(message.field[i]);
                        if (error)
                            return "field." + error;
                    }
                }
                if (message.extension != null && message.hasOwnProperty("extension")) {
                    if (!Array.isArray(message.extension))
                        return "extension: array expected";
                    for (var i = 0; i < message.extension.length; ++i) {
                        var error = $root.perfetto.protos.FieldDescriptorProto.verify(message.extension[i]);
                        if (error)
                            return "extension." + error;
                    }
                }
                if (message.nestedType != null && message.hasOwnProperty("nestedType")) {
                    if (!Array.isArray(message.nestedType))
                        return "nestedType: array expected";
                    for (var i = 0; i < message.nestedType.length; ++i) {
                        var error = $root.perfetto.protos.DescriptorProto.verify(message.nestedType[i]);
                        if (error)
                            return "nestedType." + error;
                    }
                }
                if (message.enumType != null && message.hasOwnProperty("enumType")) {
                    if (!Array.isArray(message.enumType))
                        return "enumType: array expected";
                    for (var i = 0; i < message.enumType.length; ++i) {
                        var error = $root.perfetto.protos.EnumDescriptorProto.verify(message.enumType[i]);
                        if (error)
                            return "enumType." + error;
                    }
                }
                if (message.oneofDecl != null && message.hasOwnProperty("oneofDecl")) {
                    if (!Array.isArray(message.oneofDecl))
                        return "oneofDecl: array expected";
                    for (var i = 0; i < message.oneofDecl.length; ++i) {
                        var error = $root.perfetto.protos.OneofDescriptorProto.verify(message.oneofDecl[i]);
                        if (error)
                            return "oneofDecl." + error;
                    }
                }
                if (message.reservedRange != null && message.hasOwnProperty("reservedRange")) {
                    if (!Array.isArray(message.reservedRange))
                        return "reservedRange: array expected";
                    for (var i = 0; i < message.reservedRange.length; ++i) {
                        var error = $root.perfetto.protos.DescriptorProto.ReservedRange.verify(message.reservedRange[i]);
                        if (error)
                            return "reservedRange." + error;
                    }
                }
                if (message.reservedName != null && message.hasOwnProperty("reservedName")) {
                    if (!Array.isArray(message.reservedName))
                        return "reservedName: array expected";
                    for (var i = 0; i < message.reservedName.length; ++i)
                        if (!$util.isString(message.reservedName[i]))
                            return "reservedName: string[] expected";
                }
                return null;
            };

            /**
             * Creates a DescriptorProto message from a plain object. Also converts values to their respective internal types.
             * @function fromObject
             * @memberof perfetto.protos.DescriptorProto
             * @static
             * @param {Object.<string,*>} object Plain object
             * @returns {perfetto.protos.DescriptorProto} DescriptorProto
             */
            DescriptorProto.fromObject = function fromObject(object) {
                if (object instanceof $root.perfetto.protos.DescriptorProto)
                    return object;
                var message = new $root.perfetto.protos.DescriptorProto();
                if (object.name != null)
                    message.name = String(object.name);
                if (object.field) {
                    if (!Array.isArray(object.field))
                        throw TypeError(".perfetto.protos.DescriptorProto.field: array expected");
                    message.field = [];
                    for (var i = 0; i < object.field.length; ++i) {
                        if (typeof object.field[i] !== "object")
                            throw TypeError(".perfetto.protos.DescriptorProto.field: object expected");
                        message.field[i] = $root.perfetto.protos.FieldDescriptorProto.fromObject(object.field[i]);
                    }
                }
                if (object.extension) {
                    if (!Array.isArray(object.extension))
                        throw TypeError(".perfetto.protos.DescriptorProto.extension: array expected");
                    message.extension = [];
                    for (var i = 0; i < object.extension.length; ++i) {
                        if (typeof object.extension[i] !== "object")
                            throw TypeError(".perfetto.protos.DescriptorProto.extension: object expected");
                        message.extension[i] = $root.perfetto.protos.FieldDescriptorProto.fromObject(object.extension[i]);
                    }
                }
                if (object.nestedType) {
                    if (!Array.isArray(object.nestedType))
                        throw TypeError(".perfetto.protos.DescriptorProto.nestedType: array expected");
                    message.nestedType = [];
                    for (var i = 0; i < object.nestedType.length; ++i) {
                        if (typeof object.nestedType[i] !== "object")
                            throw TypeError(".perfetto.protos.DescriptorProto.nestedType: object expected");
                        message.nestedType[i] = $root.perfetto.protos.DescriptorProto.fromObject(object.nestedType[i]);
                    }
                }
                if (object.enumType) {
                    if (!Array.isArray(object.enumType))
                        throw TypeError(".perfetto.protos.DescriptorProto.enumType: array expected");
                    message.enumType = [];
                    for (var i = 0; i < object.enumType.length; ++i) {
                        if (typeof object.enumType[i] !== "object")
                            throw TypeError(".perfetto.protos.DescriptorProto.enumType: object expected");
                        message.enumType[i] = $root.perfetto.protos.EnumDescriptorProto.fromObject(object.enumType[i]);
                    }
                }
                if (object.oneofDecl) {
                    if (!Array.isArray(object.oneofDecl))
                        throw TypeError(".perfetto.protos.DescriptorProto.oneofDecl: array expected");
                    message.oneofDecl = [];
                    for (var i = 0; i < object.oneofDecl.length; ++i) {
                        if (typeof object.oneofDecl[i] !== "object")
                            throw TypeError(".perfetto.protos.DescriptorProto.oneofDecl: object expected");
                        message.oneofDecl[i] = $root.perfetto.protos.OneofDescriptorProto.fromObject(object.oneofDecl[i]);
                    }
                }
                if (object.reservedRange) {
                    if (!Array.isArray(object.reservedRange))
                        throw TypeError(".perfetto.protos.DescriptorProto.reservedRange: array expected");
                    message.reservedRange = [];
                    for (var i = 0; i < object.reservedRange.length; ++i) {
                        if (typeof object.reservedRange[i] !== "object")
                            throw TypeError(".perfetto.protos.DescriptorProto.reservedRange: object expected");
                        message.reservedRange[i] = $root.perfetto.protos.DescriptorProto.ReservedRange.fromObject(object.reservedRange[i]);
                    }
                }
                if (object.reservedName) {
                    if (!Array.isArray(object.reservedName))
                        throw TypeError(".perfetto.protos.DescriptorProto.reservedName: array expected");
                    message.reservedName = [];
                    for (var i = 0; i < object.reservedName.length; ++i)
                        message.reservedName[i] = String(object.reservedName[i]);
                }
                return message;
            };

            /**
             * Creates a plain object from a DescriptorProto message. Also converts values to other types if specified.
             * @function toObject
             * @memberof perfetto.protos.DescriptorProto
             * @static
             * @param {perfetto.protos.DescriptorProto} message DescriptorProto
             * @param {$protobuf.IConversionOptions} [options] Conversion options
             * @returns {Object.<string,*>} Plain object
             */
            DescriptorProto.toObject = function toObject(message, options) {
                if (!options)
                    options = {};
                var object = {};
                if (options.arrays || options.defaults) {
                    object.field = [];
                    object.nestedType = [];
                    object.enumType = [];
                    object.extension = [];
                    object.oneofDecl = [];
                    object.reservedRange = [];
                    object.reservedName = [];
                }
                if (options.defaults)
                    object.name = "";
                if (message.name != null && message.hasOwnProperty("name"))
                    object.name = message.name;
                if (message.field && message.field.length) {
                    object.field = [];
                    for (var j = 0; j < message.field.length; ++j)
                        object.field[j] = $root.perfetto.protos.FieldDescriptorProto.toObject(message.field[j], options);
                }
                if (message.nestedType && message.nestedType.length) {
                    object.nestedType = [];
                    for (var j = 0; j < message.nestedType.length; ++j)
                        object.nestedType[j] = $root.perfetto.protos.DescriptorProto.toObject(message.nestedType[j], options);
                }
                if (message.enumType && message.enumType.length) {
                    object.enumType = [];
                    for (var j = 0; j < message.enumType.length; ++j)
                        object.enumType[j] = $root.perfetto.protos.EnumDescriptorProto.toObject(message.enumType[j], options);
                }
                if (message.extension && message.extension.length) {
                    object.extension = [];
                    for (var j = 0; j < message.extension.length; ++j)
                        object.extension[j] = $root.perfetto.protos.FieldDescriptorProto.toObject(message.extension[j], options);
                }
                if (message.oneofDecl && message.oneofDecl.length) {
                    object.oneofDecl = [];
                    for (var j = 0; j < message.oneofDecl.length; ++j)
                        object.oneofDecl[j] = $root.perfetto.protos.OneofDescriptorProto.toObject(message.oneofDecl[j], options);
                }
                if (message.reservedRange && message.reservedRange.length) {
                    object.reservedRange = [];
                    for (var j = 0; j < message.reservedRange.length; ++j)
                        object.reservedRange[j] = $root.perfetto.protos.DescriptorProto.ReservedRange.toObject(message.reservedRange[j], options);
                }
                if (message.reservedName && message.reservedName.length) {
                    object.reservedName = [];
                    for (var j = 0; j < message.reservedName.length; ++j)
                        object.reservedName[j] = message.reservedName[j];
                }
                return object;
            };

            /**
             * Converts this DescriptorProto to JSON.
             * @function toJSON
             * @memberof perfetto.protos.DescriptorProto
             * @instance
             * @returns {Object.<string,*>} JSON object
             */
            DescriptorProto.prototype.toJSON = function toJSON() {
                return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
            };

            DescriptorProto.ReservedRange = (function() {

                /**
                 * Properties of a ReservedRange.
                 * @memberof perfetto.protos.DescriptorProto
                 * @interface IReservedRange
                 * @property {number|null} [start] ReservedRange start
                 * @property {number|null} [end] ReservedRange end
                 */

                /**
                 * Constructs a new ReservedRange.
                 * @memberof perfetto.protos.DescriptorProto
                 * @classdesc Represents a ReservedRange.
                 * @implements IReservedRange
                 * @constructor
                 * @param {perfetto.protos.DescriptorProto.IReservedRange=} [properties] Properties to set
                 */
                function ReservedRange(properties) {
                    if (properties)
                        for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                            if (properties[keys[i]] != null)
                                this[keys[i]] = properties[keys[i]];
                }

                /**
                 * ReservedRange start.
                 * @member {number} start
                 * @memberof perfetto.protos.DescriptorProto.ReservedRange
                 * @instance
                 */
                ReservedRange.prototype.start = 0;

                /**
                 * ReservedRange end.
                 * @member {number} end
                 * @memberof perfetto.protos.DescriptorProto.ReservedRange
                 * @instance
                 */
                ReservedRange.prototype.end = 0;

                /**
                 * Creates a new ReservedRange instance using the specified properties.
                 * @function create
                 * @memberof perfetto.protos.DescriptorProto.ReservedRange
                 * @static
                 * @param {perfetto.protos.DescriptorProto.IReservedRange=} [properties] Properties to set
                 * @returns {perfetto.protos.DescriptorProto.ReservedRange} ReservedRange instance
                 */
                ReservedRange.create = function create(properties) {
                    return new ReservedRange(properties);
                };

                /**
                 * Encodes the specified ReservedRange message. Does not implicitly {@link perfetto.protos.DescriptorProto.ReservedRange.verify|verify} messages.
                 * @function encode
                 * @memberof perfetto.protos.DescriptorProto.ReservedRange
                 * @static
                 * @param {perfetto.protos.DescriptorProto.IReservedRange} message ReservedRange message or plain object to encode
                 * @param {$protobuf.Writer} [writer] Writer to encode to
                 * @returns {$protobuf.Writer} Writer
                 */
                ReservedRange.encode = function encode(message, writer) {
                    if (!writer)
                        writer = $Writer.create();
                    if (message.start != null && Object.hasOwnProperty.call(message, "start"))
                        writer.uint32(/* id 1, wireType 0 =*/8).int32(message.start);
                    if (message.end != null && Object.hasOwnProperty.call(message, "end"))
                        writer.uint32(/* id 2, wireType 0 =*/16).int32(message.end);
                    return writer;
                };

                /**
                 * Encodes the specified ReservedRange message, length delimited. Does not implicitly {@link perfetto.protos.DescriptorProto.ReservedRange.verify|verify} messages.
                 * @function encodeDelimited
                 * @memberof perfetto.protos.DescriptorProto.ReservedRange
                 * @static
                 * @param {perfetto.protos.DescriptorProto.IReservedRange} message ReservedRange message or plain object to encode
                 * @param {$protobuf.Writer} [writer] Writer to encode to
                 * @returns {$protobuf.Writer} Writer
                 */
                ReservedRange.encodeDelimited = function encodeDelimited(message, writer) {
                    return this.encode(message, writer).ldelim();
                };

                /**
                 * Decodes a ReservedRange message from the specified reader or buffer.
                 * @function decode
                 * @memberof perfetto.protos.DescriptorProto.ReservedRange
                 * @static
                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                 * @param {number} [length] Message length if known beforehand
                 * @returns {perfetto.protos.DescriptorProto.ReservedRange} ReservedRange
                 * @throws {Error} If the payload is not a reader or valid buffer
                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
                 */
                ReservedRange.decode = function decode(reader, length) {
                    if (!(reader instanceof $Reader))
                        reader = $Reader.create(reader);
                    var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.DescriptorProto.ReservedRange();
                    while (reader.pos < end) {
                        var tag = reader.uint32();
                        switch (tag >>> 3) {
                        case 1:
                            message.start = reader.int32();
                            break;
                        case 2:
                            message.end = reader.int32();
                            break;
                        default:
                            reader.skipType(tag & 7);
                            break;
                        }
                    }
                    return message;
                };

                /**
                 * Decodes a ReservedRange message from the specified reader or buffer, length delimited.
                 * @function decodeDelimited
                 * @memberof perfetto.protos.DescriptorProto.ReservedRange
                 * @static
                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                 * @returns {perfetto.protos.DescriptorProto.ReservedRange} ReservedRange
                 * @throws {Error} If the payload is not a reader or valid buffer
                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
                 */
                ReservedRange.decodeDelimited = function decodeDelimited(reader) {
                    if (!(reader instanceof $Reader))
                        reader = new $Reader(reader);
                    return this.decode(reader, reader.uint32());
                };

                /**
                 * Verifies a ReservedRange message.
                 * @function verify
                 * @memberof perfetto.protos.DescriptorProto.ReservedRange
                 * @static
                 * @param {Object.<string,*>} message Plain object to verify
                 * @returns {string|null} `null` if valid, otherwise the reason why it is not
                 */
                ReservedRange.verify = function verify(message) {
                    if (typeof message !== "object" || message === null)
                        return "object expected";
                    if (message.start != null && message.hasOwnProperty("start"))
                        if (!$util.isInteger(message.start))
                            return "start: integer expected";
                    if (message.end != null && message.hasOwnProperty("end"))
                        if (!$util.isInteger(message.end))
                            return "end: integer expected";
                    return null;
                };

                /**
                 * Creates a ReservedRange message from a plain object. Also converts values to their respective internal types.
                 * @function fromObject
                 * @memberof perfetto.protos.DescriptorProto.ReservedRange
                 * @static
                 * @param {Object.<string,*>} object Plain object
                 * @returns {perfetto.protos.DescriptorProto.ReservedRange} ReservedRange
                 */
                ReservedRange.fromObject = function fromObject(object) {
                    if (object instanceof $root.perfetto.protos.DescriptorProto.ReservedRange)
                        return object;
                    var message = new $root.perfetto.protos.DescriptorProto.ReservedRange();
                    if (object.start != null)
                        message.start = object.start | 0;
                    if (object.end != null)
                        message.end = object.end | 0;
                    return message;
                };

                /**
                 * Creates a plain object from a ReservedRange message. Also converts values to other types if specified.
                 * @function toObject
                 * @memberof perfetto.protos.DescriptorProto.ReservedRange
                 * @static
                 * @param {perfetto.protos.DescriptorProto.ReservedRange} message ReservedRange
                 * @param {$protobuf.IConversionOptions} [options] Conversion options
                 * @returns {Object.<string,*>} Plain object
                 */
                ReservedRange.toObject = function toObject(message, options) {
                    if (!options)
                        options = {};
                    var object = {};
                    if (options.defaults) {
                        object.start = 0;
                        object.end = 0;
                    }
                    if (message.start != null && message.hasOwnProperty("start"))
                        object.start = message.start;
                    if (message.end != null && message.hasOwnProperty("end"))
                        object.end = message.end;
                    return object;
                };

                /**
                 * Converts this ReservedRange to JSON.
                 * @function toJSON
                 * @memberof perfetto.protos.DescriptorProto.ReservedRange
                 * @instance
                 * @returns {Object.<string,*>} JSON object
                 */
                ReservedRange.prototype.toJSON = function toJSON() {
                    return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
                };

                return ReservedRange;
            })();

            return DescriptorProto;
        })();

        protos.FieldDescriptorProto = (function() {

            /**
             * Properties of a FieldDescriptorProto.
             * @memberof perfetto.protos
             * @interface IFieldDescriptorProto
             * @property {string|null} [name] FieldDescriptorProto name
             * @property {number|null} [number] FieldDescriptorProto number
             * @property {perfetto.protos.FieldDescriptorProto.Label|null} [label] FieldDescriptorProto label
             * @property {perfetto.protos.FieldDescriptorProto.Type|null} [type] FieldDescriptorProto type
             * @property {string|null} [typeName] FieldDescriptorProto typeName
             * @property {string|null} [extendee] FieldDescriptorProto extendee
             * @property {string|null} [defaultValue] FieldDescriptorProto defaultValue
             * @property {number|null} [oneofIndex] FieldDescriptorProto oneofIndex
             */

            /**
             * Constructs a new FieldDescriptorProto.
             * @memberof perfetto.protos
             * @classdesc Represents a FieldDescriptorProto.
             * @implements IFieldDescriptorProto
             * @constructor
             * @param {perfetto.protos.IFieldDescriptorProto=} [properties] Properties to set
             */
            function FieldDescriptorProto(properties) {
                if (properties)
                    for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                        if (properties[keys[i]] != null)
                            this[keys[i]] = properties[keys[i]];
            }

            /**
             * FieldDescriptorProto name.
             * @member {string} name
             * @memberof perfetto.protos.FieldDescriptorProto
             * @instance
             */
            FieldDescriptorProto.prototype.name = "";

            /**
             * FieldDescriptorProto number.
             * @member {number} number
             * @memberof perfetto.protos.FieldDescriptorProto
             * @instance
             */
            FieldDescriptorProto.prototype.number = 0;

            /**
             * FieldDescriptorProto label.
             * @member {perfetto.protos.FieldDescriptorProto.Label} label
             * @memberof perfetto.protos.FieldDescriptorProto
             * @instance
             */
            FieldDescriptorProto.prototype.label = 1;

            /**
             * FieldDescriptorProto type.
             * @member {perfetto.protos.FieldDescriptorProto.Type} type
             * @memberof perfetto.protos.FieldDescriptorProto
             * @instance
             */
            FieldDescriptorProto.prototype.type = 1;

            /**
             * FieldDescriptorProto typeName.
             * @member {string} typeName
             * @memberof perfetto.protos.FieldDescriptorProto
             * @instance
             */
            FieldDescriptorProto.prototype.typeName = "";

            /**
             * FieldDescriptorProto extendee.
             * @member {string} extendee
             * @memberof perfetto.protos.FieldDescriptorProto
             * @instance
             */
            FieldDescriptorProto.prototype.extendee = "";

            /**
             * FieldDescriptorProto defaultValue.
             * @member {string} defaultValue
             * @memberof perfetto.protos.FieldDescriptorProto
             * @instance
             */
            FieldDescriptorProto.prototype.defaultValue = "";

            /**
             * FieldDescriptorProto oneofIndex.
             * @member {number} oneofIndex
             * @memberof perfetto.protos.FieldDescriptorProto
             * @instance
             */
            FieldDescriptorProto.prototype.oneofIndex = 0;

            /**
             * Creates a new FieldDescriptorProto instance using the specified properties.
             * @function create
             * @memberof perfetto.protos.FieldDescriptorProto
             * @static
             * @param {perfetto.protos.IFieldDescriptorProto=} [properties] Properties to set
             * @returns {perfetto.protos.FieldDescriptorProto} FieldDescriptorProto instance
             */
            FieldDescriptorProto.create = function create(properties) {
                return new FieldDescriptorProto(properties);
            };

            /**
             * Encodes the specified FieldDescriptorProto message. Does not implicitly {@link perfetto.protos.FieldDescriptorProto.verify|verify} messages.
             * @function encode
             * @memberof perfetto.protos.FieldDescriptorProto
             * @static
             * @param {perfetto.protos.IFieldDescriptorProto} message FieldDescriptorProto message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            FieldDescriptorProto.encode = function encode(message, writer) {
                if (!writer)
                    writer = $Writer.create();
                if (message.name != null && Object.hasOwnProperty.call(message, "name"))
                    writer.uint32(/* id 1, wireType 2 =*/10).string(message.name);
                if (message.extendee != null && Object.hasOwnProperty.call(message, "extendee"))
                    writer.uint32(/* id 2, wireType 2 =*/18).string(message.extendee);
                if (message.number != null && Object.hasOwnProperty.call(message, "number"))
                    writer.uint32(/* id 3, wireType 0 =*/24).int32(message.number);
                if (message.label != null && Object.hasOwnProperty.call(message, "label"))
                    writer.uint32(/* id 4, wireType 0 =*/32).int32(message.label);
                if (message.type != null && Object.hasOwnProperty.call(message, "type"))
                    writer.uint32(/* id 5, wireType 0 =*/40).int32(message.type);
                if (message.typeName != null && Object.hasOwnProperty.call(message, "typeName"))
                    writer.uint32(/* id 6, wireType 2 =*/50).string(message.typeName);
                if (message.defaultValue != null && Object.hasOwnProperty.call(message, "defaultValue"))
                    writer.uint32(/* id 7, wireType 2 =*/58).string(message.defaultValue);
                if (message.oneofIndex != null && Object.hasOwnProperty.call(message, "oneofIndex"))
                    writer.uint32(/* id 9, wireType 0 =*/72).int32(message.oneofIndex);
                return writer;
            };

            /**
             * Encodes the specified FieldDescriptorProto message, length delimited. Does not implicitly {@link perfetto.protos.FieldDescriptorProto.verify|verify} messages.
             * @function encodeDelimited
             * @memberof perfetto.protos.FieldDescriptorProto
             * @static
             * @param {perfetto.protos.IFieldDescriptorProto} message FieldDescriptorProto message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            FieldDescriptorProto.encodeDelimited = function encodeDelimited(message, writer) {
                return this.encode(message, writer).ldelim();
            };

            /**
             * Decodes a FieldDescriptorProto message from the specified reader or buffer.
             * @function decode
             * @memberof perfetto.protos.FieldDescriptorProto
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @param {number} [length] Message length if known beforehand
             * @returns {perfetto.protos.FieldDescriptorProto} FieldDescriptorProto
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            FieldDescriptorProto.decode = function decode(reader, length) {
                if (!(reader instanceof $Reader))
                    reader = $Reader.create(reader);
                var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.FieldDescriptorProto();
                while (reader.pos < end) {
                    var tag = reader.uint32();
                    switch (tag >>> 3) {
                    case 1:
                        message.name = reader.string();
                        break;
                    case 3:
                        message.number = reader.int32();
                        break;
                    case 4:
                        message.label = reader.int32();
                        break;
                    case 5:
                        message.type = reader.int32();
                        break;
                    case 6:
                        message.typeName = reader.string();
                        break;
                    case 2:
                        message.extendee = reader.string();
                        break;
                    case 7:
                        message.defaultValue = reader.string();
                        break;
                    case 9:
                        message.oneofIndex = reader.int32();
                        break;
                    default:
                        reader.skipType(tag & 7);
                        break;
                    }
                }
                return message;
            };

            /**
             * Decodes a FieldDescriptorProto message from the specified reader or buffer, length delimited.
             * @function decodeDelimited
             * @memberof perfetto.protos.FieldDescriptorProto
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @returns {perfetto.protos.FieldDescriptorProto} FieldDescriptorProto
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            FieldDescriptorProto.decodeDelimited = function decodeDelimited(reader) {
                if (!(reader instanceof $Reader))
                    reader = new $Reader(reader);
                return this.decode(reader, reader.uint32());
            };

            /**
             * Verifies a FieldDescriptorProto message.
             * @function verify
             * @memberof perfetto.protos.FieldDescriptorProto
             * @static
             * @param {Object.<string,*>} message Plain object to verify
             * @returns {string|null} `null` if valid, otherwise the reason why it is not
             */
            FieldDescriptorProto.verify = function verify(message) {
                if (typeof message !== "object" || message === null)
                    return "object expected";
                if (message.name != null && message.hasOwnProperty("name"))
                    if (!$util.isString(message.name))
                        return "name: string expected";
                if (message.number != null && message.hasOwnProperty("number"))
                    if (!$util.isInteger(message.number))
                        return "number: integer expected";
                if (message.label != null && message.hasOwnProperty("label"))
                    switch (message.label) {
                    default:
                        return "label: enum value expected";
                    case 1:
                    case 2:
                    case 3:
                        break;
                    }
                if (message.type != null && message.hasOwnProperty("type"))
                    switch (message.type) {
                    default:
                        return "type: enum value expected";
                    case 1:
                    case 2:
                    case 3:
                    case 4:
                    case 5:
                    case 6:
                    case 7:
                    case 8:
                    case 9:
                    case 10:
                    case 11:
                    case 12:
                    case 13:
                    case 14:
                    case 15:
                    case 16:
                    case 17:
                    case 18:
                        break;
                    }
                if (message.typeName != null && message.hasOwnProperty("typeName"))
                    if (!$util.isString(message.typeName))
                        return "typeName: string expected";
                if (message.extendee != null && message.hasOwnProperty("extendee"))
                    if (!$util.isString(message.extendee))
                        return "extendee: string expected";
                if (message.defaultValue != null && message.hasOwnProperty("defaultValue"))
                    if (!$util.isString(message.defaultValue))
                        return "defaultValue: string expected";
                if (message.oneofIndex != null && message.hasOwnProperty("oneofIndex"))
                    if (!$util.isInteger(message.oneofIndex))
                        return "oneofIndex: integer expected";
                return null;
            };

            /**
             * Creates a FieldDescriptorProto message from a plain object. Also converts values to their respective internal types.
             * @function fromObject
             * @memberof perfetto.protos.FieldDescriptorProto
             * @static
             * @param {Object.<string,*>} object Plain object
             * @returns {perfetto.protos.FieldDescriptorProto} FieldDescriptorProto
             */
            FieldDescriptorProto.fromObject = function fromObject(object) {
                if (object instanceof $root.perfetto.protos.FieldDescriptorProto)
                    return object;
                var message = new $root.perfetto.protos.FieldDescriptorProto();
                if (object.name != null)
                    message.name = String(object.name);
                if (object.number != null)
                    message.number = object.number | 0;
                switch (object.label) {
                case "LABEL_OPTIONAL":
                case 1:
                    message.label = 1;
                    break;
                case "LABEL_REQUIRED":
                case 2:
                    message.label = 2;
                    break;
                case "LABEL_REPEATED":
                case 3:
                    message.label = 3;
                    break;
                }
                switch (object.type) {
                case "TYPE_DOUBLE":
                case 1:
                    message.type = 1;
                    break;
                case "TYPE_FLOAT":
                case 2:
                    message.type = 2;
                    break;
                case "TYPE_INT64":
                case 3:
                    message.type = 3;
                    break;
                case "TYPE_UINT64":
                case 4:
                    message.type = 4;
                    break;
                case "TYPE_INT32":
                case 5:
                    message.type = 5;
                    break;
                case "TYPE_FIXED64":
                case 6:
                    message.type = 6;
                    break;
                case "TYPE_FIXED32":
                case 7:
                    message.type = 7;
                    break;
                case "TYPE_BOOL":
                case 8:
                    message.type = 8;
                    break;
                case "TYPE_STRING":
                case 9:
                    message.type = 9;
                    break;
                case "TYPE_GROUP":
                case 10:
                    message.type = 10;
                    break;
                case "TYPE_MESSAGE":
                case 11:
                    message.type = 11;
                    break;
                case "TYPE_BYTES":
                case 12:
                    message.type = 12;
                    break;
                case "TYPE_UINT32":
                case 13:
                    message.type = 13;
                    break;
                case "TYPE_ENUM":
                case 14:
                    message.type = 14;
                    break;
                case "TYPE_SFIXED32":
                case 15:
                    message.type = 15;
                    break;
                case "TYPE_SFIXED64":
                case 16:
                    message.type = 16;
                    break;
                case "TYPE_SINT32":
                case 17:
                    message.type = 17;
                    break;
                case "TYPE_SINT64":
                case 18:
                    message.type = 18;
                    break;
                }
                if (object.typeName != null)
                    message.typeName = String(object.typeName);
                if (object.extendee != null)
                    message.extendee = String(object.extendee);
                if (object.defaultValue != null)
                    message.defaultValue = String(object.defaultValue);
                if (object.oneofIndex != null)
                    message.oneofIndex = object.oneofIndex | 0;
                return message;
            };

            /**
             * Creates a plain object from a FieldDescriptorProto message. Also converts values to other types if specified.
             * @function toObject
             * @memberof perfetto.protos.FieldDescriptorProto
             * @static
             * @param {perfetto.protos.FieldDescriptorProto} message FieldDescriptorProto
             * @param {$protobuf.IConversionOptions} [options] Conversion options
             * @returns {Object.<string,*>} Plain object
             */
            FieldDescriptorProto.toObject = function toObject(message, options) {
                if (!options)
                    options = {};
                var object = {};
                if (options.defaults) {
                    object.name = "";
                    object.extendee = "";
                    object.number = 0;
                    object.label = options.enums === String ? "LABEL_OPTIONAL" : 1;
                    object.type = options.enums === String ? "TYPE_DOUBLE" : 1;
                    object.typeName = "";
                    object.defaultValue = "";
                    object.oneofIndex = 0;
                }
                if (message.name != null && message.hasOwnProperty("name"))
                    object.name = message.name;
                if (message.extendee != null && message.hasOwnProperty("extendee"))
                    object.extendee = message.extendee;
                if (message.number != null && message.hasOwnProperty("number"))
                    object.number = message.number;
                if (message.label != null && message.hasOwnProperty("label"))
                    object.label = options.enums === String ? $root.perfetto.protos.FieldDescriptorProto.Label[message.label] : message.label;
                if (message.type != null && message.hasOwnProperty("type"))
                    object.type = options.enums === String ? $root.perfetto.protos.FieldDescriptorProto.Type[message.type] : message.type;
                if (message.typeName != null && message.hasOwnProperty("typeName"))
                    object.typeName = message.typeName;
                if (message.defaultValue != null && message.hasOwnProperty("defaultValue"))
                    object.defaultValue = message.defaultValue;
                if (message.oneofIndex != null && message.hasOwnProperty("oneofIndex"))
                    object.oneofIndex = message.oneofIndex;
                return object;
            };

            /**
             * Converts this FieldDescriptorProto to JSON.
             * @function toJSON
             * @memberof perfetto.protos.FieldDescriptorProto
             * @instance
             * @returns {Object.<string,*>} JSON object
             */
            FieldDescriptorProto.prototype.toJSON = function toJSON() {
                return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
            };

            /**
             * Type enum.
             * @name perfetto.protos.FieldDescriptorProto.Type
             * @enum {number}
             * @property {number} TYPE_DOUBLE=1 TYPE_DOUBLE value
             * @property {number} TYPE_FLOAT=2 TYPE_FLOAT value
             * @property {number} TYPE_INT64=3 TYPE_INT64 value
             * @property {number} TYPE_UINT64=4 TYPE_UINT64 value
             * @property {number} TYPE_INT32=5 TYPE_INT32 value
             * @property {number} TYPE_FIXED64=6 TYPE_FIXED64 value
             * @property {number} TYPE_FIXED32=7 TYPE_FIXED32 value
             * @property {number} TYPE_BOOL=8 TYPE_BOOL value
             * @property {number} TYPE_STRING=9 TYPE_STRING value
             * @property {number} TYPE_GROUP=10 TYPE_GROUP value
             * @property {number} TYPE_MESSAGE=11 TYPE_MESSAGE value
             * @property {number} TYPE_BYTES=12 TYPE_BYTES value
             * @property {number} TYPE_UINT32=13 TYPE_UINT32 value
             * @property {number} TYPE_ENUM=14 TYPE_ENUM value
             * @property {number} TYPE_SFIXED32=15 TYPE_SFIXED32 value
             * @property {number} TYPE_SFIXED64=16 TYPE_SFIXED64 value
             * @property {number} TYPE_SINT32=17 TYPE_SINT32 value
             * @property {number} TYPE_SINT64=18 TYPE_SINT64 value
             */
            FieldDescriptorProto.Type = (function() {
                var valuesById = {}, values = Object.create(valuesById);
                values[valuesById[1] = "TYPE_DOUBLE"] = 1;
                values[valuesById[2] = "TYPE_FLOAT"] = 2;
                values[valuesById[3] = "TYPE_INT64"] = 3;
                values[valuesById[4] = "TYPE_UINT64"] = 4;
                values[valuesById[5] = "TYPE_INT32"] = 5;
                values[valuesById[6] = "TYPE_FIXED64"] = 6;
                values[valuesById[7] = "TYPE_FIXED32"] = 7;
                values[valuesById[8] = "TYPE_BOOL"] = 8;
                values[valuesById[9] = "TYPE_STRING"] = 9;
                values[valuesById[10] = "TYPE_GROUP"] = 10;
                values[valuesById[11] = "TYPE_MESSAGE"] = 11;
                values[valuesById[12] = "TYPE_BYTES"] = 12;
                values[valuesById[13] = "TYPE_UINT32"] = 13;
                values[valuesById[14] = "TYPE_ENUM"] = 14;
                values[valuesById[15] = "TYPE_SFIXED32"] = 15;
                values[valuesById[16] = "TYPE_SFIXED64"] = 16;
                values[valuesById[17] = "TYPE_SINT32"] = 17;
                values[valuesById[18] = "TYPE_SINT64"] = 18;
                return values;
            })();

            /**
             * Label enum.
             * @name perfetto.protos.FieldDescriptorProto.Label
             * @enum {number}
             * @property {number} LABEL_OPTIONAL=1 LABEL_OPTIONAL value
             * @property {number} LABEL_REQUIRED=2 LABEL_REQUIRED value
             * @property {number} LABEL_REPEATED=3 LABEL_REPEATED value
             */
            FieldDescriptorProto.Label = (function() {
                var valuesById = {}, values = Object.create(valuesById);
                values[valuesById[1] = "LABEL_OPTIONAL"] = 1;
                values[valuesById[2] = "LABEL_REQUIRED"] = 2;
                values[valuesById[3] = "LABEL_REPEATED"] = 3;
                return values;
            })();

            return FieldDescriptorProto;
        })();

        protos.OneofDescriptorProto = (function() {

            /**
             * Properties of an OneofDescriptorProto.
             * @memberof perfetto.protos
             * @interface IOneofDescriptorProto
             * @property {string|null} [name] OneofDescriptorProto name
             * @property {perfetto.protos.IOneofOptions|null} [options] OneofDescriptorProto options
             */

            /**
             * Constructs a new OneofDescriptorProto.
             * @memberof perfetto.protos
             * @classdesc Represents an OneofDescriptorProto.
             * @implements IOneofDescriptorProto
             * @constructor
             * @param {perfetto.protos.IOneofDescriptorProto=} [properties] Properties to set
             */
            function OneofDescriptorProto(properties) {
                if (properties)
                    for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                        if (properties[keys[i]] != null)
                            this[keys[i]] = properties[keys[i]];
            }

            /**
             * OneofDescriptorProto name.
             * @member {string} name
             * @memberof perfetto.protos.OneofDescriptorProto
             * @instance
             */
            OneofDescriptorProto.prototype.name = "";

            /**
             * OneofDescriptorProto options.
             * @member {perfetto.protos.IOneofOptions|null|undefined} options
             * @memberof perfetto.protos.OneofDescriptorProto
             * @instance
             */
            OneofDescriptorProto.prototype.options = null;

            /**
             * Creates a new OneofDescriptorProto instance using the specified properties.
             * @function create
             * @memberof perfetto.protos.OneofDescriptorProto
             * @static
             * @param {perfetto.protos.IOneofDescriptorProto=} [properties] Properties to set
             * @returns {perfetto.protos.OneofDescriptorProto} OneofDescriptorProto instance
             */
            OneofDescriptorProto.create = function create(properties) {
                return new OneofDescriptorProto(properties);
            };

            /**
             * Encodes the specified OneofDescriptorProto message. Does not implicitly {@link perfetto.protos.OneofDescriptorProto.verify|verify} messages.
             * @function encode
             * @memberof perfetto.protos.OneofDescriptorProto
             * @static
             * @param {perfetto.protos.IOneofDescriptorProto} message OneofDescriptorProto message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            OneofDescriptorProto.encode = function encode(message, writer) {
                if (!writer)
                    writer = $Writer.create();
                if (message.name != null && Object.hasOwnProperty.call(message, "name"))
                    writer.uint32(/* id 1, wireType 2 =*/10).string(message.name);
                if (message.options != null && Object.hasOwnProperty.call(message, "options"))
                    $root.perfetto.protos.OneofOptions.encode(message.options, writer.uint32(/* id 2, wireType 2 =*/18).fork()).ldelim();
                return writer;
            };

            /**
             * Encodes the specified OneofDescriptorProto message, length delimited. Does not implicitly {@link perfetto.protos.OneofDescriptorProto.verify|verify} messages.
             * @function encodeDelimited
             * @memberof perfetto.protos.OneofDescriptorProto
             * @static
             * @param {perfetto.protos.IOneofDescriptorProto} message OneofDescriptorProto message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            OneofDescriptorProto.encodeDelimited = function encodeDelimited(message, writer) {
                return this.encode(message, writer).ldelim();
            };

            /**
             * Decodes an OneofDescriptorProto message from the specified reader or buffer.
             * @function decode
             * @memberof perfetto.protos.OneofDescriptorProto
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @param {number} [length] Message length if known beforehand
             * @returns {perfetto.protos.OneofDescriptorProto} OneofDescriptorProto
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            OneofDescriptorProto.decode = function decode(reader, length) {
                if (!(reader instanceof $Reader))
                    reader = $Reader.create(reader);
                var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.OneofDescriptorProto();
                while (reader.pos < end) {
                    var tag = reader.uint32();
                    switch (tag >>> 3) {
                    case 1:
                        message.name = reader.string();
                        break;
                    case 2:
                        message.options = $root.perfetto.protos.OneofOptions.decode(reader, reader.uint32());
                        break;
                    default:
                        reader.skipType(tag & 7);
                        break;
                    }
                }
                return message;
            };

            /**
             * Decodes an OneofDescriptorProto message from the specified reader or buffer, length delimited.
             * @function decodeDelimited
             * @memberof perfetto.protos.OneofDescriptorProto
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @returns {perfetto.protos.OneofDescriptorProto} OneofDescriptorProto
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            OneofDescriptorProto.decodeDelimited = function decodeDelimited(reader) {
                if (!(reader instanceof $Reader))
                    reader = new $Reader(reader);
                return this.decode(reader, reader.uint32());
            };

            /**
             * Verifies an OneofDescriptorProto message.
             * @function verify
             * @memberof perfetto.protos.OneofDescriptorProto
             * @static
             * @param {Object.<string,*>} message Plain object to verify
             * @returns {string|null} `null` if valid, otherwise the reason why it is not
             */
            OneofDescriptorProto.verify = function verify(message) {
                if (typeof message !== "object" || message === null)
                    return "object expected";
                if (message.name != null && message.hasOwnProperty("name"))
                    if (!$util.isString(message.name))
                        return "name: string expected";
                if (message.options != null && message.hasOwnProperty("options")) {
                    var error = $root.perfetto.protos.OneofOptions.verify(message.options);
                    if (error)
                        return "options." + error;
                }
                return null;
            };

            /**
             * Creates an OneofDescriptorProto message from a plain object. Also converts values to their respective internal types.
             * @function fromObject
             * @memberof perfetto.protos.OneofDescriptorProto
             * @static
             * @param {Object.<string,*>} object Plain object
             * @returns {perfetto.protos.OneofDescriptorProto} OneofDescriptorProto
             */
            OneofDescriptorProto.fromObject = function fromObject(object) {
                if (object instanceof $root.perfetto.protos.OneofDescriptorProto)
                    return object;
                var message = new $root.perfetto.protos.OneofDescriptorProto();
                if (object.name != null)
                    message.name = String(object.name);
                if (object.options != null) {
                    if (typeof object.options !== "object")
                        throw TypeError(".perfetto.protos.OneofDescriptorProto.options: object expected");
                    message.options = $root.perfetto.protos.OneofOptions.fromObject(object.options);
                }
                return message;
            };

            /**
             * Creates a plain object from an OneofDescriptorProto message. Also converts values to other types if specified.
             * @function toObject
             * @memberof perfetto.protos.OneofDescriptorProto
             * @static
             * @param {perfetto.protos.OneofDescriptorProto} message OneofDescriptorProto
             * @param {$protobuf.IConversionOptions} [options] Conversion options
             * @returns {Object.<string,*>} Plain object
             */
            OneofDescriptorProto.toObject = function toObject(message, options) {
                if (!options)
                    options = {};
                var object = {};
                if (options.defaults) {
                    object.name = "";
                    object.options = null;
                }
                if (message.name != null && message.hasOwnProperty("name"))
                    object.name = message.name;
                if (message.options != null && message.hasOwnProperty("options"))
                    object.options = $root.perfetto.protos.OneofOptions.toObject(message.options, options);
                return object;
            };

            /**
             * Converts this OneofDescriptorProto to JSON.
             * @function toJSON
             * @memberof perfetto.protos.OneofDescriptorProto
             * @instance
             * @returns {Object.<string,*>} JSON object
             */
            OneofDescriptorProto.prototype.toJSON = function toJSON() {
                return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
            };

            return OneofDescriptorProto;
        })();

        protos.EnumDescriptorProto = (function() {

            /**
             * Properties of an EnumDescriptorProto.
             * @memberof perfetto.protos
             * @interface IEnumDescriptorProto
             * @property {string|null} [name] EnumDescriptorProto name
             * @property {Array.<perfetto.protos.IEnumValueDescriptorProto>|null} [value] EnumDescriptorProto value
             * @property {Array.<string>|null} [reservedName] EnumDescriptorProto reservedName
             */

            /**
             * Constructs a new EnumDescriptorProto.
             * @memberof perfetto.protos
             * @classdesc Represents an EnumDescriptorProto.
             * @implements IEnumDescriptorProto
             * @constructor
             * @param {perfetto.protos.IEnumDescriptorProto=} [properties] Properties to set
             */
            function EnumDescriptorProto(properties) {
                this.value = [];
                this.reservedName = [];
                if (properties)
                    for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                        if (properties[keys[i]] != null)
                            this[keys[i]] = properties[keys[i]];
            }

            /**
             * EnumDescriptorProto name.
             * @member {string} name
             * @memberof perfetto.protos.EnumDescriptorProto
             * @instance
             */
            EnumDescriptorProto.prototype.name = "";

            /**
             * EnumDescriptorProto value.
             * @member {Array.<perfetto.protos.IEnumValueDescriptorProto>} value
             * @memberof perfetto.protos.EnumDescriptorProto
             * @instance
             */
            EnumDescriptorProto.prototype.value = $util.emptyArray;

            /**
             * EnumDescriptorProto reservedName.
             * @member {Array.<string>} reservedName
             * @memberof perfetto.protos.EnumDescriptorProto
             * @instance
             */
            EnumDescriptorProto.prototype.reservedName = $util.emptyArray;

            /**
             * Creates a new EnumDescriptorProto instance using the specified properties.
             * @function create
             * @memberof perfetto.protos.EnumDescriptorProto
             * @static
             * @param {perfetto.protos.IEnumDescriptorProto=} [properties] Properties to set
             * @returns {perfetto.protos.EnumDescriptorProto} EnumDescriptorProto instance
             */
            EnumDescriptorProto.create = function create(properties) {
                return new EnumDescriptorProto(properties);
            };

            /**
             * Encodes the specified EnumDescriptorProto message. Does not implicitly {@link perfetto.protos.EnumDescriptorProto.verify|verify} messages.
             * @function encode
             * @memberof perfetto.protos.EnumDescriptorProto
             * @static
             * @param {perfetto.protos.IEnumDescriptorProto} message EnumDescriptorProto message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            EnumDescriptorProto.encode = function encode(message, writer) {
                if (!writer)
                    writer = $Writer.create();
                if (message.name != null && Object.hasOwnProperty.call(message, "name"))
                    writer.uint32(/* id 1, wireType 2 =*/10).string(message.name);
                if (message.value != null && message.value.length)
                    for (var i = 0; i < message.value.length; ++i)
                        $root.perfetto.protos.EnumValueDescriptorProto.encode(message.value[i], writer.uint32(/* id 2, wireType 2 =*/18).fork()).ldelim();
                if (message.reservedName != null && message.reservedName.length)
                    for (var i = 0; i < message.reservedName.length; ++i)
                        writer.uint32(/* id 5, wireType 2 =*/42).string(message.reservedName[i]);
                return writer;
            };

            /**
             * Encodes the specified EnumDescriptorProto message, length delimited. Does not implicitly {@link perfetto.protos.EnumDescriptorProto.verify|verify} messages.
             * @function encodeDelimited
             * @memberof perfetto.protos.EnumDescriptorProto
             * @static
             * @param {perfetto.protos.IEnumDescriptorProto} message EnumDescriptorProto message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            EnumDescriptorProto.encodeDelimited = function encodeDelimited(message, writer) {
                return this.encode(message, writer).ldelim();
            };

            /**
             * Decodes an EnumDescriptorProto message from the specified reader or buffer.
             * @function decode
             * @memberof perfetto.protos.EnumDescriptorProto
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @param {number} [length] Message length if known beforehand
             * @returns {perfetto.protos.EnumDescriptorProto} EnumDescriptorProto
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            EnumDescriptorProto.decode = function decode(reader, length) {
                if (!(reader instanceof $Reader))
                    reader = $Reader.create(reader);
                var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.EnumDescriptorProto();
                while (reader.pos < end) {
                    var tag = reader.uint32();
                    switch (tag >>> 3) {
                    case 1:
                        message.name = reader.string();
                        break;
                    case 2:
                        if (!(message.value && message.value.length))
                            message.value = [];
                        message.value.push($root.perfetto.protos.EnumValueDescriptorProto.decode(reader, reader.uint32()));
                        break;
                    case 5:
                        if (!(message.reservedName && message.reservedName.length))
                            message.reservedName = [];
                        message.reservedName.push(reader.string());
                        break;
                    default:
                        reader.skipType(tag & 7);
                        break;
                    }
                }
                return message;
            };

            /**
             * Decodes an EnumDescriptorProto message from the specified reader or buffer, length delimited.
             * @function decodeDelimited
             * @memberof perfetto.protos.EnumDescriptorProto
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @returns {perfetto.protos.EnumDescriptorProto} EnumDescriptorProto
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            EnumDescriptorProto.decodeDelimited = function decodeDelimited(reader) {
                if (!(reader instanceof $Reader))
                    reader = new $Reader(reader);
                return this.decode(reader, reader.uint32());
            };

            /**
             * Verifies an EnumDescriptorProto message.
             * @function verify
             * @memberof perfetto.protos.EnumDescriptorProto
             * @static
             * @param {Object.<string,*>} message Plain object to verify
             * @returns {string|null} `null` if valid, otherwise the reason why it is not
             */
            EnumDescriptorProto.verify = function verify(message) {
                if (typeof message !== "object" || message === null)
                    return "object expected";
                if (message.name != null && message.hasOwnProperty("name"))
                    if (!$util.isString(message.name))
                        return "name: string expected";
                if (message.value != null && message.hasOwnProperty("value")) {
                    if (!Array.isArray(message.value))
                        return "value: array expected";
                    for (var i = 0; i < message.value.length; ++i) {
                        var error = $root.perfetto.protos.EnumValueDescriptorProto.verify(message.value[i]);
                        if (error)
                            return "value." + error;
                    }
                }
                if (message.reservedName != null && message.hasOwnProperty("reservedName")) {
                    if (!Array.isArray(message.reservedName))
                        return "reservedName: array expected";
                    for (var i = 0; i < message.reservedName.length; ++i)
                        if (!$util.isString(message.reservedName[i]))
                            return "reservedName: string[] expected";
                }
                return null;
            };

            /**
             * Creates an EnumDescriptorProto message from a plain object. Also converts values to their respective internal types.
             * @function fromObject
             * @memberof perfetto.protos.EnumDescriptorProto
             * @static
             * @param {Object.<string,*>} object Plain object
             * @returns {perfetto.protos.EnumDescriptorProto} EnumDescriptorProto
             */
            EnumDescriptorProto.fromObject = function fromObject(object) {
                if (object instanceof $root.perfetto.protos.EnumDescriptorProto)
                    return object;
                var message = new $root.perfetto.protos.EnumDescriptorProto();
                if (object.name != null)
                    message.name = String(object.name);
                if (object.value) {
                    if (!Array.isArray(object.value))
                        throw TypeError(".perfetto.protos.EnumDescriptorProto.value: array expected");
                    message.value = [];
                    for (var i = 0; i < object.value.length; ++i) {
                        if (typeof object.value[i] !== "object")
                            throw TypeError(".perfetto.protos.EnumDescriptorProto.value: object expected");
                        message.value[i] = $root.perfetto.protos.EnumValueDescriptorProto.fromObject(object.value[i]);
                    }
                }
                if (object.reservedName) {
                    if (!Array.isArray(object.reservedName))
                        throw TypeError(".perfetto.protos.EnumDescriptorProto.reservedName: array expected");
                    message.reservedName = [];
                    for (var i = 0; i < object.reservedName.length; ++i)
                        message.reservedName[i] = String(object.reservedName[i]);
                }
                return message;
            };

            /**
             * Creates a plain object from an EnumDescriptorProto message. Also converts values to other types if specified.
             * @function toObject
             * @memberof perfetto.protos.EnumDescriptorProto
             * @static
             * @param {perfetto.protos.EnumDescriptorProto} message EnumDescriptorProto
             * @param {$protobuf.IConversionOptions} [options] Conversion options
             * @returns {Object.<string,*>} Plain object
             */
            EnumDescriptorProto.toObject = function toObject(message, options) {
                if (!options)
                    options = {};
                var object = {};
                if (options.arrays || options.defaults) {
                    object.value = [];
                    object.reservedName = [];
                }
                if (options.defaults)
                    object.name = "";
                if (message.name != null && message.hasOwnProperty("name"))
                    object.name = message.name;
                if (message.value && message.value.length) {
                    object.value = [];
                    for (var j = 0; j < message.value.length; ++j)
                        object.value[j] = $root.perfetto.protos.EnumValueDescriptorProto.toObject(message.value[j], options);
                }
                if (message.reservedName && message.reservedName.length) {
                    object.reservedName = [];
                    for (var j = 0; j < message.reservedName.length; ++j)
                        object.reservedName[j] = message.reservedName[j];
                }
                return object;
            };

            /**
             * Converts this EnumDescriptorProto to JSON.
             * @function toJSON
             * @memberof perfetto.protos.EnumDescriptorProto
             * @instance
             * @returns {Object.<string,*>} JSON object
             */
            EnumDescriptorProto.prototype.toJSON = function toJSON() {
                return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
            };

            return EnumDescriptorProto;
        })();

        protos.EnumValueDescriptorProto = (function() {

            /**
             * Properties of an EnumValueDescriptorProto.
             * @memberof perfetto.protos
             * @interface IEnumValueDescriptorProto
             * @property {string|null} [name] EnumValueDescriptorProto name
             * @property {number|null} [number] EnumValueDescriptorProto number
             */

            /**
             * Constructs a new EnumValueDescriptorProto.
             * @memberof perfetto.protos
             * @classdesc Represents an EnumValueDescriptorProto.
             * @implements IEnumValueDescriptorProto
             * @constructor
             * @param {perfetto.protos.IEnumValueDescriptorProto=} [properties] Properties to set
             */
            function EnumValueDescriptorProto(properties) {
                if (properties)
                    for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                        if (properties[keys[i]] != null)
                            this[keys[i]] = properties[keys[i]];
            }

            /**
             * EnumValueDescriptorProto name.
             * @member {string} name
             * @memberof perfetto.protos.EnumValueDescriptorProto
             * @instance
             */
            EnumValueDescriptorProto.prototype.name = "";

            /**
             * EnumValueDescriptorProto number.
             * @member {number} number
             * @memberof perfetto.protos.EnumValueDescriptorProto
             * @instance
             */
            EnumValueDescriptorProto.prototype.number = 0;

            /**
             * Creates a new EnumValueDescriptorProto instance using the specified properties.
             * @function create
             * @memberof perfetto.protos.EnumValueDescriptorProto
             * @static
             * @param {perfetto.protos.IEnumValueDescriptorProto=} [properties] Properties to set
             * @returns {perfetto.protos.EnumValueDescriptorProto} EnumValueDescriptorProto instance
             */
            EnumValueDescriptorProto.create = function create(properties) {
                return new EnumValueDescriptorProto(properties);
            };

            /**
             * Encodes the specified EnumValueDescriptorProto message. Does not implicitly {@link perfetto.protos.EnumValueDescriptorProto.verify|verify} messages.
             * @function encode
             * @memberof perfetto.protos.EnumValueDescriptorProto
             * @static
             * @param {perfetto.protos.IEnumValueDescriptorProto} message EnumValueDescriptorProto message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            EnumValueDescriptorProto.encode = function encode(message, writer) {
                if (!writer)
                    writer = $Writer.create();
                if (message.name != null && Object.hasOwnProperty.call(message, "name"))
                    writer.uint32(/* id 1, wireType 2 =*/10).string(message.name);
                if (message.number != null && Object.hasOwnProperty.call(message, "number"))
                    writer.uint32(/* id 2, wireType 0 =*/16).int32(message.number);
                return writer;
            };

            /**
             * Encodes the specified EnumValueDescriptorProto message, length delimited. Does not implicitly {@link perfetto.protos.EnumValueDescriptorProto.verify|verify} messages.
             * @function encodeDelimited
             * @memberof perfetto.protos.EnumValueDescriptorProto
             * @static
             * @param {perfetto.protos.IEnumValueDescriptorProto} message EnumValueDescriptorProto message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            EnumValueDescriptorProto.encodeDelimited = function encodeDelimited(message, writer) {
                return this.encode(message, writer).ldelim();
            };

            /**
             * Decodes an EnumValueDescriptorProto message from the specified reader or buffer.
             * @function decode
             * @memberof perfetto.protos.EnumValueDescriptorProto
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @param {number} [length] Message length if known beforehand
             * @returns {perfetto.protos.EnumValueDescriptorProto} EnumValueDescriptorProto
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            EnumValueDescriptorProto.decode = function decode(reader, length) {
                if (!(reader instanceof $Reader))
                    reader = $Reader.create(reader);
                var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.EnumValueDescriptorProto();
                while (reader.pos < end) {
                    var tag = reader.uint32();
                    switch (tag >>> 3) {
                    case 1:
                        message.name = reader.string();
                        break;
                    case 2:
                        message.number = reader.int32();
                        break;
                    default:
                        reader.skipType(tag & 7);
                        break;
                    }
                }
                return message;
            };

            /**
             * Decodes an EnumValueDescriptorProto message from the specified reader or buffer, length delimited.
             * @function decodeDelimited
             * @memberof perfetto.protos.EnumValueDescriptorProto
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @returns {perfetto.protos.EnumValueDescriptorProto} EnumValueDescriptorProto
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            EnumValueDescriptorProto.decodeDelimited = function decodeDelimited(reader) {
                if (!(reader instanceof $Reader))
                    reader = new $Reader(reader);
                return this.decode(reader, reader.uint32());
            };

            /**
             * Verifies an EnumValueDescriptorProto message.
             * @function verify
             * @memberof perfetto.protos.EnumValueDescriptorProto
             * @static
             * @param {Object.<string,*>} message Plain object to verify
             * @returns {string|null} `null` if valid, otherwise the reason why it is not
             */
            EnumValueDescriptorProto.verify = function verify(message) {
                if (typeof message !== "object" || message === null)
                    return "object expected";
                if (message.name != null && message.hasOwnProperty("name"))
                    if (!$util.isString(message.name))
                        return "name: string expected";
                if (message.number != null && message.hasOwnProperty("number"))
                    if (!$util.isInteger(message.number))
                        return "number: integer expected";
                return null;
            };

            /**
             * Creates an EnumValueDescriptorProto message from a plain object. Also converts values to their respective internal types.
             * @function fromObject
             * @memberof perfetto.protos.EnumValueDescriptorProto
             * @static
             * @param {Object.<string,*>} object Plain object
             * @returns {perfetto.protos.EnumValueDescriptorProto} EnumValueDescriptorProto
             */
            EnumValueDescriptorProto.fromObject = function fromObject(object) {
                if (object instanceof $root.perfetto.protos.EnumValueDescriptorProto)
                    return object;
                var message = new $root.perfetto.protos.EnumValueDescriptorProto();
                if (object.name != null)
                    message.name = String(object.name);
                if (object.number != null)
                    message.number = object.number | 0;
                return message;
            };

            /**
             * Creates a plain object from an EnumValueDescriptorProto message. Also converts values to other types if specified.
             * @function toObject
             * @memberof perfetto.protos.EnumValueDescriptorProto
             * @static
             * @param {perfetto.protos.EnumValueDescriptorProto} message EnumValueDescriptorProto
             * @param {$protobuf.IConversionOptions} [options] Conversion options
             * @returns {Object.<string,*>} Plain object
             */
            EnumValueDescriptorProto.toObject = function toObject(message, options) {
                if (!options)
                    options = {};
                var object = {};
                if (options.defaults) {
                    object.name = "";
                    object.number = 0;
                }
                if (message.name != null && message.hasOwnProperty("name"))
                    object.name = message.name;
                if (message.number != null && message.hasOwnProperty("number"))
                    object.number = message.number;
                return object;
            };

            /**
             * Converts this EnumValueDescriptorProto to JSON.
             * @function toJSON
             * @memberof perfetto.protos.EnumValueDescriptorProto
             * @instance
             * @returns {Object.<string,*>} JSON object
             */
            EnumValueDescriptorProto.prototype.toJSON = function toJSON() {
                return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
            };

            return EnumValueDescriptorProto;
        })();

        protos.OneofOptions = (function() {

            /**
             * Properties of an OneofOptions.
             * @memberof perfetto.protos
             * @interface IOneofOptions
             */

            /**
             * Constructs a new OneofOptions.
             * @memberof perfetto.protos
             * @classdesc Represents an OneofOptions.
             * @implements IOneofOptions
             * @constructor
             * @param {perfetto.protos.IOneofOptions=} [properties] Properties to set
             */
            function OneofOptions(properties) {
                if (properties)
                    for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                        if (properties[keys[i]] != null)
                            this[keys[i]] = properties[keys[i]];
            }

            /**
             * Creates a new OneofOptions instance using the specified properties.
             * @function create
             * @memberof perfetto.protos.OneofOptions
             * @static
             * @param {perfetto.protos.IOneofOptions=} [properties] Properties to set
             * @returns {perfetto.protos.OneofOptions} OneofOptions instance
             */
            OneofOptions.create = function create(properties) {
                return new OneofOptions(properties);
            };

            /**
             * Encodes the specified OneofOptions message. Does not implicitly {@link perfetto.protos.OneofOptions.verify|verify} messages.
             * @function encode
             * @memberof perfetto.protos.OneofOptions
             * @static
             * @param {perfetto.protos.IOneofOptions} message OneofOptions message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            OneofOptions.encode = function encode(message, writer) {
                if (!writer)
                    writer = $Writer.create();
                return writer;
            };

            /**
             * Encodes the specified OneofOptions message, length delimited. Does not implicitly {@link perfetto.protos.OneofOptions.verify|verify} messages.
             * @function encodeDelimited
             * @memberof perfetto.protos.OneofOptions
             * @static
             * @param {perfetto.protos.IOneofOptions} message OneofOptions message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            OneofOptions.encodeDelimited = function encodeDelimited(message, writer) {
                return this.encode(message, writer).ldelim();
            };

            /**
             * Decodes an OneofOptions message from the specified reader or buffer.
             * @function decode
             * @memberof perfetto.protos.OneofOptions
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @param {number} [length] Message length if known beforehand
             * @returns {perfetto.protos.OneofOptions} OneofOptions
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            OneofOptions.decode = function decode(reader, length) {
                if (!(reader instanceof $Reader))
                    reader = $Reader.create(reader);
                var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.OneofOptions();
                while (reader.pos < end) {
                    var tag = reader.uint32();
                    switch (tag >>> 3) {
                    default:
                        reader.skipType(tag & 7);
                        break;
                    }
                }
                return message;
            };

            /**
             * Decodes an OneofOptions message from the specified reader or buffer, length delimited.
             * @function decodeDelimited
             * @memberof perfetto.protos.OneofOptions
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @returns {perfetto.protos.OneofOptions} OneofOptions
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            OneofOptions.decodeDelimited = function decodeDelimited(reader) {
                if (!(reader instanceof $Reader))
                    reader = new $Reader(reader);
                return this.decode(reader, reader.uint32());
            };

            /**
             * Verifies an OneofOptions message.
             * @function verify
             * @memberof perfetto.protos.OneofOptions
             * @static
             * @param {Object.<string,*>} message Plain object to verify
             * @returns {string|null} `null` if valid, otherwise the reason why it is not
             */
            OneofOptions.verify = function verify(message) {
                if (typeof message !== "object" || message === null)
                    return "object expected";
                return null;
            };

            /**
             * Creates an OneofOptions message from a plain object. Also converts values to their respective internal types.
             * @function fromObject
             * @memberof perfetto.protos.OneofOptions
             * @static
             * @param {Object.<string,*>} object Plain object
             * @returns {perfetto.protos.OneofOptions} OneofOptions
             */
            OneofOptions.fromObject = function fromObject(object) {
                if (object instanceof $root.perfetto.protos.OneofOptions)
                    return object;
                return new $root.perfetto.protos.OneofOptions();
            };

            /**
             * Creates a plain object from an OneofOptions message. Also converts values to other types if specified.
             * @function toObject
             * @memberof perfetto.protos.OneofOptions
             * @static
             * @param {perfetto.protos.OneofOptions} message OneofOptions
             * @param {$protobuf.IConversionOptions} [options] Conversion options
             * @returns {Object.<string,*>} Plain object
             */
            OneofOptions.toObject = function toObject() {
                return {};
            };

            /**
             * Converts this OneofOptions to JSON.
             * @function toJSON
             * @memberof perfetto.protos.OneofOptions
             * @instance
             * @returns {Object.<string,*>} JSON object
             */
            OneofOptions.prototype.toJSON = function toJSON() {
                return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
            };

            return OneofOptions;
        })();

        protos.TraceStats = (function() {

            /**
             * Properties of a TraceStats.
             * @memberof perfetto.protos
             * @interface ITraceStats
             * @property {Array.<perfetto.protos.TraceStats.IBufferStats>|null} [bufferStats] TraceStats bufferStats
             * @property {number|null} [producersConnected] TraceStats producersConnected
             * @property {number|null} [producersSeen] TraceStats producersSeen
             * @property {number|null} [dataSourcesRegistered] TraceStats dataSourcesRegistered
             * @property {number|null} [dataSourcesSeen] TraceStats dataSourcesSeen
             * @property {number|null} [tracingSessions] TraceStats tracingSessions
             * @property {number|null} [totalBuffers] TraceStats totalBuffers
             * @property {number|null} [chunksDiscarded] TraceStats chunksDiscarded
             * @property {number|null} [patchesDiscarded] TraceStats patchesDiscarded
             * @property {number|null} [invalidPackets] TraceStats invalidPackets
             * @property {perfetto.protos.TraceStats.IFilterStats|null} [filterStats] TraceStats filterStats
             */

            /**
             * Constructs a new TraceStats.
             * @memberof perfetto.protos
             * @classdesc Represents a TraceStats.
             * @implements ITraceStats
             * @constructor
             * @param {perfetto.protos.ITraceStats=} [properties] Properties to set
             */
            function TraceStats(properties) {
                this.bufferStats = [];
                if (properties)
                    for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                        if (properties[keys[i]] != null)
                            this[keys[i]] = properties[keys[i]];
            }

            /**
             * TraceStats bufferStats.
             * @member {Array.<perfetto.protos.TraceStats.IBufferStats>} bufferStats
             * @memberof perfetto.protos.TraceStats
             * @instance
             */
            TraceStats.prototype.bufferStats = $util.emptyArray;

            /**
             * TraceStats producersConnected.
             * @member {number} producersConnected
             * @memberof perfetto.protos.TraceStats
             * @instance
             */
            TraceStats.prototype.producersConnected = 0;

            /**
             * TraceStats producersSeen.
             * @member {number} producersSeen
             * @memberof perfetto.protos.TraceStats
             * @instance
             */
            TraceStats.prototype.producersSeen = $util.Long ? $util.Long.fromBits(0,0,true) : 0;

            /**
             * TraceStats dataSourcesRegistered.
             * @member {number} dataSourcesRegistered
             * @memberof perfetto.protos.TraceStats
             * @instance
             */
            TraceStats.prototype.dataSourcesRegistered = 0;

            /**
             * TraceStats dataSourcesSeen.
             * @member {number} dataSourcesSeen
             * @memberof perfetto.protos.TraceStats
             * @instance
             */
            TraceStats.prototype.dataSourcesSeen = $util.Long ? $util.Long.fromBits(0,0,true) : 0;

            /**
             * TraceStats tracingSessions.
             * @member {number} tracingSessions
             * @memberof perfetto.protos.TraceStats
             * @instance
             */
            TraceStats.prototype.tracingSessions = 0;

            /**
             * TraceStats totalBuffers.
             * @member {number} totalBuffers
             * @memberof perfetto.protos.TraceStats
             * @instance
             */
            TraceStats.prototype.totalBuffers = 0;

            /**
             * TraceStats chunksDiscarded.
             * @member {number} chunksDiscarded
             * @memberof perfetto.protos.TraceStats
             * @instance
             */
            TraceStats.prototype.chunksDiscarded = $util.Long ? $util.Long.fromBits(0,0,true) : 0;

            /**
             * TraceStats patchesDiscarded.
             * @member {number} patchesDiscarded
             * @memberof perfetto.protos.TraceStats
             * @instance
             */
            TraceStats.prototype.patchesDiscarded = $util.Long ? $util.Long.fromBits(0,0,true) : 0;

            /**
             * TraceStats invalidPackets.
             * @member {number} invalidPackets
             * @memberof perfetto.protos.TraceStats
             * @instance
             */
            TraceStats.prototype.invalidPackets = $util.Long ? $util.Long.fromBits(0,0,true) : 0;

            /**
             * TraceStats filterStats.
             * @member {perfetto.protos.TraceStats.IFilterStats|null|undefined} filterStats
             * @memberof perfetto.protos.TraceStats
             * @instance
             */
            TraceStats.prototype.filterStats = null;

            /**
             * Creates a new TraceStats instance using the specified properties.
             * @function create
             * @memberof perfetto.protos.TraceStats
             * @static
             * @param {perfetto.protos.ITraceStats=} [properties] Properties to set
             * @returns {perfetto.protos.TraceStats} TraceStats instance
             */
            TraceStats.create = function create(properties) {
                return new TraceStats(properties);
            };

            /**
             * Encodes the specified TraceStats message. Does not implicitly {@link perfetto.protos.TraceStats.verify|verify} messages.
             * @function encode
             * @memberof perfetto.protos.TraceStats
             * @static
             * @param {perfetto.protos.ITraceStats} message TraceStats message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            TraceStats.encode = function encode(message, writer) {
                if (!writer)
                    writer = $Writer.create();
                if (message.bufferStats != null && message.bufferStats.length)
                    for (var i = 0; i < message.bufferStats.length; ++i)
                        $root.perfetto.protos.TraceStats.BufferStats.encode(message.bufferStats[i], writer.uint32(/* id 1, wireType 2 =*/10).fork()).ldelim();
                if (message.producersConnected != null && Object.hasOwnProperty.call(message, "producersConnected"))
                    writer.uint32(/* id 2, wireType 0 =*/16).uint32(message.producersConnected);
                if (message.producersSeen != null && Object.hasOwnProperty.call(message, "producersSeen"))
                    writer.uint32(/* id 3, wireType 0 =*/24).uint64(message.producersSeen);
                if (message.dataSourcesRegistered != null && Object.hasOwnProperty.call(message, "dataSourcesRegistered"))
                    writer.uint32(/* id 4, wireType 0 =*/32).uint32(message.dataSourcesRegistered);
                if (message.dataSourcesSeen != null && Object.hasOwnProperty.call(message, "dataSourcesSeen"))
                    writer.uint32(/* id 5, wireType 0 =*/40).uint64(message.dataSourcesSeen);
                if (message.tracingSessions != null && Object.hasOwnProperty.call(message, "tracingSessions"))
                    writer.uint32(/* id 6, wireType 0 =*/48).uint32(message.tracingSessions);
                if (message.totalBuffers != null && Object.hasOwnProperty.call(message, "totalBuffers"))
                    writer.uint32(/* id 7, wireType 0 =*/56).uint32(message.totalBuffers);
                if (message.chunksDiscarded != null && Object.hasOwnProperty.call(message, "chunksDiscarded"))
                    writer.uint32(/* id 8, wireType 0 =*/64).uint64(message.chunksDiscarded);
                if (message.patchesDiscarded != null && Object.hasOwnProperty.call(message, "patchesDiscarded"))
                    writer.uint32(/* id 9, wireType 0 =*/72).uint64(message.patchesDiscarded);
                if (message.invalidPackets != null && Object.hasOwnProperty.call(message, "invalidPackets"))
                    writer.uint32(/* id 10, wireType 0 =*/80).uint64(message.invalidPackets);
                if (message.filterStats != null && Object.hasOwnProperty.call(message, "filterStats"))
                    $root.perfetto.protos.TraceStats.FilterStats.encode(message.filterStats, writer.uint32(/* id 11, wireType 2 =*/90).fork()).ldelim();
                return writer;
            };

            /**
             * Encodes the specified TraceStats message, length delimited. Does not implicitly {@link perfetto.protos.TraceStats.verify|verify} messages.
             * @function encodeDelimited
             * @memberof perfetto.protos.TraceStats
             * @static
             * @param {perfetto.protos.ITraceStats} message TraceStats message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            TraceStats.encodeDelimited = function encodeDelimited(message, writer) {
                return this.encode(message, writer).ldelim();
            };

            /**
             * Decodes a TraceStats message from the specified reader or buffer.
             * @function decode
             * @memberof perfetto.protos.TraceStats
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @param {number} [length] Message length if known beforehand
             * @returns {perfetto.protos.TraceStats} TraceStats
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            TraceStats.decode = function decode(reader, length) {
                if (!(reader instanceof $Reader))
                    reader = $Reader.create(reader);
                var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.TraceStats();
                while (reader.pos < end) {
                    var tag = reader.uint32();
                    switch (tag >>> 3) {
                    case 1:
                        if (!(message.bufferStats && message.bufferStats.length))
                            message.bufferStats = [];
                        message.bufferStats.push($root.perfetto.protos.TraceStats.BufferStats.decode(reader, reader.uint32()));
                        break;
                    case 2:
                        message.producersConnected = reader.uint32();
                        break;
                    case 3:
                        message.producersSeen = reader.uint64();
                        break;
                    case 4:
                        message.dataSourcesRegistered = reader.uint32();
                        break;
                    case 5:
                        message.dataSourcesSeen = reader.uint64();
                        break;
                    case 6:
                        message.tracingSessions = reader.uint32();
                        break;
                    case 7:
                        message.totalBuffers = reader.uint32();
                        break;
                    case 8:
                        message.chunksDiscarded = reader.uint64();
                        break;
                    case 9:
                        message.patchesDiscarded = reader.uint64();
                        break;
                    case 10:
                        message.invalidPackets = reader.uint64();
                        break;
                    case 11:
                        message.filterStats = $root.perfetto.protos.TraceStats.FilterStats.decode(reader, reader.uint32());
                        break;
                    default:
                        reader.skipType(tag & 7);
                        break;
                    }
                }
                return message;
            };

            /**
             * Decodes a TraceStats message from the specified reader or buffer, length delimited.
             * @function decodeDelimited
             * @memberof perfetto.protos.TraceStats
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @returns {perfetto.protos.TraceStats} TraceStats
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            TraceStats.decodeDelimited = function decodeDelimited(reader) {
                if (!(reader instanceof $Reader))
                    reader = new $Reader(reader);
                return this.decode(reader, reader.uint32());
            };

            /**
             * Verifies a TraceStats message.
             * @function verify
             * @memberof perfetto.protos.TraceStats
             * @static
             * @param {Object.<string,*>} message Plain object to verify
             * @returns {string|null} `null` if valid, otherwise the reason why it is not
             */
            TraceStats.verify = function verify(message) {
                if (typeof message !== "object" || message === null)
                    return "object expected";
                if (message.bufferStats != null && message.hasOwnProperty("bufferStats")) {
                    if (!Array.isArray(message.bufferStats))
                        return "bufferStats: array expected";
                    for (var i = 0; i < message.bufferStats.length; ++i) {
                        var error = $root.perfetto.protos.TraceStats.BufferStats.verify(message.bufferStats[i]);
                        if (error)
                            return "bufferStats." + error;
                    }
                }
                if (message.producersConnected != null && message.hasOwnProperty("producersConnected"))
                    if (!$util.isInteger(message.producersConnected))
                        return "producersConnected: integer expected";
                if (message.producersSeen != null && message.hasOwnProperty("producersSeen"))
                    if (!$util.isInteger(message.producersSeen) && !(message.producersSeen && $util.isInteger(message.producersSeen.low) && $util.isInteger(message.producersSeen.high)))
                        return "producersSeen: integer|Long expected";
                if (message.dataSourcesRegistered != null && message.hasOwnProperty("dataSourcesRegistered"))
                    if (!$util.isInteger(message.dataSourcesRegistered))
                        return "dataSourcesRegistered: integer expected";
                if (message.dataSourcesSeen != null && message.hasOwnProperty("dataSourcesSeen"))
                    if (!$util.isInteger(message.dataSourcesSeen) && !(message.dataSourcesSeen && $util.isInteger(message.dataSourcesSeen.low) && $util.isInteger(message.dataSourcesSeen.high)))
                        return "dataSourcesSeen: integer|Long expected";
                if (message.tracingSessions != null && message.hasOwnProperty("tracingSessions"))
                    if (!$util.isInteger(message.tracingSessions))
                        return "tracingSessions: integer expected";
                if (message.totalBuffers != null && message.hasOwnProperty("totalBuffers"))
                    if (!$util.isInteger(message.totalBuffers))
                        return "totalBuffers: integer expected";
                if (message.chunksDiscarded != null && message.hasOwnProperty("chunksDiscarded"))
                    if (!$util.isInteger(message.chunksDiscarded) && !(message.chunksDiscarded && $util.isInteger(message.chunksDiscarded.low) && $util.isInteger(message.chunksDiscarded.high)))
                        return "chunksDiscarded: integer|Long expected";
                if (message.patchesDiscarded != null && message.hasOwnProperty("patchesDiscarded"))
                    if (!$util.isInteger(message.patchesDiscarded) && !(message.patchesDiscarded && $util.isInteger(message.patchesDiscarded.low) && $util.isInteger(message.patchesDiscarded.high)))
                        return "patchesDiscarded: integer|Long expected";
                if (message.invalidPackets != null && message.hasOwnProperty("invalidPackets"))
                    if (!$util.isInteger(message.invalidPackets) && !(message.invalidPackets && $util.isInteger(message.invalidPackets.low) && $util.isInteger(message.invalidPackets.high)))
                        return "invalidPackets: integer|Long expected";
                if (message.filterStats != null && message.hasOwnProperty("filterStats")) {
                    var error = $root.perfetto.protos.TraceStats.FilterStats.verify(message.filterStats);
                    if (error)
                        return "filterStats." + error;
                }
                return null;
            };

            /**
             * Creates a TraceStats message from a plain object. Also converts values to their respective internal types.
             * @function fromObject
             * @memberof perfetto.protos.TraceStats
             * @static
             * @param {Object.<string,*>} object Plain object
             * @returns {perfetto.protos.TraceStats} TraceStats
             */
            TraceStats.fromObject = function fromObject(object) {
                if (object instanceof $root.perfetto.protos.TraceStats)
                    return object;
                var message = new $root.perfetto.protos.TraceStats();
                if (object.bufferStats) {
                    if (!Array.isArray(object.bufferStats))
                        throw TypeError(".perfetto.protos.TraceStats.bufferStats: array expected");
                    message.bufferStats = [];
                    for (var i = 0; i < object.bufferStats.length; ++i) {
                        if (typeof object.bufferStats[i] !== "object")
                            throw TypeError(".perfetto.protos.TraceStats.bufferStats: object expected");
                        message.bufferStats[i] = $root.perfetto.protos.TraceStats.BufferStats.fromObject(object.bufferStats[i]);
                    }
                }
                if (object.producersConnected != null)
                    message.producersConnected = object.producersConnected >>> 0;
                if (object.producersSeen != null)
                    if ($util.Long)
                        (message.producersSeen = $util.Long.fromValue(object.producersSeen)).unsigned = true;
                    else if (typeof object.producersSeen === "string")
                        message.producersSeen = parseInt(object.producersSeen, 10);
                    else if (typeof object.producersSeen === "number")
                        message.producersSeen = object.producersSeen;
                    else if (typeof object.producersSeen === "object")
                        message.producersSeen = new $util.LongBits(object.producersSeen.low >>> 0, object.producersSeen.high >>> 0).toNumber(true);
                if (object.dataSourcesRegistered != null)
                    message.dataSourcesRegistered = object.dataSourcesRegistered >>> 0;
                if (object.dataSourcesSeen != null)
                    if ($util.Long)
                        (message.dataSourcesSeen = $util.Long.fromValue(object.dataSourcesSeen)).unsigned = true;
                    else if (typeof object.dataSourcesSeen === "string")
                        message.dataSourcesSeen = parseInt(object.dataSourcesSeen, 10);
                    else if (typeof object.dataSourcesSeen === "number")
                        message.dataSourcesSeen = object.dataSourcesSeen;
                    else if (typeof object.dataSourcesSeen === "object")
                        message.dataSourcesSeen = new $util.LongBits(object.dataSourcesSeen.low >>> 0, object.dataSourcesSeen.high >>> 0).toNumber(true);
                if (object.tracingSessions != null)
                    message.tracingSessions = object.tracingSessions >>> 0;
                if (object.totalBuffers != null)
                    message.totalBuffers = object.totalBuffers >>> 0;
                if (object.chunksDiscarded != null)
                    if ($util.Long)
                        (message.chunksDiscarded = $util.Long.fromValue(object.chunksDiscarded)).unsigned = true;
                    else if (typeof object.chunksDiscarded === "string")
                        message.chunksDiscarded = parseInt(object.chunksDiscarded, 10);
                    else if (typeof object.chunksDiscarded === "number")
                        message.chunksDiscarded = object.chunksDiscarded;
                    else if (typeof object.chunksDiscarded === "object")
                        message.chunksDiscarded = new $util.LongBits(object.chunksDiscarded.low >>> 0, object.chunksDiscarded.high >>> 0).toNumber(true);
                if (object.patchesDiscarded != null)
                    if ($util.Long)
                        (message.patchesDiscarded = $util.Long.fromValue(object.patchesDiscarded)).unsigned = true;
                    else if (typeof object.patchesDiscarded === "string")
                        message.patchesDiscarded = parseInt(object.patchesDiscarded, 10);
                    else if (typeof object.patchesDiscarded === "number")
                        message.patchesDiscarded = object.patchesDiscarded;
                    else if (typeof object.patchesDiscarded === "object")
                        message.patchesDiscarded = new $util.LongBits(object.patchesDiscarded.low >>> 0, object.patchesDiscarded.high >>> 0).toNumber(true);
                if (object.invalidPackets != null)
                    if ($util.Long)
                        (message.invalidPackets = $util.Long.fromValue(object.invalidPackets)).unsigned = true;
                    else if (typeof object.invalidPackets === "string")
                        message.invalidPackets = parseInt(object.invalidPackets, 10);
                    else if (typeof object.invalidPackets === "number")
                        message.invalidPackets = object.invalidPackets;
                    else if (typeof object.invalidPackets === "object")
                        message.invalidPackets = new $util.LongBits(object.invalidPackets.low >>> 0, object.invalidPackets.high >>> 0).toNumber(true);
                if (object.filterStats != null) {
                    if (typeof object.filterStats !== "object")
                        throw TypeError(".perfetto.protos.TraceStats.filterStats: object expected");
                    message.filterStats = $root.perfetto.protos.TraceStats.FilterStats.fromObject(object.filterStats);
                }
                return message;
            };

            /**
             * Creates a plain object from a TraceStats message. Also converts values to other types if specified.
             * @function toObject
             * @memberof perfetto.protos.TraceStats
             * @static
             * @param {perfetto.protos.TraceStats} message TraceStats
             * @param {$protobuf.IConversionOptions} [options] Conversion options
             * @returns {Object.<string,*>} Plain object
             */
            TraceStats.toObject = function toObject(message, options) {
                if (!options)
                    options = {};
                var object = {};
                if (options.arrays || options.defaults)
                    object.bufferStats = [];
                if (options.defaults) {
                    object.producersConnected = 0;
                    if ($util.Long) {
                        var long = new $util.Long(0, 0, true);
                        object.producersSeen = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
                    } else
                        object.producersSeen = options.longs === String ? "0" : 0;
                    object.dataSourcesRegistered = 0;
                    if ($util.Long) {
                        var long = new $util.Long(0, 0, true);
                        object.dataSourcesSeen = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
                    } else
                        object.dataSourcesSeen = options.longs === String ? "0" : 0;
                    object.tracingSessions = 0;
                    object.totalBuffers = 0;
                    if ($util.Long) {
                        var long = new $util.Long(0, 0, true);
                        object.chunksDiscarded = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
                    } else
                        object.chunksDiscarded = options.longs === String ? "0" : 0;
                    if ($util.Long) {
                        var long = new $util.Long(0, 0, true);
                        object.patchesDiscarded = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
                    } else
                        object.patchesDiscarded = options.longs === String ? "0" : 0;
                    if ($util.Long) {
                        var long = new $util.Long(0, 0, true);
                        object.invalidPackets = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
                    } else
                        object.invalidPackets = options.longs === String ? "0" : 0;
                    object.filterStats = null;
                }
                if (message.bufferStats && message.bufferStats.length) {
                    object.bufferStats = [];
                    for (var j = 0; j < message.bufferStats.length; ++j)
                        object.bufferStats[j] = $root.perfetto.protos.TraceStats.BufferStats.toObject(message.bufferStats[j], options);
                }
                if (message.producersConnected != null && message.hasOwnProperty("producersConnected"))
                    object.producersConnected = message.producersConnected;
                if (message.producersSeen != null && message.hasOwnProperty("producersSeen"))
                    if (typeof message.producersSeen === "number")
                        object.producersSeen = options.longs === String ? String(message.producersSeen) : message.producersSeen;
                    else
                        object.producersSeen = options.longs === String ? $util.Long.prototype.toString.call(message.producersSeen) : options.longs === Number ? new $util.LongBits(message.producersSeen.low >>> 0, message.producersSeen.high >>> 0).toNumber(true) : message.producersSeen;
                if (message.dataSourcesRegistered != null && message.hasOwnProperty("dataSourcesRegistered"))
                    object.dataSourcesRegistered = message.dataSourcesRegistered;
                if (message.dataSourcesSeen != null && message.hasOwnProperty("dataSourcesSeen"))
                    if (typeof message.dataSourcesSeen === "number")
                        object.dataSourcesSeen = options.longs === String ? String(message.dataSourcesSeen) : message.dataSourcesSeen;
                    else
                        object.dataSourcesSeen = options.longs === String ? $util.Long.prototype.toString.call(message.dataSourcesSeen) : options.longs === Number ? new $util.LongBits(message.dataSourcesSeen.low >>> 0, message.dataSourcesSeen.high >>> 0).toNumber(true) : message.dataSourcesSeen;
                if (message.tracingSessions != null && message.hasOwnProperty("tracingSessions"))
                    object.tracingSessions = message.tracingSessions;
                if (message.totalBuffers != null && message.hasOwnProperty("totalBuffers"))
                    object.totalBuffers = message.totalBuffers;
                if (message.chunksDiscarded != null && message.hasOwnProperty("chunksDiscarded"))
                    if (typeof message.chunksDiscarded === "number")
                        object.chunksDiscarded = options.longs === String ? String(message.chunksDiscarded) : message.chunksDiscarded;
                    else
                        object.chunksDiscarded = options.longs === String ? $util.Long.prototype.toString.call(message.chunksDiscarded) : options.longs === Number ? new $util.LongBits(message.chunksDiscarded.low >>> 0, message.chunksDiscarded.high >>> 0).toNumber(true) : message.chunksDiscarded;
                if (message.patchesDiscarded != null && message.hasOwnProperty("patchesDiscarded"))
                    if (typeof message.patchesDiscarded === "number")
                        object.patchesDiscarded = options.longs === String ? String(message.patchesDiscarded) : message.patchesDiscarded;
                    else
                        object.patchesDiscarded = options.longs === String ? $util.Long.prototype.toString.call(message.patchesDiscarded) : options.longs === Number ? new $util.LongBits(message.patchesDiscarded.low >>> 0, message.patchesDiscarded.high >>> 0).toNumber(true) : message.patchesDiscarded;
                if (message.invalidPackets != null && message.hasOwnProperty("invalidPackets"))
                    if (typeof message.invalidPackets === "number")
                        object.invalidPackets = options.longs === String ? String(message.invalidPackets) : message.invalidPackets;
                    else
                        object.invalidPackets = options.longs === String ? $util.Long.prototype.toString.call(message.invalidPackets) : options.longs === Number ? new $util.LongBits(message.invalidPackets.low >>> 0, message.invalidPackets.high >>> 0).toNumber(true) : message.invalidPackets;
                if (message.filterStats != null && message.hasOwnProperty("filterStats"))
                    object.filterStats = $root.perfetto.protos.TraceStats.FilterStats.toObject(message.filterStats, options);
                return object;
            };

            /**
             * Converts this TraceStats to JSON.
             * @function toJSON
             * @memberof perfetto.protos.TraceStats
             * @instance
             * @returns {Object.<string,*>} JSON object
             */
            TraceStats.prototype.toJSON = function toJSON() {
                return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
            };

            TraceStats.BufferStats = (function() {

                /**
                 * Properties of a BufferStats.
                 * @memberof perfetto.protos.TraceStats
                 * @interface IBufferStats
                 * @property {number|null} [bufferSize] BufferStats bufferSize
                 * @property {number|null} [bytesWritten] BufferStats bytesWritten
                 * @property {number|null} [bytesOverwritten] BufferStats bytesOverwritten
                 * @property {number|null} [bytesRead] BufferStats bytesRead
                 * @property {number|null} [paddingBytesWritten] BufferStats paddingBytesWritten
                 * @property {number|null} [paddingBytesCleared] BufferStats paddingBytesCleared
                 * @property {number|null} [chunksWritten] BufferStats chunksWritten
                 * @property {number|null} [chunksRewritten] BufferStats chunksRewritten
                 * @property {number|null} [chunksOverwritten] BufferStats chunksOverwritten
                 * @property {number|null} [chunksDiscarded] BufferStats chunksDiscarded
                 * @property {number|null} [chunksRead] BufferStats chunksRead
                 * @property {number|null} [chunksCommittedOutOfOrder] BufferStats chunksCommittedOutOfOrder
                 * @property {number|null} [writeWrapCount] BufferStats writeWrapCount
                 * @property {number|null} [patchesSucceeded] BufferStats patchesSucceeded
                 * @property {number|null} [patchesFailed] BufferStats patchesFailed
                 * @property {number|null} [readaheadsSucceeded] BufferStats readaheadsSucceeded
                 * @property {number|null} [readaheadsFailed] BufferStats readaheadsFailed
                 * @property {number|null} [abiViolations] BufferStats abiViolations
                 * @property {number|null} [traceWriterPacketLoss] BufferStats traceWriterPacketLoss
                 */

                /**
                 * Constructs a new BufferStats.
                 * @memberof perfetto.protos.TraceStats
                 * @classdesc Represents a BufferStats.
                 * @implements IBufferStats
                 * @constructor
                 * @param {perfetto.protos.TraceStats.IBufferStats=} [properties] Properties to set
                 */
                function BufferStats(properties) {
                    if (properties)
                        for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                            if (properties[keys[i]] != null)
                                this[keys[i]] = properties[keys[i]];
                }

                /**
                 * BufferStats bufferSize.
                 * @member {number} bufferSize
                 * @memberof perfetto.protos.TraceStats.BufferStats
                 * @instance
                 */
                BufferStats.prototype.bufferSize = $util.Long ? $util.Long.fromBits(0,0,true) : 0;

                /**
                 * BufferStats bytesWritten.
                 * @member {number} bytesWritten
                 * @memberof perfetto.protos.TraceStats.BufferStats
                 * @instance
                 */
                BufferStats.prototype.bytesWritten = $util.Long ? $util.Long.fromBits(0,0,true) : 0;

                /**
                 * BufferStats bytesOverwritten.
                 * @member {number} bytesOverwritten
                 * @memberof perfetto.protos.TraceStats.BufferStats
                 * @instance
                 */
                BufferStats.prototype.bytesOverwritten = $util.Long ? $util.Long.fromBits(0,0,true) : 0;

                /**
                 * BufferStats bytesRead.
                 * @member {number} bytesRead
                 * @memberof perfetto.protos.TraceStats.BufferStats
                 * @instance
                 */
                BufferStats.prototype.bytesRead = $util.Long ? $util.Long.fromBits(0,0,true) : 0;

                /**
                 * BufferStats paddingBytesWritten.
                 * @member {number} paddingBytesWritten
                 * @memberof perfetto.protos.TraceStats.BufferStats
                 * @instance
                 */
                BufferStats.prototype.paddingBytesWritten = $util.Long ? $util.Long.fromBits(0,0,true) : 0;

                /**
                 * BufferStats paddingBytesCleared.
                 * @member {number} paddingBytesCleared
                 * @memberof perfetto.protos.TraceStats.BufferStats
                 * @instance
                 */
                BufferStats.prototype.paddingBytesCleared = $util.Long ? $util.Long.fromBits(0,0,true) : 0;

                /**
                 * BufferStats chunksWritten.
                 * @member {number} chunksWritten
                 * @memberof perfetto.protos.TraceStats.BufferStats
                 * @instance
                 */
                BufferStats.prototype.chunksWritten = $util.Long ? $util.Long.fromBits(0,0,true) : 0;

                /**
                 * BufferStats chunksRewritten.
                 * @member {number} chunksRewritten
                 * @memberof perfetto.protos.TraceStats.BufferStats
                 * @instance
                 */
                BufferStats.prototype.chunksRewritten = $util.Long ? $util.Long.fromBits(0,0,true) : 0;

                /**
                 * BufferStats chunksOverwritten.
                 * @member {number} chunksOverwritten
                 * @memberof perfetto.protos.TraceStats.BufferStats
                 * @instance
                 */
                BufferStats.prototype.chunksOverwritten = $util.Long ? $util.Long.fromBits(0,0,true) : 0;

                /**
                 * BufferStats chunksDiscarded.
                 * @member {number} chunksDiscarded
                 * @memberof perfetto.protos.TraceStats.BufferStats
                 * @instance
                 */
                BufferStats.prototype.chunksDiscarded = $util.Long ? $util.Long.fromBits(0,0,true) : 0;

                /**
                 * BufferStats chunksRead.
                 * @member {number} chunksRead
                 * @memberof perfetto.protos.TraceStats.BufferStats
                 * @instance
                 */
                BufferStats.prototype.chunksRead = $util.Long ? $util.Long.fromBits(0,0,true) : 0;

                /**
                 * BufferStats chunksCommittedOutOfOrder.
                 * @member {number} chunksCommittedOutOfOrder
                 * @memberof perfetto.protos.TraceStats.BufferStats
                 * @instance
                 */
                BufferStats.prototype.chunksCommittedOutOfOrder = $util.Long ? $util.Long.fromBits(0,0,true) : 0;

                /**
                 * BufferStats writeWrapCount.
                 * @member {number} writeWrapCount
                 * @memberof perfetto.protos.TraceStats.BufferStats
                 * @instance
                 */
                BufferStats.prototype.writeWrapCount = $util.Long ? $util.Long.fromBits(0,0,true) : 0;

                /**
                 * BufferStats patchesSucceeded.
                 * @member {number} patchesSucceeded
                 * @memberof perfetto.protos.TraceStats.BufferStats
                 * @instance
                 */
                BufferStats.prototype.patchesSucceeded = $util.Long ? $util.Long.fromBits(0,0,true) : 0;

                /**
                 * BufferStats patchesFailed.
                 * @member {number} patchesFailed
                 * @memberof perfetto.protos.TraceStats.BufferStats
                 * @instance
                 */
                BufferStats.prototype.patchesFailed = $util.Long ? $util.Long.fromBits(0,0,true) : 0;

                /**
                 * BufferStats readaheadsSucceeded.
                 * @member {number} readaheadsSucceeded
                 * @memberof perfetto.protos.TraceStats.BufferStats
                 * @instance
                 */
                BufferStats.prototype.readaheadsSucceeded = $util.Long ? $util.Long.fromBits(0,0,true) : 0;

                /**
                 * BufferStats readaheadsFailed.
                 * @member {number} readaheadsFailed
                 * @memberof perfetto.protos.TraceStats.BufferStats
                 * @instance
                 */
                BufferStats.prototype.readaheadsFailed = $util.Long ? $util.Long.fromBits(0,0,true) : 0;

                /**
                 * BufferStats abiViolations.
                 * @member {number} abiViolations
                 * @memberof perfetto.protos.TraceStats.BufferStats
                 * @instance
                 */
                BufferStats.prototype.abiViolations = $util.Long ? $util.Long.fromBits(0,0,true) : 0;

                /**
                 * BufferStats traceWriterPacketLoss.
                 * @member {number} traceWriterPacketLoss
                 * @memberof perfetto.protos.TraceStats.BufferStats
                 * @instance
                 */
                BufferStats.prototype.traceWriterPacketLoss = $util.Long ? $util.Long.fromBits(0,0,true) : 0;

                /**
                 * Creates a new BufferStats instance using the specified properties.
                 * @function create
                 * @memberof perfetto.protos.TraceStats.BufferStats
                 * @static
                 * @param {perfetto.protos.TraceStats.IBufferStats=} [properties] Properties to set
                 * @returns {perfetto.protos.TraceStats.BufferStats} BufferStats instance
                 */
                BufferStats.create = function create(properties) {
                    return new BufferStats(properties);
                };

                /**
                 * Encodes the specified BufferStats message. Does not implicitly {@link perfetto.protos.TraceStats.BufferStats.verify|verify} messages.
                 * @function encode
                 * @memberof perfetto.protos.TraceStats.BufferStats
                 * @static
                 * @param {perfetto.protos.TraceStats.IBufferStats} message BufferStats message or plain object to encode
                 * @param {$protobuf.Writer} [writer] Writer to encode to
                 * @returns {$protobuf.Writer} Writer
                 */
                BufferStats.encode = function encode(message, writer) {
                    if (!writer)
                        writer = $Writer.create();
                    if (message.bytesWritten != null && Object.hasOwnProperty.call(message, "bytesWritten"))
                        writer.uint32(/* id 1, wireType 0 =*/8).uint64(message.bytesWritten);
                    if (message.chunksWritten != null && Object.hasOwnProperty.call(message, "chunksWritten"))
                        writer.uint32(/* id 2, wireType 0 =*/16).uint64(message.chunksWritten);
                    if (message.chunksOverwritten != null && Object.hasOwnProperty.call(message, "chunksOverwritten"))
                        writer.uint32(/* id 3, wireType 0 =*/24).uint64(message.chunksOverwritten);
                    if (message.writeWrapCount != null && Object.hasOwnProperty.call(message, "writeWrapCount"))
                        writer.uint32(/* id 4, wireType 0 =*/32).uint64(message.writeWrapCount);
                    if (message.patchesSucceeded != null && Object.hasOwnProperty.call(message, "patchesSucceeded"))
                        writer.uint32(/* id 5, wireType 0 =*/40).uint64(message.patchesSucceeded);
                    if (message.patchesFailed != null && Object.hasOwnProperty.call(message, "patchesFailed"))
                        writer.uint32(/* id 6, wireType 0 =*/48).uint64(message.patchesFailed);
                    if (message.readaheadsSucceeded != null && Object.hasOwnProperty.call(message, "readaheadsSucceeded"))
                        writer.uint32(/* id 7, wireType 0 =*/56).uint64(message.readaheadsSucceeded);
                    if (message.readaheadsFailed != null && Object.hasOwnProperty.call(message, "readaheadsFailed"))
                        writer.uint32(/* id 8, wireType 0 =*/64).uint64(message.readaheadsFailed);
                    if (message.abiViolations != null && Object.hasOwnProperty.call(message, "abiViolations"))
                        writer.uint32(/* id 9, wireType 0 =*/72).uint64(message.abiViolations);
                    if (message.chunksRewritten != null && Object.hasOwnProperty.call(message, "chunksRewritten"))
                        writer.uint32(/* id 10, wireType 0 =*/80).uint64(message.chunksRewritten);
                    if (message.chunksCommittedOutOfOrder != null && Object.hasOwnProperty.call(message, "chunksCommittedOutOfOrder"))
                        writer.uint32(/* id 11, wireType 0 =*/88).uint64(message.chunksCommittedOutOfOrder);
                    if (message.bufferSize != null && Object.hasOwnProperty.call(message, "bufferSize"))
                        writer.uint32(/* id 12, wireType 0 =*/96).uint64(message.bufferSize);
                    if (message.bytesOverwritten != null && Object.hasOwnProperty.call(message, "bytesOverwritten"))
                        writer.uint32(/* id 13, wireType 0 =*/104).uint64(message.bytesOverwritten);
                    if (message.bytesRead != null && Object.hasOwnProperty.call(message, "bytesRead"))
                        writer.uint32(/* id 14, wireType 0 =*/112).uint64(message.bytesRead);
                    if (message.paddingBytesWritten != null && Object.hasOwnProperty.call(message, "paddingBytesWritten"))
                        writer.uint32(/* id 15, wireType 0 =*/120).uint64(message.paddingBytesWritten);
                    if (message.paddingBytesCleared != null && Object.hasOwnProperty.call(message, "paddingBytesCleared"))
                        writer.uint32(/* id 16, wireType 0 =*/128).uint64(message.paddingBytesCleared);
                    if (message.chunksRead != null && Object.hasOwnProperty.call(message, "chunksRead"))
                        writer.uint32(/* id 17, wireType 0 =*/136).uint64(message.chunksRead);
                    if (message.chunksDiscarded != null && Object.hasOwnProperty.call(message, "chunksDiscarded"))
                        writer.uint32(/* id 18, wireType 0 =*/144).uint64(message.chunksDiscarded);
                    if (message.traceWriterPacketLoss != null && Object.hasOwnProperty.call(message, "traceWriterPacketLoss"))
                        writer.uint32(/* id 19, wireType 0 =*/152).uint64(message.traceWriterPacketLoss);
                    return writer;
                };

                /**
                 * Encodes the specified BufferStats message, length delimited. Does not implicitly {@link perfetto.protos.TraceStats.BufferStats.verify|verify} messages.
                 * @function encodeDelimited
                 * @memberof perfetto.protos.TraceStats.BufferStats
                 * @static
                 * @param {perfetto.protos.TraceStats.IBufferStats} message BufferStats message or plain object to encode
                 * @param {$protobuf.Writer} [writer] Writer to encode to
                 * @returns {$protobuf.Writer} Writer
                 */
                BufferStats.encodeDelimited = function encodeDelimited(message, writer) {
                    return this.encode(message, writer).ldelim();
                };

                /**
                 * Decodes a BufferStats message from the specified reader or buffer.
                 * @function decode
                 * @memberof perfetto.protos.TraceStats.BufferStats
                 * @static
                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                 * @param {number} [length] Message length if known beforehand
                 * @returns {perfetto.protos.TraceStats.BufferStats} BufferStats
                 * @throws {Error} If the payload is not a reader or valid buffer
                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
                 */
                BufferStats.decode = function decode(reader, length) {
                    if (!(reader instanceof $Reader))
                        reader = $Reader.create(reader);
                    var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.TraceStats.BufferStats();
                    while (reader.pos < end) {
                        var tag = reader.uint32();
                        switch (tag >>> 3) {
                        case 12:
                            message.bufferSize = reader.uint64();
                            break;
                        case 1:
                            message.bytesWritten = reader.uint64();
                            break;
                        case 13:
                            message.bytesOverwritten = reader.uint64();
                            break;
                        case 14:
                            message.bytesRead = reader.uint64();
                            break;
                        case 15:
                            message.paddingBytesWritten = reader.uint64();
                            break;
                        case 16:
                            message.paddingBytesCleared = reader.uint64();
                            break;
                        case 2:
                            message.chunksWritten = reader.uint64();
                            break;
                        case 10:
                            message.chunksRewritten = reader.uint64();
                            break;
                        case 3:
                            message.chunksOverwritten = reader.uint64();
                            break;
                        case 18:
                            message.chunksDiscarded = reader.uint64();
                            break;
                        case 17:
                            message.chunksRead = reader.uint64();
                            break;
                        case 11:
                            message.chunksCommittedOutOfOrder = reader.uint64();
                            break;
                        case 4:
                            message.writeWrapCount = reader.uint64();
                            break;
                        case 5:
                            message.patchesSucceeded = reader.uint64();
                            break;
                        case 6:
                            message.patchesFailed = reader.uint64();
                            break;
                        case 7:
                            message.readaheadsSucceeded = reader.uint64();
                            break;
                        case 8:
                            message.readaheadsFailed = reader.uint64();
                            break;
                        case 9:
                            message.abiViolations = reader.uint64();
                            break;
                        case 19:
                            message.traceWriterPacketLoss = reader.uint64();
                            break;
                        default:
                            reader.skipType(tag & 7);
                            break;
                        }
                    }
                    return message;
                };

                /**
                 * Decodes a BufferStats message from the specified reader or buffer, length delimited.
                 * @function decodeDelimited
                 * @memberof perfetto.protos.TraceStats.BufferStats
                 * @static
                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                 * @returns {perfetto.protos.TraceStats.BufferStats} BufferStats
                 * @throws {Error} If the payload is not a reader or valid buffer
                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
                 */
                BufferStats.decodeDelimited = function decodeDelimited(reader) {
                    if (!(reader instanceof $Reader))
                        reader = new $Reader(reader);
                    return this.decode(reader, reader.uint32());
                };

                /**
                 * Verifies a BufferStats message.
                 * @function verify
                 * @memberof perfetto.protos.TraceStats.BufferStats
                 * @static
                 * @param {Object.<string,*>} message Plain object to verify
                 * @returns {string|null} `null` if valid, otherwise the reason why it is not
                 */
                BufferStats.verify = function verify(message) {
                    if (typeof message !== "object" || message === null)
                        return "object expected";
                    if (message.bufferSize != null && message.hasOwnProperty("bufferSize"))
                        if (!$util.isInteger(message.bufferSize) && !(message.bufferSize && $util.isInteger(message.bufferSize.low) && $util.isInteger(message.bufferSize.high)))
                            return "bufferSize: integer|Long expected";
                    if (message.bytesWritten != null && message.hasOwnProperty("bytesWritten"))
                        if (!$util.isInteger(message.bytesWritten) && !(message.bytesWritten && $util.isInteger(message.bytesWritten.low) && $util.isInteger(message.bytesWritten.high)))
                            return "bytesWritten: integer|Long expected";
                    if (message.bytesOverwritten != null && message.hasOwnProperty("bytesOverwritten"))
                        if (!$util.isInteger(message.bytesOverwritten) && !(message.bytesOverwritten && $util.isInteger(message.bytesOverwritten.low) && $util.isInteger(message.bytesOverwritten.high)))
                            return "bytesOverwritten: integer|Long expected";
                    if (message.bytesRead != null && message.hasOwnProperty("bytesRead"))
                        if (!$util.isInteger(message.bytesRead) && !(message.bytesRead && $util.isInteger(message.bytesRead.low) && $util.isInteger(message.bytesRead.high)))
                            return "bytesRead: integer|Long expected";
                    if (message.paddingBytesWritten != null && message.hasOwnProperty("paddingBytesWritten"))
                        if (!$util.isInteger(message.paddingBytesWritten) && !(message.paddingBytesWritten && $util.isInteger(message.paddingBytesWritten.low) && $util.isInteger(message.paddingBytesWritten.high)))
                            return "paddingBytesWritten: integer|Long expected";
                    if (message.paddingBytesCleared != null && message.hasOwnProperty("paddingBytesCleared"))
                        if (!$util.isInteger(message.paddingBytesCleared) && !(message.paddingBytesCleared && $util.isInteger(message.paddingBytesCleared.low) && $util.isInteger(message.paddingBytesCleared.high)))
                            return "paddingBytesCleared: integer|Long expected";
                    if (message.chunksWritten != null && message.hasOwnProperty("chunksWritten"))
                        if (!$util.isInteger(message.chunksWritten) && !(message.chunksWritten && $util.isInteger(message.chunksWritten.low) && $util.isInteger(message.chunksWritten.high)))
                            return "chunksWritten: integer|Long expected";
                    if (message.chunksRewritten != null && message.hasOwnProperty("chunksRewritten"))
                        if (!$util.isInteger(message.chunksRewritten) && !(message.chunksRewritten && $util.isInteger(message.chunksRewritten.low) && $util.isInteger(message.chunksRewritten.high)))
                            return "chunksRewritten: integer|Long expected";
                    if (message.chunksOverwritten != null && message.hasOwnProperty("chunksOverwritten"))
                        if (!$util.isInteger(message.chunksOverwritten) && !(message.chunksOverwritten && $util.isInteger(message.chunksOverwritten.low) && $util.isInteger(message.chunksOverwritten.high)))
                            return "chunksOverwritten: integer|Long expected";
                    if (message.chunksDiscarded != null && message.hasOwnProperty("chunksDiscarded"))
                        if (!$util.isInteger(message.chunksDiscarded) && !(message.chunksDiscarded && $util.isInteger(message.chunksDiscarded.low) && $util.isInteger(message.chunksDiscarded.high)))
                            return "chunksDiscarded: integer|Long expected";
                    if (message.chunksRead != null && message.hasOwnProperty("chunksRead"))
                        if (!$util.isInteger(message.chunksRead) && !(message.chunksRead && $util.isInteger(message.chunksRead.low) && $util.isInteger(message.chunksRead.high)))
                            return "chunksRead: integer|Long expected";
                    if (message.chunksCommittedOutOfOrder != null && message.hasOwnProperty("chunksCommittedOutOfOrder"))
                        if (!$util.isInteger(message.chunksCommittedOutOfOrder) && !(message.chunksCommittedOutOfOrder && $util.isInteger(message.chunksCommittedOutOfOrder.low) && $util.isInteger(message.chunksCommittedOutOfOrder.high)))
                            return "chunksCommittedOutOfOrder: integer|Long expected";
                    if (message.writeWrapCount != null && message.hasOwnProperty("writeWrapCount"))
                        if (!$util.isInteger(message.writeWrapCount) && !(message.writeWrapCount && $util.isInteger(message.writeWrapCount.low) && $util.isInteger(message.writeWrapCount.high)))
                            return "writeWrapCount: integer|Long expected";
                    if (message.patchesSucceeded != null && message.hasOwnProperty("patchesSucceeded"))
                        if (!$util.isInteger(message.patchesSucceeded) && !(message.patchesSucceeded && $util.isInteger(message.patchesSucceeded.low) && $util.isInteger(message.patchesSucceeded.high)))
                            return "patchesSucceeded: integer|Long expected";
                    if (message.patchesFailed != null && message.hasOwnProperty("patchesFailed"))
                        if (!$util.isInteger(message.patchesFailed) && !(message.patchesFailed && $util.isInteger(message.patchesFailed.low) && $util.isInteger(message.patchesFailed.high)))
                            return "patchesFailed: integer|Long expected";
                    if (message.readaheadsSucceeded != null && message.hasOwnProperty("readaheadsSucceeded"))
                        if (!$util.isInteger(message.readaheadsSucceeded) && !(message.readaheadsSucceeded && $util.isInteger(message.readaheadsSucceeded.low) && $util.isInteger(message.readaheadsSucceeded.high)))
                            return "readaheadsSucceeded: integer|Long expected";
                    if (message.readaheadsFailed != null && message.hasOwnProperty("readaheadsFailed"))
                        if (!$util.isInteger(message.readaheadsFailed) && !(message.readaheadsFailed && $util.isInteger(message.readaheadsFailed.low) && $util.isInteger(message.readaheadsFailed.high)))
                            return "readaheadsFailed: integer|Long expected";
                    if (message.abiViolations != null && message.hasOwnProperty("abiViolations"))
                        if (!$util.isInteger(message.abiViolations) && !(message.abiViolations && $util.isInteger(message.abiViolations.low) && $util.isInteger(message.abiViolations.high)))
                            return "abiViolations: integer|Long expected";
                    if (message.traceWriterPacketLoss != null && message.hasOwnProperty("traceWriterPacketLoss"))
                        if (!$util.isInteger(message.traceWriterPacketLoss) && !(message.traceWriterPacketLoss && $util.isInteger(message.traceWriterPacketLoss.low) && $util.isInteger(message.traceWriterPacketLoss.high)))
                            return "traceWriterPacketLoss: integer|Long expected";
                    return null;
                };

                /**
                 * Creates a BufferStats message from a plain object. Also converts values to their respective internal types.
                 * @function fromObject
                 * @memberof perfetto.protos.TraceStats.BufferStats
                 * @static
                 * @param {Object.<string,*>} object Plain object
                 * @returns {perfetto.protos.TraceStats.BufferStats} BufferStats
                 */
                BufferStats.fromObject = function fromObject(object) {
                    if (object instanceof $root.perfetto.protos.TraceStats.BufferStats)
                        return object;
                    var message = new $root.perfetto.protos.TraceStats.BufferStats();
                    if (object.bufferSize != null)
                        if ($util.Long)
                            (message.bufferSize = $util.Long.fromValue(object.bufferSize)).unsigned = true;
                        else if (typeof object.bufferSize === "string")
                            message.bufferSize = parseInt(object.bufferSize, 10);
                        else if (typeof object.bufferSize === "number")
                            message.bufferSize = object.bufferSize;
                        else if (typeof object.bufferSize === "object")
                            message.bufferSize = new $util.LongBits(object.bufferSize.low >>> 0, object.bufferSize.high >>> 0).toNumber(true);
                    if (object.bytesWritten != null)
                        if ($util.Long)
                            (message.bytesWritten = $util.Long.fromValue(object.bytesWritten)).unsigned = true;
                        else if (typeof object.bytesWritten === "string")
                            message.bytesWritten = parseInt(object.bytesWritten, 10);
                        else if (typeof object.bytesWritten === "number")
                            message.bytesWritten = object.bytesWritten;
                        else if (typeof object.bytesWritten === "object")
                            message.bytesWritten = new $util.LongBits(object.bytesWritten.low >>> 0, object.bytesWritten.high >>> 0).toNumber(true);
                    if (object.bytesOverwritten != null)
                        if ($util.Long)
                            (message.bytesOverwritten = $util.Long.fromValue(object.bytesOverwritten)).unsigned = true;
                        else if (typeof object.bytesOverwritten === "string")
                            message.bytesOverwritten = parseInt(object.bytesOverwritten, 10);
                        else if (typeof object.bytesOverwritten === "number")
                            message.bytesOverwritten = object.bytesOverwritten;
                        else if (typeof object.bytesOverwritten === "object")
                            message.bytesOverwritten = new $util.LongBits(object.bytesOverwritten.low >>> 0, object.bytesOverwritten.high >>> 0).toNumber(true);
                    if (object.bytesRead != null)
                        if ($util.Long)
                            (message.bytesRead = $util.Long.fromValue(object.bytesRead)).unsigned = true;
                        else if (typeof object.bytesRead === "string")
                            message.bytesRead = parseInt(object.bytesRead, 10);
                        else if (typeof object.bytesRead === "number")
                            message.bytesRead = object.bytesRead;
                        else if (typeof object.bytesRead === "object")
                            message.bytesRead = new $util.LongBits(object.bytesRead.low >>> 0, object.bytesRead.high >>> 0).toNumber(true);
                    if (object.paddingBytesWritten != null)
                        if ($util.Long)
                            (message.paddingBytesWritten = $util.Long.fromValue(object.paddingBytesWritten)).unsigned = true;
                        else if (typeof object.paddingBytesWritten === "string")
                            message.paddingBytesWritten = parseInt(object.paddingBytesWritten, 10);
                        else if (typeof object.paddingBytesWritten === "number")
                            message.paddingBytesWritten = object.paddingBytesWritten;
                        else if (typeof object.paddingBytesWritten === "object")
                            message.paddingBytesWritten = new $util.LongBits(object.paddingBytesWritten.low >>> 0, object.paddingBytesWritten.high >>> 0).toNumber(true);
                    if (object.paddingBytesCleared != null)
                        if ($util.Long)
                            (message.paddingBytesCleared = $util.Long.fromValue(object.paddingBytesCleared)).unsigned = true;
                        else if (typeof object.paddingBytesCleared === "string")
                            message.paddingBytesCleared = parseInt(object.paddingBytesCleared, 10);
                        else if (typeof object.paddingBytesCleared === "number")
                            message.paddingBytesCleared = object.paddingBytesCleared;
                        else if (typeof object.paddingBytesCleared === "object")
                            message.paddingBytesCleared = new $util.LongBits(object.paddingBytesCleared.low >>> 0, object.paddingBytesCleared.high >>> 0).toNumber(true);
                    if (object.chunksWritten != null)
                        if ($util.Long)
                            (message.chunksWritten = $util.Long.fromValue(object.chunksWritten)).unsigned = true;
                        else if (typeof object.chunksWritten === "string")
                            message.chunksWritten = parseInt(object.chunksWritten, 10);
                        else if (typeof object.chunksWritten === "number")
                            message.chunksWritten = object.chunksWritten;
                        else if (typeof object.chunksWritten === "object")
                            message.chunksWritten = new $util.LongBits(object.chunksWritten.low >>> 0, object.chunksWritten.high >>> 0).toNumber(true);
                    if (object.chunksRewritten != null)
                        if ($util.Long)
                            (message.chunksRewritten = $util.Long.fromValue(object.chunksRewritten)).unsigned = true;
                        else if (typeof object.chunksRewritten === "string")
                            message.chunksRewritten = parseInt(object.chunksRewritten, 10);
                        else if (typeof object.chunksRewritten === "number")
                            message.chunksRewritten = object.chunksRewritten;
                        else if (typeof object.chunksRewritten === "object")
                            message.chunksRewritten = new $util.LongBits(object.chunksRewritten.low >>> 0, object.chunksRewritten.high >>> 0).toNumber(true);
                    if (object.chunksOverwritten != null)
                        if ($util.Long)
                            (message.chunksOverwritten = $util.Long.fromValue(object.chunksOverwritten)).unsigned = true;
                        else if (typeof object.chunksOverwritten === "string")
                            message.chunksOverwritten = parseInt(object.chunksOverwritten, 10);
                        else if (typeof object.chunksOverwritten === "number")
                            message.chunksOverwritten = object.chunksOverwritten;
                        else if (typeof object.chunksOverwritten === "object")
                            message.chunksOverwritten = new $util.LongBits(object.chunksOverwritten.low >>> 0, object.chunksOverwritten.high >>> 0).toNumber(true);
                    if (object.chunksDiscarded != null)
                        if ($util.Long)
                            (message.chunksDiscarded = $util.Long.fromValue(object.chunksDiscarded)).unsigned = true;
                        else if (typeof object.chunksDiscarded === "string")
                            message.chunksDiscarded = parseInt(object.chunksDiscarded, 10);
                        else if (typeof object.chunksDiscarded === "number")
                            message.chunksDiscarded = object.chunksDiscarded;
                        else if (typeof object.chunksDiscarded === "object")
                            message.chunksDiscarded = new $util.LongBits(object.chunksDiscarded.low >>> 0, object.chunksDiscarded.high >>> 0).toNumber(true);
                    if (object.chunksRead != null)
                        if ($util.Long)
                            (message.chunksRead = $util.Long.fromValue(object.chunksRead)).unsigned = true;
                        else if (typeof object.chunksRead === "string")
                            message.chunksRead = parseInt(object.chunksRead, 10);
                        else if (typeof object.chunksRead === "number")
                            message.chunksRead = object.chunksRead;
                        else if (typeof object.chunksRead === "object")
                            message.chunksRead = new $util.LongBits(object.chunksRead.low >>> 0, object.chunksRead.high >>> 0).toNumber(true);
                    if (object.chunksCommittedOutOfOrder != null)
                        if ($util.Long)
                            (message.chunksCommittedOutOfOrder = $util.Long.fromValue(object.chunksCommittedOutOfOrder)).unsigned = true;
                        else if (typeof object.chunksCommittedOutOfOrder === "string")
                            message.chunksCommittedOutOfOrder = parseInt(object.chunksCommittedOutOfOrder, 10);
                        else if (typeof object.chunksCommittedOutOfOrder === "number")
                            message.chunksCommittedOutOfOrder = object.chunksCommittedOutOfOrder;
                        else if (typeof object.chunksCommittedOutOfOrder === "object")
                            message.chunksCommittedOutOfOrder = new $util.LongBits(object.chunksCommittedOutOfOrder.low >>> 0, object.chunksCommittedOutOfOrder.high >>> 0).toNumber(true);
                    if (object.writeWrapCount != null)
                        if ($util.Long)
                            (message.writeWrapCount = $util.Long.fromValue(object.writeWrapCount)).unsigned = true;
                        else if (typeof object.writeWrapCount === "string")
                            message.writeWrapCount = parseInt(object.writeWrapCount, 10);
                        else if (typeof object.writeWrapCount === "number")
                            message.writeWrapCount = object.writeWrapCount;
                        else if (typeof object.writeWrapCount === "object")
                            message.writeWrapCount = new $util.LongBits(object.writeWrapCount.low >>> 0, object.writeWrapCount.high >>> 0).toNumber(true);
                    if (object.patchesSucceeded != null)
                        if ($util.Long)
                            (message.patchesSucceeded = $util.Long.fromValue(object.patchesSucceeded)).unsigned = true;
                        else if (typeof object.patchesSucceeded === "string")
                            message.patchesSucceeded = parseInt(object.patchesSucceeded, 10);
                        else if (typeof object.patchesSucceeded === "number")
                            message.patchesSucceeded = object.patchesSucceeded;
                        else if (typeof object.patchesSucceeded === "object")
                            message.patchesSucceeded = new $util.LongBits(object.patchesSucceeded.low >>> 0, object.patchesSucceeded.high >>> 0).toNumber(true);
                    if (object.patchesFailed != null)
                        if ($util.Long)
                            (message.patchesFailed = $util.Long.fromValue(object.patchesFailed)).unsigned = true;
                        else if (typeof object.patchesFailed === "string")
                            message.patchesFailed = parseInt(object.patchesFailed, 10);
                        else if (typeof object.patchesFailed === "number")
                            message.patchesFailed = object.patchesFailed;
                        else if (typeof object.patchesFailed === "object")
                            message.patchesFailed = new $util.LongBits(object.patchesFailed.low >>> 0, object.patchesFailed.high >>> 0).toNumber(true);
                    if (object.readaheadsSucceeded != null)
                        if ($util.Long)
                            (message.readaheadsSucceeded = $util.Long.fromValue(object.readaheadsSucceeded)).unsigned = true;
                        else if (typeof object.readaheadsSucceeded === "string")
                            message.readaheadsSucceeded = parseInt(object.readaheadsSucceeded, 10);
                        else if (typeof object.readaheadsSucceeded === "number")
                            message.readaheadsSucceeded = object.readaheadsSucceeded;
                        else if (typeof object.readaheadsSucceeded === "object")
                            message.readaheadsSucceeded = new $util.LongBits(object.readaheadsSucceeded.low >>> 0, object.readaheadsSucceeded.high >>> 0).toNumber(true);
                    if (object.readaheadsFailed != null)
                        if ($util.Long)
                            (message.readaheadsFailed = $util.Long.fromValue(object.readaheadsFailed)).unsigned = true;
                        else if (typeof object.readaheadsFailed === "string")
                            message.readaheadsFailed = parseInt(object.readaheadsFailed, 10);
                        else if (typeof object.readaheadsFailed === "number")
                            message.readaheadsFailed = object.readaheadsFailed;
                        else if (typeof object.readaheadsFailed === "object")
                            message.readaheadsFailed = new $util.LongBits(object.readaheadsFailed.low >>> 0, object.readaheadsFailed.high >>> 0).toNumber(true);
                    if (object.abiViolations != null)
                        if ($util.Long)
                            (message.abiViolations = $util.Long.fromValue(object.abiViolations)).unsigned = true;
                        else if (typeof object.abiViolations === "string")
                            message.abiViolations = parseInt(object.abiViolations, 10);
                        else if (typeof object.abiViolations === "number")
                            message.abiViolations = object.abiViolations;
                        else if (typeof object.abiViolations === "object")
                            message.abiViolations = new $util.LongBits(object.abiViolations.low >>> 0, object.abiViolations.high >>> 0).toNumber(true);
                    if (object.traceWriterPacketLoss != null)
                        if ($util.Long)
                            (message.traceWriterPacketLoss = $util.Long.fromValue(object.traceWriterPacketLoss)).unsigned = true;
                        else if (typeof object.traceWriterPacketLoss === "string")
                            message.traceWriterPacketLoss = parseInt(object.traceWriterPacketLoss, 10);
                        else if (typeof object.traceWriterPacketLoss === "number")
                            message.traceWriterPacketLoss = object.traceWriterPacketLoss;
                        else if (typeof object.traceWriterPacketLoss === "object")
                            message.traceWriterPacketLoss = new $util.LongBits(object.traceWriterPacketLoss.low >>> 0, object.traceWriterPacketLoss.high >>> 0).toNumber(true);
                    return message;
                };

                /**
                 * Creates a plain object from a BufferStats message. Also converts values to other types if specified.
                 * @function toObject
                 * @memberof perfetto.protos.TraceStats.BufferStats
                 * @static
                 * @param {perfetto.protos.TraceStats.BufferStats} message BufferStats
                 * @param {$protobuf.IConversionOptions} [options] Conversion options
                 * @returns {Object.<string,*>} Plain object
                 */
                BufferStats.toObject = function toObject(message, options) {
                    if (!options)
                        options = {};
                    var object = {};
                    if (options.defaults) {
                        if ($util.Long) {
                            var long = new $util.Long(0, 0, true);
                            object.bytesWritten = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
                        } else
                            object.bytesWritten = options.longs === String ? "0" : 0;
                        if ($util.Long) {
                            var long = new $util.Long(0, 0, true);
                            object.chunksWritten = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
                        } else
                            object.chunksWritten = options.longs === String ? "0" : 0;
                        if ($util.Long) {
                            var long = new $util.Long(0, 0, true);
                            object.chunksOverwritten = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
                        } else
                            object.chunksOverwritten = options.longs === String ? "0" : 0;
                        if ($util.Long) {
                            var long = new $util.Long(0, 0, true);
                            object.writeWrapCount = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
                        } else
                            object.writeWrapCount = options.longs === String ? "0" : 0;
                        if ($util.Long) {
                            var long = new $util.Long(0, 0, true);
                            object.patchesSucceeded = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
                        } else
                            object.patchesSucceeded = options.longs === String ? "0" : 0;
                        if ($util.Long) {
                            var long = new $util.Long(0, 0, true);
                            object.patchesFailed = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
                        } else
                            object.patchesFailed = options.longs === String ? "0" : 0;
                        if ($util.Long) {
                            var long = new $util.Long(0, 0, true);
                            object.readaheadsSucceeded = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
                        } else
                            object.readaheadsSucceeded = options.longs === String ? "0" : 0;
                        if ($util.Long) {
                            var long = new $util.Long(0, 0, true);
                            object.readaheadsFailed = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
                        } else
                            object.readaheadsFailed = options.longs === String ? "0" : 0;
                        if ($util.Long) {
                            var long = new $util.Long(0, 0, true);
                            object.abiViolations = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
                        } else
                            object.abiViolations = options.longs === String ? "0" : 0;
                        if ($util.Long) {
                            var long = new $util.Long(0, 0, true);
                            object.chunksRewritten = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
                        } else
                            object.chunksRewritten = options.longs === String ? "0" : 0;
                        if ($util.Long) {
                            var long = new $util.Long(0, 0, true);
                            object.chunksCommittedOutOfOrder = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
                        } else
                            object.chunksCommittedOutOfOrder = options.longs === String ? "0" : 0;
                        if ($util.Long) {
                            var long = new $util.Long(0, 0, true);
                            object.bufferSize = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
                        } else
                            object.bufferSize = options.longs === String ? "0" : 0;
                        if ($util.Long) {
                            var long = new $util.Long(0, 0, true);
                            object.bytesOverwritten = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
                        } else
                            object.bytesOverwritten = options.longs === String ? "0" : 0;
                        if ($util.Long) {
                            var long = new $util.Long(0, 0, true);
                            object.bytesRead = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
                        } else
                            object.bytesRead = options.longs === String ? "0" : 0;
                        if ($util.Long) {
                            var long = new $util.Long(0, 0, true);
                            object.paddingBytesWritten = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
                        } else
                            object.paddingBytesWritten = options.longs === String ? "0" : 0;
                        if ($util.Long) {
                            var long = new $util.Long(0, 0, true);
                            object.paddingBytesCleared = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
                        } else
                            object.paddingBytesCleared = options.longs === String ? "0" : 0;
                        if ($util.Long) {
                            var long = new $util.Long(0, 0, true);
                            object.chunksRead = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
                        } else
                            object.chunksRead = options.longs === String ? "0" : 0;
                        if ($util.Long) {
                            var long = new $util.Long(0, 0, true);
                            object.chunksDiscarded = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
                        } else
                            object.chunksDiscarded = options.longs === String ? "0" : 0;
                        if ($util.Long) {
                            var long = new $util.Long(0, 0, true);
                            object.traceWriterPacketLoss = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
                        } else
                            object.traceWriterPacketLoss = options.longs === String ? "0" : 0;
                    }
                    if (message.bytesWritten != null && message.hasOwnProperty("bytesWritten"))
                        if (typeof message.bytesWritten === "number")
                            object.bytesWritten = options.longs === String ? String(message.bytesWritten) : message.bytesWritten;
                        else
                            object.bytesWritten = options.longs === String ? $util.Long.prototype.toString.call(message.bytesWritten) : options.longs === Number ? new $util.LongBits(message.bytesWritten.low >>> 0, message.bytesWritten.high >>> 0).toNumber(true) : message.bytesWritten;
                    if (message.chunksWritten != null && message.hasOwnProperty("chunksWritten"))
                        if (typeof message.chunksWritten === "number")
                            object.chunksWritten = options.longs === String ? String(message.chunksWritten) : message.chunksWritten;
                        else
                            object.chunksWritten = options.longs === String ? $util.Long.prototype.toString.call(message.chunksWritten) : options.longs === Number ? new $util.LongBits(message.chunksWritten.low >>> 0, message.chunksWritten.high >>> 0).toNumber(true) : message.chunksWritten;
                    if (message.chunksOverwritten != null && message.hasOwnProperty("chunksOverwritten"))
                        if (typeof message.chunksOverwritten === "number")
                            object.chunksOverwritten = options.longs === String ? String(message.chunksOverwritten) : message.chunksOverwritten;
                        else
                            object.chunksOverwritten = options.longs === String ? $util.Long.prototype.toString.call(message.chunksOverwritten) : options.longs === Number ? new $util.LongBits(message.chunksOverwritten.low >>> 0, message.chunksOverwritten.high >>> 0).toNumber(true) : message.chunksOverwritten;
                    if (message.writeWrapCount != null && message.hasOwnProperty("writeWrapCount"))
                        if (typeof message.writeWrapCount === "number")
                            object.writeWrapCount = options.longs === String ? String(message.writeWrapCount) : message.writeWrapCount;
                        else
                            object.writeWrapCount = options.longs === String ? $util.Long.prototype.toString.call(message.writeWrapCount) : options.longs === Number ? new $util.LongBits(message.writeWrapCount.low >>> 0, message.writeWrapCount.high >>> 0).toNumber(true) : message.writeWrapCount;
                    if (message.patchesSucceeded != null && message.hasOwnProperty("patchesSucceeded"))
                        if (typeof message.patchesSucceeded === "number")
                            object.patchesSucceeded = options.longs === String ? String(message.patchesSucceeded) : message.patchesSucceeded;
                        else
                            object.patchesSucceeded = options.longs === String ? $util.Long.prototype.toString.call(message.patchesSucceeded) : options.longs === Number ? new $util.LongBits(message.patchesSucceeded.low >>> 0, message.patchesSucceeded.high >>> 0).toNumber(true) : message.patchesSucceeded;
                    if (message.patchesFailed != null && message.hasOwnProperty("patchesFailed"))
                        if (typeof message.patchesFailed === "number")
                            object.patchesFailed = options.longs === String ? String(message.patchesFailed) : message.patchesFailed;
                        else
                            object.patchesFailed = options.longs === String ? $util.Long.prototype.toString.call(message.patchesFailed) : options.longs === Number ? new $util.LongBits(message.patchesFailed.low >>> 0, message.patchesFailed.high >>> 0).toNumber(true) : message.patchesFailed;
                    if (message.readaheadsSucceeded != null && message.hasOwnProperty("readaheadsSucceeded"))
                        if (typeof message.readaheadsSucceeded === "number")
                            object.readaheadsSucceeded = options.longs === String ? String(message.readaheadsSucceeded) : message.readaheadsSucceeded;
                        else
                            object.readaheadsSucceeded = options.longs === String ? $util.Long.prototype.toString.call(message.readaheadsSucceeded) : options.longs === Number ? new $util.LongBits(message.readaheadsSucceeded.low >>> 0, message.readaheadsSucceeded.high >>> 0).toNumber(true) : message.readaheadsSucceeded;
                    if (message.readaheadsFailed != null && message.hasOwnProperty("readaheadsFailed"))
                        if (typeof message.readaheadsFailed === "number")
                            object.readaheadsFailed = options.longs === String ? String(message.readaheadsFailed) : message.readaheadsFailed;
                        else
                            object.readaheadsFailed = options.longs === String ? $util.Long.prototype.toString.call(message.readaheadsFailed) : options.longs === Number ? new $util.LongBits(message.readaheadsFailed.low >>> 0, message.readaheadsFailed.high >>> 0).toNumber(true) : message.readaheadsFailed;
                    if (message.abiViolations != null && message.hasOwnProperty("abiViolations"))
                        if (typeof message.abiViolations === "number")
                            object.abiViolations = options.longs === String ? String(message.abiViolations) : message.abiViolations;
                        else
                            object.abiViolations = options.longs === String ? $util.Long.prototype.toString.call(message.abiViolations) : options.longs === Number ? new $util.LongBits(message.abiViolations.low >>> 0, message.abiViolations.high >>> 0).toNumber(true) : message.abiViolations;
                    if (message.chunksRewritten != null && message.hasOwnProperty("chunksRewritten"))
                        if (typeof message.chunksRewritten === "number")
                            object.chunksRewritten = options.longs === String ? String(message.chunksRewritten) : message.chunksRewritten;
                        else
                            object.chunksRewritten = options.longs === String ? $util.Long.prototype.toString.call(message.chunksRewritten) : options.longs === Number ? new $util.LongBits(message.chunksRewritten.low >>> 0, message.chunksRewritten.high >>> 0).toNumber(true) : message.chunksRewritten;
                    if (message.chunksCommittedOutOfOrder != null && message.hasOwnProperty("chunksCommittedOutOfOrder"))
                        if (typeof message.chunksCommittedOutOfOrder === "number")
                            object.chunksCommittedOutOfOrder = options.longs === String ? String(message.chunksCommittedOutOfOrder) : message.chunksCommittedOutOfOrder;
                        else
                            object.chunksCommittedOutOfOrder = options.longs === String ? $util.Long.prototype.toString.call(message.chunksCommittedOutOfOrder) : options.longs === Number ? new $util.LongBits(message.chunksCommittedOutOfOrder.low >>> 0, message.chunksCommittedOutOfOrder.high >>> 0).toNumber(true) : message.chunksCommittedOutOfOrder;
                    if (message.bufferSize != null && message.hasOwnProperty("bufferSize"))
                        if (typeof message.bufferSize === "number")
                            object.bufferSize = options.longs === String ? String(message.bufferSize) : message.bufferSize;
                        else
                            object.bufferSize = options.longs === String ? $util.Long.prototype.toString.call(message.bufferSize) : options.longs === Number ? new $util.LongBits(message.bufferSize.low >>> 0, message.bufferSize.high >>> 0).toNumber(true) : message.bufferSize;
                    if (message.bytesOverwritten != null && message.hasOwnProperty("bytesOverwritten"))
                        if (typeof message.bytesOverwritten === "number")
                            object.bytesOverwritten = options.longs === String ? String(message.bytesOverwritten) : message.bytesOverwritten;
                        else
                            object.bytesOverwritten = options.longs === String ? $util.Long.prototype.toString.call(message.bytesOverwritten) : options.longs === Number ? new $util.LongBits(message.bytesOverwritten.low >>> 0, message.bytesOverwritten.high >>> 0).toNumber(true) : message.bytesOverwritten;
                    if (message.bytesRead != null && message.hasOwnProperty("bytesRead"))
                        if (typeof message.bytesRead === "number")
                            object.bytesRead = options.longs === String ? String(message.bytesRead) : message.bytesRead;
                        else
                            object.bytesRead = options.longs === String ? $util.Long.prototype.toString.call(message.bytesRead) : options.longs === Number ? new $util.LongBits(message.bytesRead.low >>> 0, message.bytesRead.high >>> 0).toNumber(true) : message.bytesRead;
                    if (message.paddingBytesWritten != null && message.hasOwnProperty("paddingBytesWritten"))
                        if (typeof message.paddingBytesWritten === "number")
                            object.paddingBytesWritten = options.longs === String ? String(message.paddingBytesWritten) : message.paddingBytesWritten;
                        else
                            object.paddingBytesWritten = options.longs === String ? $util.Long.prototype.toString.call(message.paddingBytesWritten) : options.longs === Number ? new $util.LongBits(message.paddingBytesWritten.low >>> 0, message.paddingBytesWritten.high >>> 0).toNumber(true) : message.paddingBytesWritten;
                    if (message.paddingBytesCleared != null && message.hasOwnProperty("paddingBytesCleared"))
                        if (typeof message.paddingBytesCleared === "number")
                            object.paddingBytesCleared = options.longs === String ? String(message.paddingBytesCleared) : message.paddingBytesCleared;
                        else
                            object.paddingBytesCleared = options.longs === String ? $util.Long.prototype.toString.call(message.paddingBytesCleared) : options.longs === Number ? new $util.LongBits(message.paddingBytesCleared.low >>> 0, message.paddingBytesCleared.high >>> 0).toNumber(true) : message.paddingBytesCleared;
                    if (message.chunksRead != null && message.hasOwnProperty("chunksRead"))
                        if (typeof message.chunksRead === "number")
                            object.chunksRead = options.longs === String ? String(message.chunksRead) : message.chunksRead;
                        else
                            object.chunksRead = options.longs === String ? $util.Long.prototype.toString.call(message.chunksRead) : options.longs === Number ? new $util.LongBits(message.chunksRead.low >>> 0, message.chunksRead.high >>> 0).toNumber(true) : message.chunksRead;
                    if (message.chunksDiscarded != null && message.hasOwnProperty("chunksDiscarded"))
                        if (typeof message.chunksDiscarded === "number")
                            object.chunksDiscarded = options.longs === String ? String(message.chunksDiscarded) : message.chunksDiscarded;
                        else
                            object.chunksDiscarded = options.longs === String ? $util.Long.prototype.toString.call(message.chunksDiscarded) : options.longs === Number ? new $util.LongBits(message.chunksDiscarded.low >>> 0, message.chunksDiscarded.high >>> 0).toNumber(true) : message.chunksDiscarded;
                    if (message.traceWriterPacketLoss != null && message.hasOwnProperty("traceWriterPacketLoss"))
                        if (typeof message.traceWriterPacketLoss === "number")
                            object.traceWriterPacketLoss = options.longs === String ? String(message.traceWriterPacketLoss) : message.traceWriterPacketLoss;
                        else
                            object.traceWriterPacketLoss = options.longs === String ? $util.Long.prototype.toString.call(message.traceWriterPacketLoss) : options.longs === Number ? new $util.LongBits(message.traceWriterPacketLoss.low >>> 0, message.traceWriterPacketLoss.high >>> 0).toNumber(true) : message.traceWriterPacketLoss;
                    return object;
                };

                /**
                 * Converts this BufferStats to JSON.
                 * @function toJSON
                 * @memberof perfetto.protos.TraceStats.BufferStats
                 * @instance
                 * @returns {Object.<string,*>} JSON object
                 */
                BufferStats.prototype.toJSON = function toJSON() {
                    return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
                };

                return BufferStats;
            })();

            TraceStats.FilterStats = (function() {

                /**
                 * Properties of a FilterStats.
                 * @memberof perfetto.protos.TraceStats
                 * @interface IFilterStats
                 * @property {number|null} [inputPackets] FilterStats inputPackets
                 * @property {number|null} [inputBytes] FilterStats inputBytes
                 * @property {number|null} [outputBytes] FilterStats outputBytes
                 * @property {number|null} [errors] FilterStats errors
                 */

                /**
                 * Constructs a new FilterStats.
                 * @memberof perfetto.protos.TraceStats
                 * @classdesc Represents a FilterStats.
                 * @implements IFilterStats
                 * @constructor
                 * @param {perfetto.protos.TraceStats.IFilterStats=} [properties] Properties to set
                 */
                function FilterStats(properties) {
                    if (properties)
                        for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                            if (properties[keys[i]] != null)
                                this[keys[i]] = properties[keys[i]];
                }

                /**
                 * FilterStats inputPackets.
                 * @member {number} inputPackets
                 * @memberof perfetto.protos.TraceStats.FilterStats
                 * @instance
                 */
                FilterStats.prototype.inputPackets = $util.Long ? $util.Long.fromBits(0,0,true) : 0;

                /**
                 * FilterStats inputBytes.
                 * @member {number} inputBytes
                 * @memberof perfetto.protos.TraceStats.FilterStats
                 * @instance
                 */
                FilterStats.prototype.inputBytes = $util.Long ? $util.Long.fromBits(0,0,true) : 0;

                /**
                 * FilterStats outputBytes.
                 * @member {number} outputBytes
                 * @memberof perfetto.protos.TraceStats.FilterStats
                 * @instance
                 */
                FilterStats.prototype.outputBytes = $util.Long ? $util.Long.fromBits(0,0,true) : 0;

                /**
                 * FilterStats errors.
                 * @member {number} errors
                 * @memberof perfetto.protos.TraceStats.FilterStats
                 * @instance
                 */
                FilterStats.prototype.errors = $util.Long ? $util.Long.fromBits(0,0,true) : 0;

                /**
                 * Creates a new FilterStats instance using the specified properties.
                 * @function create
                 * @memberof perfetto.protos.TraceStats.FilterStats
                 * @static
                 * @param {perfetto.protos.TraceStats.IFilterStats=} [properties] Properties to set
                 * @returns {perfetto.protos.TraceStats.FilterStats} FilterStats instance
                 */
                FilterStats.create = function create(properties) {
                    return new FilterStats(properties);
                };

                /**
                 * Encodes the specified FilterStats message. Does not implicitly {@link perfetto.protos.TraceStats.FilterStats.verify|verify} messages.
                 * @function encode
                 * @memberof perfetto.protos.TraceStats.FilterStats
                 * @static
                 * @param {perfetto.protos.TraceStats.IFilterStats} message FilterStats message or plain object to encode
                 * @param {$protobuf.Writer} [writer] Writer to encode to
                 * @returns {$protobuf.Writer} Writer
                 */
                FilterStats.encode = function encode(message, writer) {
                    if (!writer)
                        writer = $Writer.create();
                    if (message.inputPackets != null && Object.hasOwnProperty.call(message, "inputPackets"))
                        writer.uint32(/* id 1, wireType 0 =*/8).uint64(message.inputPackets);
                    if (message.inputBytes != null && Object.hasOwnProperty.call(message, "inputBytes"))
                        writer.uint32(/* id 2, wireType 0 =*/16).uint64(message.inputBytes);
                    if (message.outputBytes != null && Object.hasOwnProperty.call(message, "outputBytes"))
                        writer.uint32(/* id 3, wireType 0 =*/24).uint64(message.outputBytes);
                    if (message.errors != null && Object.hasOwnProperty.call(message, "errors"))
                        writer.uint32(/* id 4, wireType 0 =*/32).uint64(message.errors);
                    return writer;
                };

                /**
                 * Encodes the specified FilterStats message, length delimited. Does not implicitly {@link perfetto.protos.TraceStats.FilterStats.verify|verify} messages.
                 * @function encodeDelimited
                 * @memberof perfetto.protos.TraceStats.FilterStats
                 * @static
                 * @param {perfetto.protos.TraceStats.IFilterStats} message FilterStats message or plain object to encode
                 * @param {$protobuf.Writer} [writer] Writer to encode to
                 * @returns {$protobuf.Writer} Writer
                 */
                FilterStats.encodeDelimited = function encodeDelimited(message, writer) {
                    return this.encode(message, writer).ldelim();
                };

                /**
                 * Decodes a FilterStats message from the specified reader or buffer.
                 * @function decode
                 * @memberof perfetto.protos.TraceStats.FilterStats
                 * @static
                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                 * @param {number} [length] Message length if known beforehand
                 * @returns {perfetto.protos.TraceStats.FilterStats} FilterStats
                 * @throws {Error} If the payload is not a reader or valid buffer
                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
                 */
                FilterStats.decode = function decode(reader, length) {
                    if (!(reader instanceof $Reader))
                        reader = $Reader.create(reader);
                    var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.TraceStats.FilterStats();
                    while (reader.pos < end) {
                        var tag = reader.uint32();
                        switch (tag >>> 3) {
                        case 1:
                            message.inputPackets = reader.uint64();
                            break;
                        case 2:
                            message.inputBytes = reader.uint64();
                            break;
                        case 3:
                            message.outputBytes = reader.uint64();
                            break;
                        case 4:
                            message.errors = reader.uint64();
                            break;
                        default:
                            reader.skipType(tag & 7);
                            break;
                        }
                    }
                    return message;
                };

                /**
                 * Decodes a FilterStats message from the specified reader or buffer, length delimited.
                 * @function decodeDelimited
                 * @memberof perfetto.protos.TraceStats.FilterStats
                 * @static
                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                 * @returns {perfetto.protos.TraceStats.FilterStats} FilterStats
                 * @throws {Error} If the payload is not a reader or valid buffer
                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
                 */
                FilterStats.decodeDelimited = function decodeDelimited(reader) {
                    if (!(reader instanceof $Reader))
                        reader = new $Reader(reader);
                    return this.decode(reader, reader.uint32());
                };

                /**
                 * Verifies a FilterStats message.
                 * @function verify
                 * @memberof perfetto.protos.TraceStats.FilterStats
                 * @static
                 * @param {Object.<string,*>} message Plain object to verify
                 * @returns {string|null} `null` if valid, otherwise the reason why it is not
                 */
                FilterStats.verify = function verify(message) {
                    if (typeof message !== "object" || message === null)
                        return "object expected";
                    if (message.inputPackets != null && message.hasOwnProperty("inputPackets"))
                        if (!$util.isInteger(message.inputPackets) && !(message.inputPackets && $util.isInteger(message.inputPackets.low) && $util.isInteger(message.inputPackets.high)))
                            return "inputPackets: integer|Long expected";
                    if (message.inputBytes != null && message.hasOwnProperty("inputBytes"))
                        if (!$util.isInteger(message.inputBytes) && !(message.inputBytes && $util.isInteger(message.inputBytes.low) && $util.isInteger(message.inputBytes.high)))
                            return "inputBytes: integer|Long expected";
                    if (message.outputBytes != null && message.hasOwnProperty("outputBytes"))
                        if (!$util.isInteger(message.outputBytes) && !(message.outputBytes && $util.isInteger(message.outputBytes.low) && $util.isInteger(message.outputBytes.high)))
                            return "outputBytes: integer|Long expected";
                    if (message.errors != null && message.hasOwnProperty("errors"))
                        if (!$util.isInteger(message.errors) && !(message.errors && $util.isInteger(message.errors.low) && $util.isInteger(message.errors.high)))
                            return "errors: integer|Long expected";
                    return null;
                };

                /**
                 * Creates a FilterStats message from a plain object. Also converts values to their respective internal types.
                 * @function fromObject
                 * @memberof perfetto.protos.TraceStats.FilterStats
                 * @static
                 * @param {Object.<string,*>} object Plain object
                 * @returns {perfetto.protos.TraceStats.FilterStats} FilterStats
                 */
                FilterStats.fromObject = function fromObject(object) {
                    if (object instanceof $root.perfetto.protos.TraceStats.FilterStats)
                        return object;
                    var message = new $root.perfetto.protos.TraceStats.FilterStats();
                    if (object.inputPackets != null)
                        if ($util.Long)
                            (message.inputPackets = $util.Long.fromValue(object.inputPackets)).unsigned = true;
                        else if (typeof object.inputPackets === "string")
                            message.inputPackets = parseInt(object.inputPackets, 10);
                        else if (typeof object.inputPackets === "number")
                            message.inputPackets = object.inputPackets;
                        else if (typeof object.inputPackets === "object")
                            message.inputPackets = new $util.LongBits(object.inputPackets.low >>> 0, object.inputPackets.high >>> 0).toNumber(true);
                    if (object.inputBytes != null)
                        if ($util.Long)
                            (message.inputBytes = $util.Long.fromValue(object.inputBytes)).unsigned = true;
                        else if (typeof object.inputBytes === "string")
                            message.inputBytes = parseInt(object.inputBytes, 10);
                        else if (typeof object.inputBytes === "number")
                            message.inputBytes = object.inputBytes;
                        else if (typeof object.inputBytes === "object")
                            message.inputBytes = new $util.LongBits(object.inputBytes.low >>> 0, object.inputBytes.high >>> 0).toNumber(true);
                    if (object.outputBytes != null)
                        if ($util.Long)
                            (message.outputBytes = $util.Long.fromValue(object.outputBytes)).unsigned = true;
                        else if (typeof object.outputBytes === "string")
                            message.outputBytes = parseInt(object.outputBytes, 10);
                        else if (typeof object.outputBytes === "number")
                            message.outputBytes = object.outputBytes;
                        else if (typeof object.outputBytes === "object")
                            message.outputBytes = new $util.LongBits(object.outputBytes.low >>> 0, object.outputBytes.high >>> 0).toNumber(true);
                    if (object.errors != null)
                        if ($util.Long)
                            (message.errors = $util.Long.fromValue(object.errors)).unsigned = true;
                        else if (typeof object.errors === "string")
                            message.errors = parseInt(object.errors, 10);
                        else if (typeof object.errors === "number")
                            message.errors = object.errors;
                        else if (typeof object.errors === "object")
                            message.errors = new $util.LongBits(object.errors.low >>> 0, object.errors.high >>> 0).toNumber(true);
                    return message;
                };

                /**
                 * Creates a plain object from a FilterStats message. Also converts values to other types if specified.
                 * @function toObject
                 * @memberof perfetto.protos.TraceStats.FilterStats
                 * @static
                 * @param {perfetto.protos.TraceStats.FilterStats} message FilterStats
                 * @param {$protobuf.IConversionOptions} [options] Conversion options
                 * @returns {Object.<string,*>} Plain object
                 */
                FilterStats.toObject = function toObject(message, options) {
                    if (!options)
                        options = {};
                    var object = {};
                    if (options.defaults) {
                        if ($util.Long) {
                            var long = new $util.Long(0, 0, true);
                            object.inputPackets = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
                        } else
                            object.inputPackets = options.longs === String ? "0" : 0;
                        if ($util.Long) {
                            var long = new $util.Long(0, 0, true);
                            object.inputBytes = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
                        } else
                            object.inputBytes = options.longs === String ? "0" : 0;
                        if ($util.Long) {
                            var long = new $util.Long(0, 0, true);
                            object.outputBytes = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
                        } else
                            object.outputBytes = options.longs === String ? "0" : 0;
                        if ($util.Long) {
                            var long = new $util.Long(0, 0, true);
                            object.errors = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
                        } else
                            object.errors = options.longs === String ? "0" : 0;
                    }
                    if (message.inputPackets != null && message.hasOwnProperty("inputPackets"))
                        if (typeof message.inputPackets === "number")
                            object.inputPackets = options.longs === String ? String(message.inputPackets) : message.inputPackets;
                        else
                            object.inputPackets = options.longs === String ? $util.Long.prototype.toString.call(message.inputPackets) : options.longs === Number ? new $util.LongBits(message.inputPackets.low >>> 0, message.inputPackets.high >>> 0).toNumber(true) : message.inputPackets;
                    if (message.inputBytes != null && message.hasOwnProperty("inputBytes"))
                        if (typeof message.inputBytes === "number")
                            object.inputBytes = options.longs === String ? String(message.inputBytes) : message.inputBytes;
                        else
                            object.inputBytes = options.longs === String ? $util.Long.prototype.toString.call(message.inputBytes) : options.longs === Number ? new $util.LongBits(message.inputBytes.low >>> 0, message.inputBytes.high >>> 0).toNumber(true) : message.inputBytes;
                    if (message.outputBytes != null && message.hasOwnProperty("outputBytes"))
                        if (typeof message.outputBytes === "number")
                            object.outputBytes = options.longs === String ? String(message.outputBytes) : message.outputBytes;
                        else
                            object.outputBytes = options.longs === String ? $util.Long.prototype.toString.call(message.outputBytes) : options.longs === Number ? new $util.LongBits(message.outputBytes.low >>> 0, message.outputBytes.high >>> 0).toNumber(true) : message.outputBytes;
                    if (message.errors != null && message.hasOwnProperty("errors"))
                        if (typeof message.errors === "number")
                            object.errors = options.longs === String ? String(message.errors) : message.errors;
                        else
                            object.errors = options.longs === String ? $util.Long.prototype.toString.call(message.errors) : options.longs === Number ? new $util.LongBits(message.errors.low >>> 0, message.errors.high >>> 0).toNumber(true) : message.errors;
                    return object;
                };

                /**
                 * Converts this FilterStats to JSON.
                 * @function toJSON
                 * @memberof perfetto.protos.TraceStats.FilterStats
                 * @instance
                 * @returns {Object.<string,*>} JSON object
                 */
                FilterStats.prototype.toJSON = function toJSON() {
                    return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
                };

                return FilterStats;
            })();

            return TraceStats;
        })();

        protos.TracingServiceCapabilities = (function() {

            /**
             * Properties of a TracingServiceCapabilities.
             * @memberof perfetto.protos
             * @interface ITracingServiceCapabilities
             * @property {boolean|null} [hasQueryCapabilities] TracingServiceCapabilities hasQueryCapabilities
             * @property {Array.<perfetto.protos.ObservableEvents.Type>|null} [observableEvents] TracingServiceCapabilities observableEvents
             * @property {boolean|null} [hasTraceConfigOutputPath] TracingServiceCapabilities hasTraceConfigOutputPath
             */

            /**
             * Constructs a new TracingServiceCapabilities.
             * @memberof perfetto.protos
             * @classdesc Represents a TracingServiceCapabilities.
             * @implements ITracingServiceCapabilities
             * @constructor
             * @param {perfetto.protos.ITracingServiceCapabilities=} [properties] Properties to set
             */
            function TracingServiceCapabilities(properties) {
                this.observableEvents = [];
                if (properties)
                    for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                        if (properties[keys[i]] != null)
                            this[keys[i]] = properties[keys[i]];
            }

            /**
             * TracingServiceCapabilities hasQueryCapabilities.
             * @member {boolean} hasQueryCapabilities
             * @memberof perfetto.protos.TracingServiceCapabilities
             * @instance
             */
            TracingServiceCapabilities.prototype.hasQueryCapabilities = false;

            /**
             * TracingServiceCapabilities observableEvents.
             * @member {Array.<perfetto.protos.ObservableEvents.Type>} observableEvents
             * @memberof perfetto.protos.TracingServiceCapabilities
             * @instance
             */
            TracingServiceCapabilities.prototype.observableEvents = $util.emptyArray;

            /**
             * TracingServiceCapabilities hasTraceConfigOutputPath.
             * @member {boolean} hasTraceConfigOutputPath
             * @memberof perfetto.protos.TracingServiceCapabilities
             * @instance
             */
            TracingServiceCapabilities.prototype.hasTraceConfigOutputPath = false;

            /**
             * Creates a new TracingServiceCapabilities instance using the specified properties.
             * @function create
             * @memberof perfetto.protos.TracingServiceCapabilities
             * @static
             * @param {perfetto.protos.ITracingServiceCapabilities=} [properties] Properties to set
             * @returns {perfetto.protos.TracingServiceCapabilities} TracingServiceCapabilities instance
             */
            TracingServiceCapabilities.create = function create(properties) {
                return new TracingServiceCapabilities(properties);
            };

            /**
             * Encodes the specified TracingServiceCapabilities message. Does not implicitly {@link perfetto.protos.TracingServiceCapabilities.verify|verify} messages.
             * @function encode
             * @memberof perfetto.protos.TracingServiceCapabilities
             * @static
             * @param {perfetto.protos.ITracingServiceCapabilities} message TracingServiceCapabilities message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            TracingServiceCapabilities.encode = function encode(message, writer) {
                if (!writer)
                    writer = $Writer.create();
                if (message.hasQueryCapabilities != null && Object.hasOwnProperty.call(message, "hasQueryCapabilities"))
                    writer.uint32(/* id 1, wireType 0 =*/8).bool(message.hasQueryCapabilities);
                if (message.observableEvents != null && message.observableEvents.length)
                    for (var i = 0; i < message.observableEvents.length; ++i)
                        writer.uint32(/* id 2, wireType 0 =*/16).int32(message.observableEvents[i]);
                if (message.hasTraceConfigOutputPath != null && Object.hasOwnProperty.call(message, "hasTraceConfigOutputPath"))
                    writer.uint32(/* id 3, wireType 0 =*/24).bool(message.hasTraceConfigOutputPath);
                return writer;
            };

            /**
             * Encodes the specified TracingServiceCapabilities message, length delimited. Does not implicitly {@link perfetto.protos.TracingServiceCapabilities.verify|verify} messages.
             * @function encodeDelimited
             * @memberof perfetto.protos.TracingServiceCapabilities
             * @static
             * @param {perfetto.protos.ITracingServiceCapabilities} message TracingServiceCapabilities message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            TracingServiceCapabilities.encodeDelimited = function encodeDelimited(message, writer) {
                return this.encode(message, writer).ldelim();
            };

            /**
             * Decodes a TracingServiceCapabilities message from the specified reader or buffer.
             * @function decode
             * @memberof perfetto.protos.TracingServiceCapabilities
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @param {number} [length] Message length if known beforehand
             * @returns {perfetto.protos.TracingServiceCapabilities} TracingServiceCapabilities
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            TracingServiceCapabilities.decode = function decode(reader, length) {
                if (!(reader instanceof $Reader))
                    reader = $Reader.create(reader);
                var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.TracingServiceCapabilities();
                while (reader.pos < end) {
                    var tag = reader.uint32();
                    switch (tag >>> 3) {
                    case 1:
                        message.hasQueryCapabilities = reader.bool();
                        break;
                    case 2:
                        if (!(message.observableEvents && message.observableEvents.length))
                            message.observableEvents = [];
                        if ((tag & 7) === 2) {
                            var end2 = reader.uint32() + reader.pos;
                            while (reader.pos < end2)
                                message.observableEvents.push(reader.int32());
                        } else
                            message.observableEvents.push(reader.int32());
                        break;
                    case 3:
                        message.hasTraceConfigOutputPath = reader.bool();
                        break;
                    default:
                        reader.skipType(tag & 7);
                        break;
                    }
                }
                return message;
            };

            /**
             * Decodes a TracingServiceCapabilities message from the specified reader or buffer, length delimited.
             * @function decodeDelimited
             * @memberof perfetto.protos.TracingServiceCapabilities
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @returns {perfetto.protos.TracingServiceCapabilities} TracingServiceCapabilities
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            TracingServiceCapabilities.decodeDelimited = function decodeDelimited(reader) {
                if (!(reader instanceof $Reader))
                    reader = new $Reader(reader);
                return this.decode(reader, reader.uint32());
            };

            /**
             * Verifies a TracingServiceCapabilities message.
             * @function verify
             * @memberof perfetto.protos.TracingServiceCapabilities
             * @static
             * @param {Object.<string,*>} message Plain object to verify
             * @returns {string|null} `null` if valid, otherwise the reason why it is not
             */
            TracingServiceCapabilities.verify = function verify(message) {
                if (typeof message !== "object" || message === null)
                    return "object expected";
                if (message.hasQueryCapabilities != null && message.hasOwnProperty("hasQueryCapabilities"))
                    if (typeof message.hasQueryCapabilities !== "boolean")
                        return "hasQueryCapabilities: boolean expected";
                if (message.observableEvents != null && message.hasOwnProperty("observableEvents")) {
                    if (!Array.isArray(message.observableEvents))
                        return "observableEvents: array expected";
                    for (var i = 0; i < message.observableEvents.length; ++i)
                        switch (message.observableEvents[i]) {
                        default:
                            return "observableEvents: enum value[] expected";
                        case 0:
                        case 1:
                        case 2:
                            break;
                        }
                }
                if (message.hasTraceConfigOutputPath != null && message.hasOwnProperty("hasTraceConfigOutputPath"))
                    if (typeof message.hasTraceConfigOutputPath !== "boolean")
                        return "hasTraceConfigOutputPath: boolean expected";
                return null;
            };

            /**
             * Creates a TracingServiceCapabilities message from a plain object. Also converts values to their respective internal types.
             * @function fromObject
             * @memberof perfetto.protos.TracingServiceCapabilities
             * @static
             * @param {Object.<string,*>} object Plain object
             * @returns {perfetto.protos.TracingServiceCapabilities} TracingServiceCapabilities
             */
            TracingServiceCapabilities.fromObject = function fromObject(object) {
                if (object instanceof $root.perfetto.protos.TracingServiceCapabilities)
                    return object;
                var message = new $root.perfetto.protos.TracingServiceCapabilities();
                if (object.hasQueryCapabilities != null)
                    message.hasQueryCapabilities = Boolean(object.hasQueryCapabilities);
                if (object.observableEvents) {
                    if (!Array.isArray(object.observableEvents))
                        throw TypeError(".perfetto.protos.TracingServiceCapabilities.observableEvents: array expected");
                    message.observableEvents = [];
                    for (var i = 0; i < object.observableEvents.length; ++i)
                        switch (object.observableEvents[i]) {
                        default:
                        case "TYPE_UNSPECIFIED":
                        case 0:
                            message.observableEvents[i] = 0;
                            break;
                        case "TYPE_DATA_SOURCES_INSTANCES":
                        case 1:
                            message.observableEvents[i] = 1;
                            break;
                        case "TYPE_ALL_DATA_SOURCES_STARTED":
                        case 2:
                            message.observableEvents[i] = 2;
                            break;
                        }
                }
                if (object.hasTraceConfigOutputPath != null)
                    message.hasTraceConfigOutputPath = Boolean(object.hasTraceConfigOutputPath);
                return message;
            };

            /**
             * Creates a plain object from a TracingServiceCapabilities message. Also converts values to other types if specified.
             * @function toObject
             * @memberof perfetto.protos.TracingServiceCapabilities
             * @static
             * @param {perfetto.protos.TracingServiceCapabilities} message TracingServiceCapabilities
             * @param {$protobuf.IConversionOptions} [options] Conversion options
             * @returns {Object.<string,*>} Plain object
             */
            TracingServiceCapabilities.toObject = function toObject(message, options) {
                if (!options)
                    options = {};
                var object = {};
                if (options.arrays || options.defaults)
                    object.observableEvents = [];
                if (options.defaults) {
                    object.hasQueryCapabilities = false;
                    object.hasTraceConfigOutputPath = false;
                }
                if (message.hasQueryCapabilities != null && message.hasOwnProperty("hasQueryCapabilities"))
                    object.hasQueryCapabilities = message.hasQueryCapabilities;
                if (message.observableEvents && message.observableEvents.length) {
                    object.observableEvents = [];
                    for (var j = 0; j < message.observableEvents.length; ++j)
                        object.observableEvents[j] = options.enums === String ? $root.perfetto.protos.ObservableEvents.Type[message.observableEvents[j]] : message.observableEvents[j];
                }
                if (message.hasTraceConfigOutputPath != null && message.hasOwnProperty("hasTraceConfigOutputPath"))
                    object.hasTraceConfigOutputPath = message.hasTraceConfigOutputPath;
                return object;
            };

            /**
             * Converts this TracingServiceCapabilities to JSON.
             * @function toJSON
             * @memberof perfetto.protos.TracingServiceCapabilities
             * @instance
             * @returns {Object.<string,*>} JSON object
             */
            TracingServiceCapabilities.prototype.toJSON = function toJSON() {
                return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
            };

            return TracingServiceCapabilities;
        })();

        protos.ObservableEvents = (function() {

            /**
             * Properties of an ObservableEvents.
             * @memberof perfetto.protos
             * @interface IObservableEvents
             * @property {Array.<perfetto.protos.ObservableEvents.IDataSourceInstanceStateChange>|null} [instanceStateChanges] ObservableEvents instanceStateChanges
             * @property {boolean|null} [allDataSourcesStarted] ObservableEvents allDataSourcesStarted
             */

            /**
             * Constructs a new ObservableEvents.
             * @memberof perfetto.protos
             * @classdesc Represents an ObservableEvents.
             * @implements IObservableEvents
             * @constructor
             * @param {perfetto.protos.IObservableEvents=} [properties] Properties to set
             */
            function ObservableEvents(properties) {
                this.instanceStateChanges = [];
                if (properties)
                    for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                        if (properties[keys[i]] != null)
                            this[keys[i]] = properties[keys[i]];
            }

            /**
             * ObservableEvents instanceStateChanges.
             * @member {Array.<perfetto.protos.ObservableEvents.IDataSourceInstanceStateChange>} instanceStateChanges
             * @memberof perfetto.protos.ObservableEvents
             * @instance
             */
            ObservableEvents.prototype.instanceStateChanges = $util.emptyArray;

            /**
             * ObservableEvents allDataSourcesStarted.
             * @member {boolean} allDataSourcesStarted
             * @memberof perfetto.protos.ObservableEvents
             * @instance
             */
            ObservableEvents.prototype.allDataSourcesStarted = false;

            /**
             * Creates a new ObservableEvents instance using the specified properties.
             * @function create
             * @memberof perfetto.protos.ObservableEvents
             * @static
             * @param {perfetto.protos.IObservableEvents=} [properties] Properties to set
             * @returns {perfetto.protos.ObservableEvents} ObservableEvents instance
             */
            ObservableEvents.create = function create(properties) {
                return new ObservableEvents(properties);
            };

            /**
             * Encodes the specified ObservableEvents message. Does not implicitly {@link perfetto.protos.ObservableEvents.verify|verify} messages.
             * @function encode
             * @memberof perfetto.protos.ObservableEvents
             * @static
             * @param {perfetto.protos.IObservableEvents} message ObservableEvents message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            ObservableEvents.encode = function encode(message, writer) {
                if (!writer)
                    writer = $Writer.create();
                if (message.instanceStateChanges != null && message.instanceStateChanges.length)
                    for (var i = 0; i < message.instanceStateChanges.length; ++i)
                        $root.perfetto.protos.ObservableEvents.DataSourceInstanceStateChange.encode(message.instanceStateChanges[i], writer.uint32(/* id 1, wireType 2 =*/10).fork()).ldelim();
                if (message.allDataSourcesStarted != null && Object.hasOwnProperty.call(message, "allDataSourcesStarted"))
                    writer.uint32(/* id 2, wireType 0 =*/16).bool(message.allDataSourcesStarted);
                return writer;
            };

            /**
             * Encodes the specified ObservableEvents message, length delimited. Does not implicitly {@link perfetto.protos.ObservableEvents.verify|verify} messages.
             * @function encodeDelimited
             * @memberof perfetto.protos.ObservableEvents
             * @static
             * @param {perfetto.protos.IObservableEvents} message ObservableEvents message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            ObservableEvents.encodeDelimited = function encodeDelimited(message, writer) {
                return this.encode(message, writer).ldelim();
            };

            /**
             * Decodes an ObservableEvents message from the specified reader or buffer.
             * @function decode
             * @memberof perfetto.protos.ObservableEvents
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @param {number} [length] Message length if known beforehand
             * @returns {perfetto.protos.ObservableEvents} ObservableEvents
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            ObservableEvents.decode = function decode(reader, length) {
                if (!(reader instanceof $Reader))
                    reader = $Reader.create(reader);
                var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.ObservableEvents();
                while (reader.pos < end) {
                    var tag = reader.uint32();
                    switch (tag >>> 3) {
                    case 1:
                        if (!(message.instanceStateChanges && message.instanceStateChanges.length))
                            message.instanceStateChanges = [];
                        message.instanceStateChanges.push($root.perfetto.protos.ObservableEvents.DataSourceInstanceStateChange.decode(reader, reader.uint32()));
                        break;
                    case 2:
                        message.allDataSourcesStarted = reader.bool();
                        break;
                    default:
                        reader.skipType(tag & 7);
                        break;
                    }
                }
                return message;
            };

            /**
             * Decodes an ObservableEvents message from the specified reader or buffer, length delimited.
             * @function decodeDelimited
             * @memberof perfetto.protos.ObservableEvents
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @returns {perfetto.protos.ObservableEvents} ObservableEvents
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            ObservableEvents.decodeDelimited = function decodeDelimited(reader) {
                if (!(reader instanceof $Reader))
                    reader = new $Reader(reader);
                return this.decode(reader, reader.uint32());
            };

            /**
             * Verifies an ObservableEvents message.
             * @function verify
             * @memberof perfetto.protos.ObservableEvents
             * @static
             * @param {Object.<string,*>} message Plain object to verify
             * @returns {string|null} `null` if valid, otherwise the reason why it is not
             */
            ObservableEvents.verify = function verify(message) {
                if (typeof message !== "object" || message === null)
                    return "object expected";
                if (message.instanceStateChanges != null && message.hasOwnProperty("instanceStateChanges")) {
                    if (!Array.isArray(message.instanceStateChanges))
                        return "instanceStateChanges: array expected";
                    for (var i = 0; i < message.instanceStateChanges.length; ++i) {
                        var error = $root.perfetto.protos.ObservableEvents.DataSourceInstanceStateChange.verify(message.instanceStateChanges[i]);
                        if (error)
                            return "instanceStateChanges." + error;
                    }
                }
                if (message.allDataSourcesStarted != null && message.hasOwnProperty("allDataSourcesStarted"))
                    if (typeof message.allDataSourcesStarted !== "boolean")
                        return "allDataSourcesStarted: boolean expected";
                return null;
            };

            /**
             * Creates an ObservableEvents message from a plain object. Also converts values to their respective internal types.
             * @function fromObject
             * @memberof perfetto.protos.ObservableEvents
             * @static
             * @param {Object.<string,*>} object Plain object
             * @returns {perfetto.protos.ObservableEvents} ObservableEvents
             */
            ObservableEvents.fromObject = function fromObject(object) {
                if (object instanceof $root.perfetto.protos.ObservableEvents)
                    return object;
                var message = new $root.perfetto.protos.ObservableEvents();
                if (object.instanceStateChanges) {
                    if (!Array.isArray(object.instanceStateChanges))
                        throw TypeError(".perfetto.protos.ObservableEvents.instanceStateChanges: array expected");
                    message.instanceStateChanges = [];
                    for (var i = 0; i < object.instanceStateChanges.length; ++i) {
                        if (typeof object.instanceStateChanges[i] !== "object")
                            throw TypeError(".perfetto.protos.ObservableEvents.instanceStateChanges: object expected");
                        message.instanceStateChanges[i] = $root.perfetto.protos.ObservableEvents.DataSourceInstanceStateChange.fromObject(object.instanceStateChanges[i]);
                    }
                }
                if (object.allDataSourcesStarted != null)
                    message.allDataSourcesStarted = Boolean(object.allDataSourcesStarted);
                return message;
            };

            /**
             * Creates a plain object from an ObservableEvents message. Also converts values to other types if specified.
             * @function toObject
             * @memberof perfetto.protos.ObservableEvents
             * @static
             * @param {perfetto.protos.ObservableEvents} message ObservableEvents
             * @param {$protobuf.IConversionOptions} [options] Conversion options
             * @returns {Object.<string,*>} Plain object
             */
            ObservableEvents.toObject = function toObject(message, options) {
                if (!options)
                    options = {};
                var object = {};
                if (options.arrays || options.defaults)
                    object.instanceStateChanges = [];
                if (options.defaults)
                    object.allDataSourcesStarted = false;
                if (message.instanceStateChanges && message.instanceStateChanges.length) {
                    object.instanceStateChanges = [];
                    for (var j = 0; j < message.instanceStateChanges.length; ++j)
                        object.instanceStateChanges[j] = $root.perfetto.protos.ObservableEvents.DataSourceInstanceStateChange.toObject(message.instanceStateChanges[j], options);
                }
                if (message.allDataSourcesStarted != null && message.hasOwnProperty("allDataSourcesStarted"))
                    object.allDataSourcesStarted = message.allDataSourcesStarted;
                return object;
            };

            /**
             * Converts this ObservableEvents to JSON.
             * @function toJSON
             * @memberof perfetto.protos.ObservableEvents
             * @instance
             * @returns {Object.<string,*>} JSON object
             */
            ObservableEvents.prototype.toJSON = function toJSON() {
                return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
            };

            /**
             * Type enum.
             * @name perfetto.protos.ObservableEvents.Type
             * @enum {number}
             * @property {number} TYPE_UNSPECIFIED=0 TYPE_UNSPECIFIED value
             * @property {number} TYPE_DATA_SOURCES_INSTANCES=1 TYPE_DATA_SOURCES_INSTANCES value
             * @property {number} TYPE_ALL_DATA_SOURCES_STARTED=2 TYPE_ALL_DATA_SOURCES_STARTED value
             */
            ObservableEvents.Type = (function() {
                var valuesById = {}, values = Object.create(valuesById);
                values[valuesById[0] = "TYPE_UNSPECIFIED"] = 0;
                values[valuesById[1] = "TYPE_DATA_SOURCES_INSTANCES"] = 1;
                values[valuesById[2] = "TYPE_ALL_DATA_SOURCES_STARTED"] = 2;
                return values;
            })();

            /**
             * DataSourceInstanceState enum.
             * @name perfetto.protos.ObservableEvents.DataSourceInstanceState
             * @enum {number}
             * @property {number} DATA_SOURCE_INSTANCE_STATE_STOPPED=1 DATA_SOURCE_INSTANCE_STATE_STOPPED value
             * @property {number} DATA_SOURCE_INSTANCE_STATE_STARTED=2 DATA_SOURCE_INSTANCE_STATE_STARTED value
             */
            ObservableEvents.DataSourceInstanceState = (function() {
                var valuesById = {}, values = Object.create(valuesById);
                values[valuesById[1] = "DATA_SOURCE_INSTANCE_STATE_STOPPED"] = 1;
                values[valuesById[2] = "DATA_SOURCE_INSTANCE_STATE_STARTED"] = 2;
                return values;
            })();

            ObservableEvents.DataSourceInstanceStateChange = (function() {

                /**
                 * Properties of a DataSourceInstanceStateChange.
                 * @memberof perfetto.protos.ObservableEvents
                 * @interface IDataSourceInstanceStateChange
                 * @property {string|null} [producerName] DataSourceInstanceStateChange producerName
                 * @property {string|null} [dataSourceName] DataSourceInstanceStateChange dataSourceName
                 * @property {perfetto.protos.ObservableEvents.DataSourceInstanceState|null} [state] DataSourceInstanceStateChange state
                 */

                /**
                 * Constructs a new DataSourceInstanceStateChange.
                 * @memberof perfetto.protos.ObservableEvents
                 * @classdesc Represents a DataSourceInstanceStateChange.
                 * @implements IDataSourceInstanceStateChange
                 * @constructor
                 * @param {perfetto.protos.ObservableEvents.IDataSourceInstanceStateChange=} [properties] Properties to set
                 */
                function DataSourceInstanceStateChange(properties) {
                    if (properties)
                        for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                            if (properties[keys[i]] != null)
                                this[keys[i]] = properties[keys[i]];
                }

                /**
                 * DataSourceInstanceStateChange producerName.
                 * @member {string} producerName
                 * @memberof perfetto.protos.ObservableEvents.DataSourceInstanceStateChange
                 * @instance
                 */
                DataSourceInstanceStateChange.prototype.producerName = "";

                /**
                 * DataSourceInstanceStateChange dataSourceName.
                 * @member {string} dataSourceName
                 * @memberof perfetto.protos.ObservableEvents.DataSourceInstanceStateChange
                 * @instance
                 */
                DataSourceInstanceStateChange.prototype.dataSourceName = "";

                /**
                 * DataSourceInstanceStateChange state.
                 * @member {perfetto.protos.ObservableEvents.DataSourceInstanceState} state
                 * @memberof perfetto.protos.ObservableEvents.DataSourceInstanceStateChange
                 * @instance
                 */
                DataSourceInstanceStateChange.prototype.state = 1;

                /**
                 * Creates a new DataSourceInstanceStateChange instance using the specified properties.
                 * @function create
                 * @memberof perfetto.protos.ObservableEvents.DataSourceInstanceStateChange
                 * @static
                 * @param {perfetto.protos.ObservableEvents.IDataSourceInstanceStateChange=} [properties] Properties to set
                 * @returns {perfetto.protos.ObservableEvents.DataSourceInstanceStateChange} DataSourceInstanceStateChange instance
                 */
                DataSourceInstanceStateChange.create = function create(properties) {
                    return new DataSourceInstanceStateChange(properties);
                };

                /**
                 * Encodes the specified DataSourceInstanceStateChange message. Does not implicitly {@link perfetto.protos.ObservableEvents.DataSourceInstanceStateChange.verify|verify} messages.
                 * @function encode
                 * @memberof perfetto.protos.ObservableEvents.DataSourceInstanceStateChange
                 * @static
                 * @param {perfetto.protos.ObservableEvents.IDataSourceInstanceStateChange} message DataSourceInstanceStateChange message or plain object to encode
                 * @param {$protobuf.Writer} [writer] Writer to encode to
                 * @returns {$protobuf.Writer} Writer
                 */
                DataSourceInstanceStateChange.encode = function encode(message, writer) {
                    if (!writer)
                        writer = $Writer.create();
                    if (message.producerName != null && Object.hasOwnProperty.call(message, "producerName"))
                        writer.uint32(/* id 1, wireType 2 =*/10).string(message.producerName);
                    if (message.dataSourceName != null && Object.hasOwnProperty.call(message, "dataSourceName"))
                        writer.uint32(/* id 2, wireType 2 =*/18).string(message.dataSourceName);
                    if (message.state != null && Object.hasOwnProperty.call(message, "state"))
                        writer.uint32(/* id 3, wireType 0 =*/24).int32(message.state);
                    return writer;
                };

                /**
                 * Encodes the specified DataSourceInstanceStateChange message, length delimited. Does not implicitly {@link perfetto.protos.ObservableEvents.DataSourceInstanceStateChange.verify|verify} messages.
                 * @function encodeDelimited
                 * @memberof perfetto.protos.ObservableEvents.DataSourceInstanceStateChange
                 * @static
                 * @param {perfetto.protos.ObservableEvents.IDataSourceInstanceStateChange} message DataSourceInstanceStateChange message or plain object to encode
                 * @param {$protobuf.Writer} [writer] Writer to encode to
                 * @returns {$protobuf.Writer} Writer
                 */
                DataSourceInstanceStateChange.encodeDelimited = function encodeDelimited(message, writer) {
                    return this.encode(message, writer).ldelim();
                };

                /**
                 * Decodes a DataSourceInstanceStateChange message from the specified reader or buffer.
                 * @function decode
                 * @memberof perfetto.protos.ObservableEvents.DataSourceInstanceStateChange
                 * @static
                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                 * @param {number} [length] Message length if known beforehand
                 * @returns {perfetto.protos.ObservableEvents.DataSourceInstanceStateChange} DataSourceInstanceStateChange
                 * @throws {Error} If the payload is not a reader or valid buffer
                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
                 */
                DataSourceInstanceStateChange.decode = function decode(reader, length) {
                    if (!(reader instanceof $Reader))
                        reader = $Reader.create(reader);
                    var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.ObservableEvents.DataSourceInstanceStateChange();
                    while (reader.pos < end) {
                        var tag = reader.uint32();
                        switch (tag >>> 3) {
                        case 1:
                            message.producerName = reader.string();
                            break;
                        case 2:
                            message.dataSourceName = reader.string();
                            break;
                        case 3:
                            message.state = reader.int32();
                            break;
                        default:
                            reader.skipType(tag & 7);
                            break;
                        }
                    }
                    return message;
                };

                /**
                 * Decodes a DataSourceInstanceStateChange message from the specified reader or buffer, length delimited.
                 * @function decodeDelimited
                 * @memberof perfetto.protos.ObservableEvents.DataSourceInstanceStateChange
                 * @static
                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                 * @returns {perfetto.protos.ObservableEvents.DataSourceInstanceStateChange} DataSourceInstanceStateChange
                 * @throws {Error} If the payload is not a reader or valid buffer
                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
                 */
                DataSourceInstanceStateChange.decodeDelimited = function decodeDelimited(reader) {
                    if (!(reader instanceof $Reader))
                        reader = new $Reader(reader);
                    return this.decode(reader, reader.uint32());
                };

                /**
                 * Verifies a DataSourceInstanceStateChange message.
                 * @function verify
                 * @memberof perfetto.protos.ObservableEvents.DataSourceInstanceStateChange
                 * @static
                 * @param {Object.<string,*>} message Plain object to verify
                 * @returns {string|null} `null` if valid, otherwise the reason why it is not
                 */
                DataSourceInstanceStateChange.verify = function verify(message) {
                    if (typeof message !== "object" || message === null)
                        return "object expected";
                    if (message.producerName != null && message.hasOwnProperty("producerName"))
                        if (!$util.isString(message.producerName))
                            return "producerName: string expected";
                    if (message.dataSourceName != null && message.hasOwnProperty("dataSourceName"))
                        if (!$util.isString(message.dataSourceName))
                            return "dataSourceName: string expected";
                    if (message.state != null && message.hasOwnProperty("state"))
                        switch (message.state) {
                        default:
                            return "state: enum value expected";
                        case 1:
                        case 2:
                            break;
                        }
                    return null;
                };

                /**
                 * Creates a DataSourceInstanceStateChange message from a plain object. Also converts values to their respective internal types.
                 * @function fromObject
                 * @memberof perfetto.protos.ObservableEvents.DataSourceInstanceStateChange
                 * @static
                 * @param {Object.<string,*>} object Plain object
                 * @returns {perfetto.protos.ObservableEvents.DataSourceInstanceStateChange} DataSourceInstanceStateChange
                 */
                DataSourceInstanceStateChange.fromObject = function fromObject(object) {
                    if (object instanceof $root.perfetto.protos.ObservableEvents.DataSourceInstanceStateChange)
                        return object;
                    var message = new $root.perfetto.protos.ObservableEvents.DataSourceInstanceStateChange();
                    if (object.producerName != null)
                        message.producerName = String(object.producerName);
                    if (object.dataSourceName != null)
                        message.dataSourceName = String(object.dataSourceName);
                    switch (object.state) {
                    case "DATA_SOURCE_INSTANCE_STATE_STOPPED":
                    case 1:
                        message.state = 1;
                        break;
                    case "DATA_SOURCE_INSTANCE_STATE_STARTED":
                    case 2:
                        message.state = 2;
                        break;
                    }
                    return message;
                };

                /**
                 * Creates a plain object from a DataSourceInstanceStateChange message. Also converts values to other types if specified.
                 * @function toObject
                 * @memberof perfetto.protos.ObservableEvents.DataSourceInstanceStateChange
                 * @static
                 * @param {perfetto.protos.ObservableEvents.DataSourceInstanceStateChange} message DataSourceInstanceStateChange
                 * @param {$protobuf.IConversionOptions} [options] Conversion options
                 * @returns {Object.<string,*>} Plain object
                 */
                DataSourceInstanceStateChange.toObject = function toObject(message, options) {
                    if (!options)
                        options = {};
                    var object = {};
                    if (options.defaults) {
                        object.producerName = "";
                        object.dataSourceName = "";
                        object.state = options.enums === String ? "DATA_SOURCE_INSTANCE_STATE_STOPPED" : 1;
                    }
                    if (message.producerName != null && message.hasOwnProperty("producerName"))
                        object.producerName = message.producerName;
                    if (message.dataSourceName != null && message.hasOwnProperty("dataSourceName"))
                        object.dataSourceName = message.dataSourceName;
                    if (message.state != null && message.hasOwnProperty("state"))
                        object.state = options.enums === String ? $root.perfetto.protos.ObservableEvents.DataSourceInstanceState[message.state] : message.state;
                    return object;
                };

                /**
                 * Converts this DataSourceInstanceStateChange to JSON.
                 * @function toJSON
                 * @memberof perfetto.protos.ObservableEvents.DataSourceInstanceStateChange
                 * @instance
                 * @returns {Object.<string,*>} JSON object
                 */
                DataSourceInstanceStateChange.prototype.toJSON = function toJSON() {
                    return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
                };

                return DataSourceInstanceStateChange;
            })();

            return ObservableEvents;
        })();

        protos.GpuCounterDescriptor = (function() {

            /**
             * Properties of a GpuCounterDescriptor.
             * @memberof perfetto.protos
             * @interface IGpuCounterDescriptor
             * @property {Array.<perfetto.protos.GpuCounterDescriptor.IGpuCounterSpec>|null} [specs] GpuCounterDescriptor specs
             * @property {Array.<perfetto.protos.GpuCounterDescriptor.IGpuCounterBlock>|null} [blocks] GpuCounterDescriptor blocks
             * @property {number|null} [minSamplingPeriodNs] GpuCounterDescriptor minSamplingPeriodNs
             * @property {number|null} [maxSamplingPeriodNs] GpuCounterDescriptor maxSamplingPeriodNs
             * @property {boolean|null} [supportsInstrumentedSampling] GpuCounterDescriptor supportsInstrumentedSampling
             */

            /**
             * Constructs a new GpuCounterDescriptor.
             * @memberof perfetto.protos
             * @classdesc Represents a GpuCounterDescriptor.
             * @implements IGpuCounterDescriptor
             * @constructor
             * @param {perfetto.protos.IGpuCounterDescriptor=} [properties] Properties to set
             */
            function GpuCounterDescriptor(properties) {
                this.specs = [];
                this.blocks = [];
                if (properties)
                    for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                        if (properties[keys[i]] != null)
                            this[keys[i]] = properties[keys[i]];
            }

            /**
             * GpuCounterDescriptor specs.
             * @member {Array.<perfetto.protos.GpuCounterDescriptor.IGpuCounterSpec>} specs
             * @memberof perfetto.protos.GpuCounterDescriptor
             * @instance
             */
            GpuCounterDescriptor.prototype.specs = $util.emptyArray;

            /**
             * GpuCounterDescriptor blocks.
             * @member {Array.<perfetto.protos.GpuCounterDescriptor.IGpuCounterBlock>} blocks
             * @memberof perfetto.protos.GpuCounterDescriptor
             * @instance
             */
            GpuCounterDescriptor.prototype.blocks = $util.emptyArray;

            /**
             * GpuCounterDescriptor minSamplingPeriodNs.
             * @member {number} minSamplingPeriodNs
             * @memberof perfetto.protos.GpuCounterDescriptor
             * @instance
             */
            GpuCounterDescriptor.prototype.minSamplingPeriodNs = $util.Long ? $util.Long.fromBits(0,0,true) : 0;

            /**
             * GpuCounterDescriptor maxSamplingPeriodNs.
             * @member {number} maxSamplingPeriodNs
             * @memberof perfetto.protos.GpuCounterDescriptor
             * @instance
             */
            GpuCounterDescriptor.prototype.maxSamplingPeriodNs = $util.Long ? $util.Long.fromBits(0,0,true) : 0;

            /**
             * GpuCounterDescriptor supportsInstrumentedSampling.
             * @member {boolean} supportsInstrumentedSampling
             * @memberof perfetto.protos.GpuCounterDescriptor
             * @instance
             */
            GpuCounterDescriptor.prototype.supportsInstrumentedSampling = false;

            /**
             * Creates a new GpuCounterDescriptor instance using the specified properties.
             * @function create
             * @memberof perfetto.protos.GpuCounterDescriptor
             * @static
             * @param {perfetto.protos.IGpuCounterDescriptor=} [properties] Properties to set
             * @returns {perfetto.protos.GpuCounterDescriptor} GpuCounterDescriptor instance
             */
            GpuCounterDescriptor.create = function create(properties) {
                return new GpuCounterDescriptor(properties);
            };

            /**
             * Encodes the specified GpuCounterDescriptor message. Does not implicitly {@link perfetto.protos.GpuCounterDescriptor.verify|verify} messages.
             * @function encode
             * @memberof perfetto.protos.GpuCounterDescriptor
             * @static
             * @param {perfetto.protos.IGpuCounterDescriptor} message GpuCounterDescriptor message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            GpuCounterDescriptor.encode = function encode(message, writer) {
                if (!writer)
                    writer = $Writer.create();
                if (message.specs != null && message.specs.length)
                    for (var i = 0; i < message.specs.length; ++i)
                        $root.perfetto.protos.GpuCounterDescriptor.GpuCounterSpec.encode(message.specs[i], writer.uint32(/* id 1, wireType 2 =*/10).fork()).ldelim();
                if (message.blocks != null && message.blocks.length)
                    for (var i = 0; i < message.blocks.length; ++i)
                        $root.perfetto.protos.GpuCounterDescriptor.GpuCounterBlock.encode(message.blocks[i], writer.uint32(/* id 2, wireType 2 =*/18).fork()).ldelim();
                if (message.minSamplingPeriodNs != null && Object.hasOwnProperty.call(message, "minSamplingPeriodNs"))
                    writer.uint32(/* id 3, wireType 0 =*/24).uint64(message.minSamplingPeriodNs);
                if (message.maxSamplingPeriodNs != null && Object.hasOwnProperty.call(message, "maxSamplingPeriodNs"))
                    writer.uint32(/* id 4, wireType 0 =*/32).uint64(message.maxSamplingPeriodNs);
                if (message.supportsInstrumentedSampling != null && Object.hasOwnProperty.call(message, "supportsInstrumentedSampling"))
                    writer.uint32(/* id 5, wireType 0 =*/40).bool(message.supportsInstrumentedSampling);
                return writer;
            };

            /**
             * Encodes the specified GpuCounterDescriptor message, length delimited. Does not implicitly {@link perfetto.protos.GpuCounterDescriptor.verify|verify} messages.
             * @function encodeDelimited
             * @memberof perfetto.protos.GpuCounterDescriptor
             * @static
             * @param {perfetto.protos.IGpuCounterDescriptor} message GpuCounterDescriptor message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            GpuCounterDescriptor.encodeDelimited = function encodeDelimited(message, writer) {
                return this.encode(message, writer).ldelim();
            };

            /**
             * Decodes a GpuCounterDescriptor message from the specified reader or buffer.
             * @function decode
             * @memberof perfetto.protos.GpuCounterDescriptor
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @param {number} [length] Message length if known beforehand
             * @returns {perfetto.protos.GpuCounterDescriptor} GpuCounterDescriptor
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            GpuCounterDescriptor.decode = function decode(reader, length) {
                if (!(reader instanceof $Reader))
                    reader = $Reader.create(reader);
                var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.GpuCounterDescriptor();
                while (reader.pos < end) {
                    var tag = reader.uint32();
                    switch (tag >>> 3) {
                    case 1:
                        if (!(message.specs && message.specs.length))
                            message.specs = [];
                        message.specs.push($root.perfetto.protos.GpuCounterDescriptor.GpuCounterSpec.decode(reader, reader.uint32()));
                        break;
                    case 2:
                        if (!(message.blocks && message.blocks.length))
                            message.blocks = [];
                        message.blocks.push($root.perfetto.protos.GpuCounterDescriptor.GpuCounterBlock.decode(reader, reader.uint32()));
                        break;
                    case 3:
                        message.minSamplingPeriodNs = reader.uint64();
                        break;
                    case 4:
                        message.maxSamplingPeriodNs = reader.uint64();
                        break;
                    case 5:
                        message.supportsInstrumentedSampling = reader.bool();
                        break;
                    default:
                        reader.skipType(tag & 7);
                        break;
                    }
                }
                return message;
            };

            /**
             * Decodes a GpuCounterDescriptor message from the specified reader or buffer, length delimited.
             * @function decodeDelimited
             * @memberof perfetto.protos.GpuCounterDescriptor
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @returns {perfetto.protos.GpuCounterDescriptor} GpuCounterDescriptor
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            GpuCounterDescriptor.decodeDelimited = function decodeDelimited(reader) {
                if (!(reader instanceof $Reader))
                    reader = new $Reader(reader);
                return this.decode(reader, reader.uint32());
            };

            /**
             * Verifies a GpuCounterDescriptor message.
             * @function verify
             * @memberof perfetto.protos.GpuCounterDescriptor
             * @static
             * @param {Object.<string,*>} message Plain object to verify
             * @returns {string|null} `null` if valid, otherwise the reason why it is not
             */
            GpuCounterDescriptor.verify = function verify(message) {
                if (typeof message !== "object" || message === null)
                    return "object expected";
                if (message.specs != null && message.hasOwnProperty("specs")) {
                    if (!Array.isArray(message.specs))
                        return "specs: array expected";
                    for (var i = 0; i < message.specs.length; ++i) {
                        var error = $root.perfetto.protos.GpuCounterDescriptor.GpuCounterSpec.verify(message.specs[i]);
                        if (error)
                            return "specs." + error;
                    }
                }
                if (message.blocks != null && message.hasOwnProperty("blocks")) {
                    if (!Array.isArray(message.blocks))
                        return "blocks: array expected";
                    for (var i = 0; i < message.blocks.length; ++i) {
                        var error = $root.perfetto.protos.GpuCounterDescriptor.GpuCounterBlock.verify(message.blocks[i]);
                        if (error)
                            return "blocks." + error;
                    }
                }
                if (message.minSamplingPeriodNs != null && message.hasOwnProperty("minSamplingPeriodNs"))
                    if (!$util.isInteger(message.minSamplingPeriodNs) && !(message.minSamplingPeriodNs && $util.isInteger(message.minSamplingPeriodNs.low) && $util.isInteger(message.minSamplingPeriodNs.high)))
                        return "minSamplingPeriodNs: integer|Long expected";
                if (message.maxSamplingPeriodNs != null && message.hasOwnProperty("maxSamplingPeriodNs"))
                    if (!$util.isInteger(message.maxSamplingPeriodNs) && !(message.maxSamplingPeriodNs && $util.isInteger(message.maxSamplingPeriodNs.low) && $util.isInteger(message.maxSamplingPeriodNs.high)))
                        return "maxSamplingPeriodNs: integer|Long expected";
                if (message.supportsInstrumentedSampling != null && message.hasOwnProperty("supportsInstrumentedSampling"))
                    if (typeof message.supportsInstrumentedSampling !== "boolean")
                        return "supportsInstrumentedSampling: boolean expected";
                return null;
            };

            /**
             * Creates a GpuCounterDescriptor message from a plain object. Also converts values to their respective internal types.
             * @function fromObject
             * @memberof perfetto.protos.GpuCounterDescriptor
             * @static
             * @param {Object.<string,*>} object Plain object
             * @returns {perfetto.protos.GpuCounterDescriptor} GpuCounterDescriptor
             */
            GpuCounterDescriptor.fromObject = function fromObject(object) {
                if (object instanceof $root.perfetto.protos.GpuCounterDescriptor)
                    return object;
                var message = new $root.perfetto.protos.GpuCounterDescriptor();
                if (object.specs) {
                    if (!Array.isArray(object.specs))
                        throw TypeError(".perfetto.protos.GpuCounterDescriptor.specs: array expected");
                    message.specs = [];
                    for (var i = 0; i < object.specs.length; ++i) {
                        if (typeof object.specs[i] !== "object")
                            throw TypeError(".perfetto.protos.GpuCounterDescriptor.specs: object expected");
                        message.specs[i] = $root.perfetto.protos.GpuCounterDescriptor.GpuCounterSpec.fromObject(object.specs[i]);
                    }
                }
                if (object.blocks) {
                    if (!Array.isArray(object.blocks))
                        throw TypeError(".perfetto.protos.GpuCounterDescriptor.blocks: array expected");
                    message.blocks = [];
                    for (var i = 0; i < object.blocks.length; ++i) {
                        if (typeof object.blocks[i] !== "object")
                            throw TypeError(".perfetto.protos.GpuCounterDescriptor.blocks: object expected");
                        message.blocks[i] = $root.perfetto.protos.GpuCounterDescriptor.GpuCounterBlock.fromObject(object.blocks[i]);
                    }
                }
                if (object.minSamplingPeriodNs != null)
                    if ($util.Long)
                        (message.minSamplingPeriodNs = $util.Long.fromValue(object.minSamplingPeriodNs)).unsigned = true;
                    else if (typeof object.minSamplingPeriodNs === "string")
                        message.minSamplingPeriodNs = parseInt(object.minSamplingPeriodNs, 10);
                    else if (typeof object.minSamplingPeriodNs === "number")
                        message.minSamplingPeriodNs = object.minSamplingPeriodNs;
                    else if (typeof object.minSamplingPeriodNs === "object")
                        message.minSamplingPeriodNs = new $util.LongBits(object.minSamplingPeriodNs.low >>> 0, object.minSamplingPeriodNs.high >>> 0).toNumber(true);
                if (object.maxSamplingPeriodNs != null)
                    if ($util.Long)
                        (message.maxSamplingPeriodNs = $util.Long.fromValue(object.maxSamplingPeriodNs)).unsigned = true;
                    else if (typeof object.maxSamplingPeriodNs === "string")
                        message.maxSamplingPeriodNs = parseInt(object.maxSamplingPeriodNs, 10);
                    else if (typeof object.maxSamplingPeriodNs === "number")
                        message.maxSamplingPeriodNs = object.maxSamplingPeriodNs;
                    else if (typeof object.maxSamplingPeriodNs === "object")
                        message.maxSamplingPeriodNs = new $util.LongBits(object.maxSamplingPeriodNs.low >>> 0, object.maxSamplingPeriodNs.high >>> 0).toNumber(true);
                if (object.supportsInstrumentedSampling != null)
                    message.supportsInstrumentedSampling = Boolean(object.supportsInstrumentedSampling);
                return message;
            };

            /**
             * Creates a plain object from a GpuCounterDescriptor message. Also converts values to other types if specified.
             * @function toObject
             * @memberof perfetto.protos.GpuCounterDescriptor
             * @static
             * @param {perfetto.protos.GpuCounterDescriptor} message GpuCounterDescriptor
             * @param {$protobuf.IConversionOptions} [options] Conversion options
             * @returns {Object.<string,*>} Plain object
             */
            GpuCounterDescriptor.toObject = function toObject(message, options) {
                if (!options)
                    options = {};
                var object = {};
                if (options.arrays || options.defaults) {
                    object.specs = [];
                    object.blocks = [];
                }
                if (options.defaults) {
                    if ($util.Long) {
                        var long = new $util.Long(0, 0, true);
                        object.minSamplingPeriodNs = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
                    } else
                        object.minSamplingPeriodNs = options.longs === String ? "0" : 0;
                    if ($util.Long) {
                        var long = new $util.Long(0, 0, true);
                        object.maxSamplingPeriodNs = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
                    } else
                        object.maxSamplingPeriodNs = options.longs === String ? "0" : 0;
                    object.supportsInstrumentedSampling = false;
                }
                if (message.specs && message.specs.length) {
                    object.specs = [];
                    for (var j = 0; j < message.specs.length; ++j)
                        object.specs[j] = $root.perfetto.protos.GpuCounterDescriptor.GpuCounterSpec.toObject(message.specs[j], options);
                }
                if (message.blocks && message.blocks.length) {
                    object.blocks = [];
                    for (var j = 0; j < message.blocks.length; ++j)
                        object.blocks[j] = $root.perfetto.protos.GpuCounterDescriptor.GpuCounterBlock.toObject(message.blocks[j], options);
                }
                if (message.minSamplingPeriodNs != null && message.hasOwnProperty("minSamplingPeriodNs"))
                    if (typeof message.minSamplingPeriodNs === "number")
                        object.minSamplingPeriodNs = options.longs === String ? String(message.minSamplingPeriodNs) : message.minSamplingPeriodNs;
                    else
                        object.minSamplingPeriodNs = options.longs === String ? $util.Long.prototype.toString.call(message.minSamplingPeriodNs) : options.longs === Number ? new $util.LongBits(message.minSamplingPeriodNs.low >>> 0, message.minSamplingPeriodNs.high >>> 0).toNumber(true) : message.minSamplingPeriodNs;
                if (message.maxSamplingPeriodNs != null && message.hasOwnProperty("maxSamplingPeriodNs"))
                    if (typeof message.maxSamplingPeriodNs === "number")
                        object.maxSamplingPeriodNs = options.longs === String ? String(message.maxSamplingPeriodNs) : message.maxSamplingPeriodNs;
                    else
                        object.maxSamplingPeriodNs = options.longs === String ? $util.Long.prototype.toString.call(message.maxSamplingPeriodNs) : options.longs === Number ? new $util.LongBits(message.maxSamplingPeriodNs.low >>> 0, message.maxSamplingPeriodNs.high >>> 0).toNumber(true) : message.maxSamplingPeriodNs;
                if (message.supportsInstrumentedSampling != null && message.hasOwnProperty("supportsInstrumentedSampling"))
                    object.supportsInstrumentedSampling = message.supportsInstrumentedSampling;
                return object;
            };

            /**
             * Converts this GpuCounterDescriptor to JSON.
             * @function toJSON
             * @memberof perfetto.protos.GpuCounterDescriptor
             * @instance
             * @returns {Object.<string,*>} JSON object
             */
            GpuCounterDescriptor.prototype.toJSON = function toJSON() {
                return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
            };

            /**
             * GpuCounterGroup enum.
             * @name perfetto.protos.GpuCounterDescriptor.GpuCounterGroup
             * @enum {number}
             * @property {number} UNCLASSIFIED=0 UNCLASSIFIED value
             * @property {number} SYSTEM=1 SYSTEM value
             * @property {number} VERTICES=2 VERTICES value
             * @property {number} FRAGMENTS=3 FRAGMENTS value
             * @property {number} PRIMITIVES=4 PRIMITIVES value
             * @property {number} MEMORY=5 MEMORY value
             * @property {number} COMPUTE=6 COMPUTE value
             */
            GpuCounterDescriptor.GpuCounterGroup = (function() {
                var valuesById = {}, values = Object.create(valuesById);
                values[valuesById[0] = "UNCLASSIFIED"] = 0;
                values[valuesById[1] = "SYSTEM"] = 1;
                values[valuesById[2] = "VERTICES"] = 2;
                values[valuesById[3] = "FRAGMENTS"] = 3;
                values[valuesById[4] = "PRIMITIVES"] = 4;
                values[valuesById[5] = "MEMORY"] = 5;
                values[valuesById[6] = "COMPUTE"] = 6;
                return values;
            })();

            GpuCounterDescriptor.GpuCounterSpec = (function() {

                /**
                 * Properties of a GpuCounterSpec.
                 * @memberof perfetto.protos.GpuCounterDescriptor
                 * @interface IGpuCounterSpec
                 * @property {number|null} [counterId] GpuCounterSpec counterId
                 * @property {string|null} [name] GpuCounterSpec name
                 * @property {string|null} [description] GpuCounterSpec description
                 * @property {number|null} [intPeakValue] GpuCounterSpec intPeakValue
                 * @property {number|null} [doublePeakValue] GpuCounterSpec doublePeakValue
                 * @property {Array.<perfetto.protos.GpuCounterDescriptor.MeasureUnit>|null} [numeratorUnits] GpuCounterSpec numeratorUnits
                 * @property {Array.<perfetto.protos.GpuCounterDescriptor.MeasureUnit>|null} [denominatorUnits] GpuCounterSpec denominatorUnits
                 * @property {boolean|null} [selectByDefault] GpuCounterSpec selectByDefault
                 * @property {Array.<perfetto.protos.GpuCounterDescriptor.GpuCounterGroup>|null} [groups] GpuCounterSpec groups
                 */

                /**
                 * Constructs a new GpuCounterSpec.
                 * @memberof perfetto.protos.GpuCounterDescriptor
                 * @classdesc Represents a GpuCounterSpec.
                 * @implements IGpuCounterSpec
                 * @constructor
                 * @param {perfetto.protos.GpuCounterDescriptor.IGpuCounterSpec=} [properties] Properties to set
                 */
                function GpuCounterSpec(properties) {
                    this.numeratorUnits = [];
                    this.denominatorUnits = [];
                    this.groups = [];
                    if (properties)
                        for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                            if (properties[keys[i]] != null)
                                this[keys[i]] = properties[keys[i]];
                }

                /**
                 * GpuCounterSpec counterId.
                 * @member {number} counterId
                 * @memberof perfetto.protos.GpuCounterDescriptor.GpuCounterSpec
                 * @instance
                 */
                GpuCounterSpec.prototype.counterId = 0;

                /**
                 * GpuCounterSpec name.
                 * @member {string} name
                 * @memberof perfetto.protos.GpuCounterDescriptor.GpuCounterSpec
                 * @instance
                 */
                GpuCounterSpec.prototype.name = "";

                /**
                 * GpuCounterSpec description.
                 * @member {string} description
                 * @memberof perfetto.protos.GpuCounterDescriptor.GpuCounterSpec
                 * @instance
                 */
                GpuCounterSpec.prototype.description = "";

                /**
                 * GpuCounterSpec intPeakValue.
                 * @member {number} intPeakValue
                 * @memberof perfetto.protos.GpuCounterDescriptor.GpuCounterSpec
                 * @instance
                 */
                GpuCounterSpec.prototype.intPeakValue = $util.Long ? $util.Long.fromBits(0,0,false) : 0;

                /**
                 * GpuCounterSpec doublePeakValue.
                 * @member {number} doublePeakValue
                 * @memberof perfetto.protos.GpuCounterDescriptor.GpuCounterSpec
                 * @instance
                 */
                GpuCounterSpec.prototype.doublePeakValue = 0;

                /**
                 * GpuCounterSpec numeratorUnits.
                 * @member {Array.<perfetto.protos.GpuCounterDescriptor.MeasureUnit>} numeratorUnits
                 * @memberof perfetto.protos.GpuCounterDescriptor.GpuCounterSpec
                 * @instance
                 */
                GpuCounterSpec.prototype.numeratorUnits = $util.emptyArray;

                /**
                 * GpuCounterSpec denominatorUnits.
                 * @member {Array.<perfetto.protos.GpuCounterDescriptor.MeasureUnit>} denominatorUnits
                 * @memberof perfetto.protos.GpuCounterDescriptor.GpuCounterSpec
                 * @instance
                 */
                GpuCounterSpec.prototype.denominatorUnits = $util.emptyArray;

                /**
                 * GpuCounterSpec selectByDefault.
                 * @member {boolean} selectByDefault
                 * @memberof perfetto.protos.GpuCounterDescriptor.GpuCounterSpec
                 * @instance
                 */
                GpuCounterSpec.prototype.selectByDefault = false;

                /**
                 * GpuCounterSpec groups.
                 * @member {Array.<perfetto.protos.GpuCounterDescriptor.GpuCounterGroup>} groups
                 * @memberof perfetto.protos.GpuCounterDescriptor.GpuCounterSpec
                 * @instance
                 */
                GpuCounterSpec.prototype.groups = $util.emptyArray;

                // OneOf field names bound to virtual getters and setters
                var $oneOfFields;

                /**
                 * GpuCounterSpec peakValue.
                 * @member {"intPeakValue"|"doublePeakValue"|undefined} peakValue
                 * @memberof perfetto.protos.GpuCounterDescriptor.GpuCounterSpec
                 * @instance
                 */
                Object.defineProperty(GpuCounterSpec.prototype, "peakValue", {
                    get: $util.oneOfGetter($oneOfFields = ["intPeakValue", "doublePeakValue"]),
                    set: $util.oneOfSetter($oneOfFields)
                });

                /**
                 * Creates a new GpuCounterSpec instance using the specified properties.
                 * @function create
                 * @memberof perfetto.protos.GpuCounterDescriptor.GpuCounterSpec
                 * @static
                 * @param {perfetto.protos.GpuCounterDescriptor.IGpuCounterSpec=} [properties] Properties to set
                 * @returns {perfetto.protos.GpuCounterDescriptor.GpuCounterSpec} GpuCounterSpec instance
                 */
                GpuCounterSpec.create = function create(properties) {
                    return new GpuCounterSpec(properties);
                };

                /**
                 * Encodes the specified GpuCounterSpec message. Does not implicitly {@link perfetto.protos.GpuCounterDescriptor.GpuCounterSpec.verify|verify} messages.
                 * @function encode
                 * @memberof perfetto.protos.GpuCounterDescriptor.GpuCounterSpec
                 * @static
                 * @param {perfetto.protos.GpuCounterDescriptor.IGpuCounterSpec} message GpuCounterSpec message or plain object to encode
                 * @param {$protobuf.Writer} [writer] Writer to encode to
                 * @returns {$protobuf.Writer} Writer
                 */
                GpuCounterSpec.encode = function encode(message, writer) {
                    if (!writer)
                        writer = $Writer.create();
                    if (message.counterId != null && Object.hasOwnProperty.call(message, "counterId"))
                        writer.uint32(/* id 1, wireType 0 =*/8).uint32(message.counterId);
                    if (message.name != null && Object.hasOwnProperty.call(message, "name"))
                        writer.uint32(/* id 2, wireType 2 =*/18).string(message.name);
                    if (message.description != null && Object.hasOwnProperty.call(message, "description"))
                        writer.uint32(/* id 3, wireType 2 =*/26).string(message.description);
                    if (message.intPeakValue != null && Object.hasOwnProperty.call(message, "intPeakValue"))
                        writer.uint32(/* id 5, wireType 0 =*/40).int64(message.intPeakValue);
                    if (message.doublePeakValue != null && Object.hasOwnProperty.call(message, "doublePeakValue"))
                        writer.uint32(/* id 6, wireType 1 =*/49).double(message.doublePeakValue);
                    if (message.numeratorUnits != null && message.numeratorUnits.length)
                        for (var i = 0; i < message.numeratorUnits.length; ++i)
                            writer.uint32(/* id 7, wireType 0 =*/56).int32(message.numeratorUnits[i]);
                    if (message.denominatorUnits != null && message.denominatorUnits.length)
                        for (var i = 0; i < message.denominatorUnits.length; ++i)
                            writer.uint32(/* id 8, wireType 0 =*/64).int32(message.denominatorUnits[i]);
                    if (message.selectByDefault != null && Object.hasOwnProperty.call(message, "selectByDefault"))
                        writer.uint32(/* id 9, wireType 0 =*/72).bool(message.selectByDefault);
                    if (message.groups != null && message.groups.length)
                        for (var i = 0; i < message.groups.length; ++i)
                            writer.uint32(/* id 10, wireType 0 =*/80).int32(message.groups[i]);
                    return writer;
                };

                /**
                 * Encodes the specified GpuCounterSpec message, length delimited. Does not implicitly {@link perfetto.protos.GpuCounterDescriptor.GpuCounterSpec.verify|verify} messages.
                 * @function encodeDelimited
                 * @memberof perfetto.protos.GpuCounterDescriptor.GpuCounterSpec
                 * @static
                 * @param {perfetto.protos.GpuCounterDescriptor.IGpuCounterSpec} message GpuCounterSpec message or plain object to encode
                 * @param {$protobuf.Writer} [writer] Writer to encode to
                 * @returns {$protobuf.Writer} Writer
                 */
                GpuCounterSpec.encodeDelimited = function encodeDelimited(message, writer) {
                    return this.encode(message, writer).ldelim();
                };

                /**
                 * Decodes a GpuCounterSpec message from the specified reader or buffer.
                 * @function decode
                 * @memberof perfetto.protos.GpuCounterDescriptor.GpuCounterSpec
                 * @static
                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                 * @param {number} [length] Message length if known beforehand
                 * @returns {perfetto.protos.GpuCounterDescriptor.GpuCounterSpec} GpuCounterSpec
                 * @throws {Error} If the payload is not a reader or valid buffer
                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
                 */
                GpuCounterSpec.decode = function decode(reader, length) {
                    if (!(reader instanceof $Reader))
                        reader = $Reader.create(reader);
                    var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.GpuCounterDescriptor.GpuCounterSpec();
                    while (reader.pos < end) {
                        var tag = reader.uint32();
                        switch (tag >>> 3) {
                        case 1:
                            message.counterId = reader.uint32();
                            break;
                        case 2:
                            message.name = reader.string();
                            break;
                        case 3:
                            message.description = reader.string();
                            break;
                        case 5:
                            message.intPeakValue = reader.int64();
                            break;
                        case 6:
                            message.doublePeakValue = reader.double();
                            break;
                        case 7:
                            if (!(message.numeratorUnits && message.numeratorUnits.length))
                                message.numeratorUnits = [];
                            if ((tag & 7) === 2) {
                                var end2 = reader.uint32() + reader.pos;
                                while (reader.pos < end2)
                                    message.numeratorUnits.push(reader.int32());
                            } else
                                message.numeratorUnits.push(reader.int32());
                            break;
                        case 8:
                            if (!(message.denominatorUnits && message.denominatorUnits.length))
                                message.denominatorUnits = [];
                            if ((tag & 7) === 2) {
                                var end2 = reader.uint32() + reader.pos;
                                while (reader.pos < end2)
                                    message.denominatorUnits.push(reader.int32());
                            } else
                                message.denominatorUnits.push(reader.int32());
                            break;
                        case 9:
                            message.selectByDefault = reader.bool();
                            break;
                        case 10:
                            if (!(message.groups && message.groups.length))
                                message.groups = [];
                            if ((tag & 7) === 2) {
                                var end2 = reader.uint32() + reader.pos;
                                while (reader.pos < end2)
                                    message.groups.push(reader.int32());
                            } else
                                message.groups.push(reader.int32());
                            break;
                        default:
                            reader.skipType(tag & 7);
                            break;
                        }
                    }
                    return message;
                };

                /**
                 * Decodes a GpuCounterSpec message from the specified reader or buffer, length delimited.
                 * @function decodeDelimited
                 * @memberof perfetto.protos.GpuCounterDescriptor.GpuCounterSpec
                 * @static
                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                 * @returns {perfetto.protos.GpuCounterDescriptor.GpuCounterSpec} GpuCounterSpec
                 * @throws {Error} If the payload is not a reader or valid buffer
                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
                 */
                GpuCounterSpec.decodeDelimited = function decodeDelimited(reader) {
                    if (!(reader instanceof $Reader))
                        reader = new $Reader(reader);
                    return this.decode(reader, reader.uint32());
                };

                /**
                 * Verifies a GpuCounterSpec message.
                 * @function verify
                 * @memberof perfetto.protos.GpuCounterDescriptor.GpuCounterSpec
                 * @static
                 * @param {Object.<string,*>} message Plain object to verify
                 * @returns {string|null} `null` if valid, otherwise the reason why it is not
                 */
                GpuCounterSpec.verify = function verify(message) {
                    if (typeof message !== "object" || message === null)
                        return "object expected";
                    var properties = {};
                    if (message.counterId != null && message.hasOwnProperty("counterId"))
                        if (!$util.isInteger(message.counterId))
                            return "counterId: integer expected";
                    if (message.name != null && message.hasOwnProperty("name"))
                        if (!$util.isString(message.name))
                            return "name: string expected";
                    if (message.description != null && message.hasOwnProperty("description"))
                        if (!$util.isString(message.description))
                            return "description: string expected";
                    if (message.intPeakValue != null && message.hasOwnProperty("intPeakValue")) {
                        properties.peakValue = 1;
                        if (!$util.isInteger(message.intPeakValue) && !(message.intPeakValue && $util.isInteger(message.intPeakValue.low) && $util.isInteger(message.intPeakValue.high)))
                            return "intPeakValue: integer|Long expected";
                    }
                    if (message.doublePeakValue != null && message.hasOwnProperty("doublePeakValue")) {
                        if (properties.peakValue === 1)
                            return "peakValue: multiple values";
                        properties.peakValue = 1;
                        if (typeof message.doublePeakValue !== "number")
                            return "doublePeakValue: number expected";
                    }
                    if (message.numeratorUnits != null && message.hasOwnProperty("numeratorUnits")) {
                        if (!Array.isArray(message.numeratorUnits))
                            return "numeratorUnits: array expected";
                        for (var i = 0; i < message.numeratorUnits.length; ++i)
                            switch (message.numeratorUnits[i]) {
                            default:
                                return "numeratorUnits: enum value[] expected";
                            case 0:
                            case 1:
                            case 2:
                            case 3:
                            case 4:
                            case 5:
                            case 6:
                            case 7:
                            case 8:
                            case 9:
                            case 10:
                            case 11:
                            case 12:
                            case 13:
                            case 14:
                            case 15:
                            case 16:
                            case 17:
                            case 18:
                            case 19:
                            case 20:
                            case 21:
                            case 22:
                            case 23:
                            case 24:
                            case 25:
                            case 26:
                            case 27:
                            case 38:
                            case 39:
                            case 28:
                            case 29:
                            case 30:
                            case 31:
                            case 32:
                            case 33:
                            case 34:
                            case 35:
                            case 36:
                            case 37:
                            case 40:
                                break;
                            }
                    }
                    if (message.denominatorUnits != null && message.hasOwnProperty("denominatorUnits")) {
                        if (!Array.isArray(message.denominatorUnits))
                            return "denominatorUnits: array expected";
                        for (var i = 0; i < message.denominatorUnits.length; ++i)
                            switch (message.denominatorUnits[i]) {
                            default:
                                return "denominatorUnits: enum value[] expected";
                            case 0:
                            case 1:
                            case 2:
                            case 3:
                            case 4:
                            case 5:
                            case 6:
                            case 7:
                            case 8:
                            case 9:
                            case 10:
                            case 11:
                            case 12:
                            case 13:
                            case 14:
                            case 15:
                            case 16:
                            case 17:
                            case 18:
                            case 19:
                            case 20:
                            case 21:
                            case 22:
                            case 23:
                            case 24:
                            case 25:
                            case 26:
                            case 27:
                            case 38:
                            case 39:
                            case 28:
                            case 29:
                            case 30:
                            case 31:
                            case 32:
                            case 33:
                            case 34:
                            case 35:
                            case 36:
                            case 37:
                            case 40:
                                break;
                            }
                    }
                    if (message.selectByDefault != null && message.hasOwnProperty("selectByDefault"))
                        if (typeof message.selectByDefault !== "boolean")
                            return "selectByDefault: boolean expected";
                    if (message.groups != null && message.hasOwnProperty("groups")) {
                        if (!Array.isArray(message.groups))
                            return "groups: array expected";
                        for (var i = 0; i < message.groups.length; ++i)
                            switch (message.groups[i]) {
                            default:
                                return "groups: enum value[] expected";
                            case 0:
                            case 1:
                            case 2:
                            case 3:
                            case 4:
                            case 5:
                            case 6:
                                break;
                            }
                    }
                    return null;
                };

                /**
                 * Creates a GpuCounterSpec message from a plain object. Also converts values to their respective internal types.
                 * @function fromObject
                 * @memberof perfetto.protos.GpuCounterDescriptor.GpuCounterSpec
                 * @static
                 * @param {Object.<string,*>} object Plain object
                 * @returns {perfetto.protos.GpuCounterDescriptor.GpuCounterSpec} GpuCounterSpec
                 */
                GpuCounterSpec.fromObject = function fromObject(object) {
                    if (object instanceof $root.perfetto.protos.GpuCounterDescriptor.GpuCounterSpec)
                        return object;
                    var message = new $root.perfetto.protos.GpuCounterDescriptor.GpuCounterSpec();
                    if (object.counterId != null)
                        message.counterId = object.counterId >>> 0;
                    if (object.name != null)
                        message.name = String(object.name);
                    if (object.description != null)
                        message.description = String(object.description);
                    if (object.intPeakValue != null)
                        if ($util.Long)
                            (message.intPeakValue = $util.Long.fromValue(object.intPeakValue)).unsigned = false;
                        else if (typeof object.intPeakValue === "string")
                            message.intPeakValue = parseInt(object.intPeakValue, 10);
                        else if (typeof object.intPeakValue === "number")
                            message.intPeakValue = object.intPeakValue;
                        else if (typeof object.intPeakValue === "object")
                            message.intPeakValue = new $util.LongBits(object.intPeakValue.low >>> 0, object.intPeakValue.high >>> 0).toNumber();
                    if (object.doublePeakValue != null)
                        message.doublePeakValue = Number(object.doublePeakValue);
                    if (object.numeratorUnits) {
                        if (!Array.isArray(object.numeratorUnits))
                            throw TypeError(".perfetto.protos.GpuCounterDescriptor.GpuCounterSpec.numeratorUnits: array expected");
                        message.numeratorUnits = [];
                        for (var i = 0; i < object.numeratorUnits.length; ++i)
                            switch (object.numeratorUnits[i]) {
                            default:
                            case "NONE":
                            case 0:
                                message.numeratorUnits[i] = 0;
                                break;
                            case "BIT":
                            case 1:
                                message.numeratorUnits[i] = 1;
                                break;
                            case "KILOBIT":
                            case 2:
                                message.numeratorUnits[i] = 2;
                                break;
                            case "MEGABIT":
                            case 3:
                                message.numeratorUnits[i] = 3;
                                break;
                            case "GIGABIT":
                            case 4:
                                message.numeratorUnits[i] = 4;
                                break;
                            case "TERABIT":
                            case 5:
                                message.numeratorUnits[i] = 5;
                                break;
                            case "PETABIT":
                            case 6:
                                message.numeratorUnits[i] = 6;
                                break;
                            case "BYTE":
                            case 7:
                                message.numeratorUnits[i] = 7;
                                break;
                            case "KILOBYTE":
                            case 8:
                                message.numeratorUnits[i] = 8;
                                break;
                            case "MEGABYTE":
                            case 9:
                                message.numeratorUnits[i] = 9;
                                break;
                            case "GIGABYTE":
                            case 10:
                                message.numeratorUnits[i] = 10;
                                break;
                            case "TERABYTE":
                            case 11:
                                message.numeratorUnits[i] = 11;
                                break;
                            case "PETABYTE":
                            case 12:
                                message.numeratorUnits[i] = 12;
                                break;
                            case "HERTZ":
                            case 13:
                                message.numeratorUnits[i] = 13;
                                break;
                            case "KILOHERTZ":
                            case 14:
                                message.numeratorUnits[i] = 14;
                                break;
                            case "MEGAHERTZ":
                            case 15:
                                message.numeratorUnits[i] = 15;
                                break;
                            case "GIGAHERTZ":
                            case 16:
                                message.numeratorUnits[i] = 16;
                                break;
                            case "TERAHERTZ":
                            case 17:
                                message.numeratorUnits[i] = 17;
                                break;
                            case "PETAHERTZ":
                            case 18:
                                message.numeratorUnits[i] = 18;
                                break;
                            case "NANOSECOND":
                            case 19:
                                message.numeratorUnits[i] = 19;
                                break;
                            case "MICROSECOND":
                            case 20:
                                message.numeratorUnits[i] = 20;
                                break;
                            case "MILLISECOND":
                            case 21:
                                message.numeratorUnits[i] = 21;
                                break;
                            case "SECOND":
                            case 22:
                                message.numeratorUnits[i] = 22;
                                break;
                            case "MINUTE":
                            case 23:
                                message.numeratorUnits[i] = 23;
                                break;
                            case "HOUR":
                            case 24:
                                message.numeratorUnits[i] = 24;
                                break;
                            case "VERTEX":
                            case 25:
                                message.numeratorUnits[i] = 25;
                                break;
                            case "PIXEL":
                            case 26:
                                message.numeratorUnits[i] = 26;
                                break;
                            case "TRIANGLE":
                            case 27:
                                message.numeratorUnits[i] = 27;
                                break;
                            case "PRIMITIVE":
                            case 38:
                                message.numeratorUnits[i] = 38;
                                break;
                            case "FRAGMENT":
                            case 39:
                                message.numeratorUnits[i] = 39;
                                break;
                            case "MILLIWATT":
                            case 28:
                                message.numeratorUnits[i] = 28;
                                break;
                            case "WATT":
                            case 29:
                                message.numeratorUnits[i] = 29;
                                break;
                            case "KILOWATT":
                            case 30:
                                message.numeratorUnits[i] = 30;
                                break;
                            case "JOULE":
                            case 31:
                                message.numeratorUnits[i] = 31;
                                break;
                            case "VOLT":
                            case 32:
                                message.numeratorUnits[i] = 32;
                                break;
                            case "AMPERE":
                            case 33:
                                message.numeratorUnits[i] = 33;
                                break;
                            case "CELSIUS":
                            case 34:
                                message.numeratorUnits[i] = 34;
                                break;
                            case "FAHRENHEIT":
                            case 35:
                                message.numeratorUnits[i] = 35;
                                break;
                            case "KELVIN":
                            case 36:
                                message.numeratorUnits[i] = 36;
                                break;
                            case "PERCENT":
                            case 37:
                                message.numeratorUnits[i] = 37;
                                break;
                            case "INSTRUCTION":
                            case 40:
                                message.numeratorUnits[i] = 40;
                                break;
                            }
                    }
                    if (object.denominatorUnits) {
                        if (!Array.isArray(object.denominatorUnits))
                            throw TypeError(".perfetto.protos.GpuCounterDescriptor.GpuCounterSpec.denominatorUnits: array expected");
                        message.denominatorUnits = [];
                        for (var i = 0; i < object.denominatorUnits.length; ++i)
                            switch (object.denominatorUnits[i]) {
                            default:
                            case "NONE":
                            case 0:
                                message.denominatorUnits[i] = 0;
                                break;
                            case "BIT":
                            case 1:
                                message.denominatorUnits[i] = 1;
                                break;
                            case "KILOBIT":
                            case 2:
                                message.denominatorUnits[i] = 2;
                                break;
                            case "MEGABIT":
                            case 3:
                                message.denominatorUnits[i] = 3;
                                break;
                            case "GIGABIT":
                            case 4:
                                message.denominatorUnits[i] = 4;
                                break;
                            case "TERABIT":
                            case 5:
                                message.denominatorUnits[i] = 5;
                                break;
                            case "PETABIT":
                            case 6:
                                message.denominatorUnits[i] = 6;
                                break;
                            case "BYTE":
                            case 7:
                                message.denominatorUnits[i] = 7;
                                break;
                            case "KILOBYTE":
                            case 8:
                                message.denominatorUnits[i] = 8;
                                break;
                            case "MEGABYTE":
                            case 9:
                                message.denominatorUnits[i] = 9;
                                break;
                            case "GIGABYTE":
                            case 10:
                                message.denominatorUnits[i] = 10;
                                break;
                            case "TERABYTE":
                            case 11:
                                message.denominatorUnits[i] = 11;
                                break;
                            case "PETABYTE":
                            case 12:
                                message.denominatorUnits[i] = 12;
                                break;
                            case "HERTZ":
                            case 13:
                                message.denominatorUnits[i] = 13;
                                break;
                            case "KILOHERTZ":
                            case 14:
                                message.denominatorUnits[i] = 14;
                                break;
                            case "MEGAHERTZ":
                            case 15:
                                message.denominatorUnits[i] = 15;
                                break;
                            case "GIGAHERTZ":
                            case 16:
                                message.denominatorUnits[i] = 16;
                                break;
                            case "TERAHERTZ":
                            case 17:
                                message.denominatorUnits[i] = 17;
                                break;
                            case "PETAHERTZ":
                            case 18:
                                message.denominatorUnits[i] = 18;
                                break;
                            case "NANOSECOND":
                            case 19:
                                message.denominatorUnits[i] = 19;
                                break;
                            case "MICROSECOND":
                            case 20:
                                message.denominatorUnits[i] = 20;
                                break;
                            case "MILLISECOND":
                            case 21:
                                message.denominatorUnits[i] = 21;
                                break;
                            case "SECOND":
                            case 22:
                                message.denominatorUnits[i] = 22;
                                break;
                            case "MINUTE":
                            case 23:
                                message.denominatorUnits[i] = 23;
                                break;
                            case "HOUR":
                            case 24:
                                message.denominatorUnits[i] = 24;
                                break;
                            case "VERTEX":
                            case 25:
                                message.denominatorUnits[i] = 25;
                                break;
                            case "PIXEL":
                            case 26:
                                message.denominatorUnits[i] = 26;
                                break;
                            case "TRIANGLE":
                            case 27:
                                message.denominatorUnits[i] = 27;
                                break;
                            case "PRIMITIVE":
                            case 38:
                                message.denominatorUnits[i] = 38;
                                break;
                            case "FRAGMENT":
                            case 39:
                                message.denominatorUnits[i] = 39;
                                break;
                            case "MILLIWATT":
                            case 28:
                                message.denominatorUnits[i] = 28;
                                break;
                            case "WATT":
                            case 29:
                                message.denominatorUnits[i] = 29;
                                break;
                            case "KILOWATT":
                            case 30:
                                message.denominatorUnits[i] = 30;
                                break;
                            case "JOULE":
                            case 31:
                                message.denominatorUnits[i] = 31;
                                break;
                            case "VOLT":
                            case 32:
                                message.denominatorUnits[i] = 32;
                                break;
                            case "AMPERE":
                            case 33:
                                message.denominatorUnits[i] = 33;
                                break;
                            case "CELSIUS":
                            case 34:
                                message.denominatorUnits[i] = 34;
                                break;
                            case "FAHRENHEIT":
                            case 35:
                                message.denominatorUnits[i] = 35;
                                break;
                            case "KELVIN":
                            case 36:
                                message.denominatorUnits[i] = 36;
                                break;
                            case "PERCENT":
                            case 37:
                                message.denominatorUnits[i] = 37;
                                break;
                            case "INSTRUCTION":
                            case 40:
                                message.denominatorUnits[i] = 40;
                                break;
                            }
                    }
                    if (object.selectByDefault != null)
                        message.selectByDefault = Boolean(object.selectByDefault);
                    if (object.groups) {
                        if (!Array.isArray(object.groups))
                            throw TypeError(".perfetto.protos.GpuCounterDescriptor.GpuCounterSpec.groups: array expected");
                        message.groups = [];
                        for (var i = 0; i < object.groups.length; ++i)
                            switch (object.groups[i]) {
                            default:
                            case "UNCLASSIFIED":
                            case 0:
                                message.groups[i] = 0;
                                break;
                            case "SYSTEM":
                            case 1:
                                message.groups[i] = 1;
                                break;
                            case "VERTICES":
                            case 2:
                                message.groups[i] = 2;
                                break;
                            case "FRAGMENTS":
                            case 3:
                                message.groups[i] = 3;
                                break;
                            case "PRIMITIVES":
                            case 4:
                                message.groups[i] = 4;
                                break;
                            case "MEMORY":
                            case 5:
                                message.groups[i] = 5;
                                break;
                            case "COMPUTE":
                            case 6:
                                message.groups[i] = 6;
                                break;
                            }
                    }
                    return message;
                };

                /**
                 * Creates a plain object from a GpuCounterSpec message. Also converts values to other types if specified.
                 * @function toObject
                 * @memberof perfetto.protos.GpuCounterDescriptor.GpuCounterSpec
                 * @static
                 * @param {perfetto.protos.GpuCounterDescriptor.GpuCounterSpec} message GpuCounterSpec
                 * @param {$protobuf.IConversionOptions} [options] Conversion options
                 * @returns {Object.<string,*>} Plain object
                 */
                GpuCounterSpec.toObject = function toObject(message, options) {
                    if (!options)
                        options = {};
                    var object = {};
                    if (options.arrays || options.defaults) {
                        object.numeratorUnits = [];
                        object.denominatorUnits = [];
                        object.groups = [];
                    }
                    if (options.defaults) {
                        object.counterId = 0;
                        object.name = "";
                        object.description = "";
                        object.selectByDefault = false;
                    }
                    if (message.counterId != null && message.hasOwnProperty("counterId"))
                        object.counterId = message.counterId;
                    if (message.name != null && message.hasOwnProperty("name"))
                        object.name = message.name;
                    if (message.description != null && message.hasOwnProperty("description"))
                        object.description = message.description;
                    if (message.intPeakValue != null && message.hasOwnProperty("intPeakValue")) {
                        if (typeof message.intPeakValue === "number")
                            object.intPeakValue = options.longs === String ? String(message.intPeakValue) : message.intPeakValue;
                        else
                            object.intPeakValue = options.longs === String ? $util.Long.prototype.toString.call(message.intPeakValue) : options.longs === Number ? new $util.LongBits(message.intPeakValue.low >>> 0, message.intPeakValue.high >>> 0).toNumber() : message.intPeakValue;
                        if (options.oneofs)
                            object.peakValue = "intPeakValue";
                    }
                    if (message.doublePeakValue != null && message.hasOwnProperty("doublePeakValue")) {
                        object.doublePeakValue = options.json && !isFinite(message.doublePeakValue) ? String(message.doublePeakValue) : message.doublePeakValue;
                        if (options.oneofs)
                            object.peakValue = "doublePeakValue";
                    }
                    if (message.numeratorUnits && message.numeratorUnits.length) {
                        object.numeratorUnits = [];
                        for (var j = 0; j < message.numeratorUnits.length; ++j)
                            object.numeratorUnits[j] = options.enums === String ? $root.perfetto.protos.GpuCounterDescriptor.MeasureUnit[message.numeratorUnits[j]] : message.numeratorUnits[j];
                    }
                    if (message.denominatorUnits && message.denominatorUnits.length) {
                        object.denominatorUnits = [];
                        for (var j = 0; j < message.denominatorUnits.length; ++j)
                            object.denominatorUnits[j] = options.enums === String ? $root.perfetto.protos.GpuCounterDescriptor.MeasureUnit[message.denominatorUnits[j]] : message.denominatorUnits[j];
                    }
                    if (message.selectByDefault != null && message.hasOwnProperty("selectByDefault"))
                        object.selectByDefault = message.selectByDefault;
                    if (message.groups && message.groups.length) {
                        object.groups = [];
                        for (var j = 0; j < message.groups.length; ++j)
                            object.groups[j] = options.enums === String ? $root.perfetto.protos.GpuCounterDescriptor.GpuCounterGroup[message.groups[j]] : message.groups[j];
                    }
                    return object;
                };

                /**
                 * Converts this GpuCounterSpec to JSON.
                 * @function toJSON
                 * @memberof perfetto.protos.GpuCounterDescriptor.GpuCounterSpec
                 * @instance
                 * @returns {Object.<string,*>} JSON object
                 */
                GpuCounterSpec.prototype.toJSON = function toJSON() {
                    return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
                };

                return GpuCounterSpec;
            })();

            GpuCounterDescriptor.GpuCounterBlock = (function() {

                /**
                 * Properties of a GpuCounterBlock.
                 * @memberof perfetto.protos.GpuCounterDescriptor
                 * @interface IGpuCounterBlock
                 * @property {number|null} [blockId] GpuCounterBlock blockId
                 * @property {number|null} [blockCapacity] GpuCounterBlock blockCapacity
                 * @property {string|null} [name] GpuCounterBlock name
                 * @property {string|null} [description] GpuCounterBlock description
                 * @property {Array.<number>|null} [counterIds] GpuCounterBlock counterIds
                 */

                /**
                 * Constructs a new GpuCounterBlock.
                 * @memberof perfetto.protos.GpuCounterDescriptor
                 * @classdesc Represents a GpuCounterBlock.
                 * @implements IGpuCounterBlock
                 * @constructor
                 * @param {perfetto.protos.GpuCounterDescriptor.IGpuCounterBlock=} [properties] Properties to set
                 */
                function GpuCounterBlock(properties) {
                    this.counterIds = [];
                    if (properties)
                        for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                            if (properties[keys[i]] != null)
                                this[keys[i]] = properties[keys[i]];
                }

                /**
                 * GpuCounterBlock blockId.
                 * @member {number} blockId
                 * @memberof perfetto.protos.GpuCounterDescriptor.GpuCounterBlock
                 * @instance
                 */
                GpuCounterBlock.prototype.blockId = 0;

                /**
                 * GpuCounterBlock blockCapacity.
                 * @member {number} blockCapacity
                 * @memberof perfetto.protos.GpuCounterDescriptor.GpuCounterBlock
                 * @instance
                 */
                GpuCounterBlock.prototype.blockCapacity = 0;

                /**
                 * GpuCounterBlock name.
                 * @member {string} name
                 * @memberof perfetto.protos.GpuCounterDescriptor.GpuCounterBlock
                 * @instance
                 */
                GpuCounterBlock.prototype.name = "";

                /**
                 * GpuCounterBlock description.
                 * @member {string} description
                 * @memberof perfetto.protos.GpuCounterDescriptor.GpuCounterBlock
                 * @instance
                 */
                GpuCounterBlock.prototype.description = "";

                /**
                 * GpuCounterBlock counterIds.
                 * @member {Array.<number>} counterIds
                 * @memberof perfetto.protos.GpuCounterDescriptor.GpuCounterBlock
                 * @instance
                 */
                GpuCounterBlock.prototype.counterIds = $util.emptyArray;

                /**
                 * Creates a new GpuCounterBlock instance using the specified properties.
                 * @function create
                 * @memberof perfetto.protos.GpuCounterDescriptor.GpuCounterBlock
                 * @static
                 * @param {perfetto.protos.GpuCounterDescriptor.IGpuCounterBlock=} [properties] Properties to set
                 * @returns {perfetto.protos.GpuCounterDescriptor.GpuCounterBlock} GpuCounterBlock instance
                 */
                GpuCounterBlock.create = function create(properties) {
                    return new GpuCounterBlock(properties);
                };

                /**
                 * Encodes the specified GpuCounterBlock message. Does not implicitly {@link perfetto.protos.GpuCounterDescriptor.GpuCounterBlock.verify|verify} messages.
                 * @function encode
                 * @memberof perfetto.protos.GpuCounterDescriptor.GpuCounterBlock
                 * @static
                 * @param {perfetto.protos.GpuCounterDescriptor.IGpuCounterBlock} message GpuCounterBlock message or plain object to encode
                 * @param {$protobuf.Writer} [writer] Writer to encode to
                 * @returns {$protobuf.Writer} Writer
                 */
                GpuCounterBlock.encode = function encode(message, writer) {
                    if (!writer)
                        writer = $Writer.create();
                    if (message.blockId != null && Object.hasOwnProperty.call(message, "blockId"))
                        writer.uint32(/* id 1, wireType 0 =*/8).uint32(message.blockId);
                    if (message.blockCapacity != null && Object.hasOwnProperty.call(message, "blockCapacity"))
                        writer.uint32(/* id 2, wireType 0 =*/16).uint32(message.blockCapacity);
                    if (message.name != null && Object.hasOwnProperty.call(message, "name"))
                        writer.uint32(/* id 3, wireType 2 =*/26).string(message.name);
                    if (message.description != null && Object.hasOwnProperty.call(message, "description"))
                        writer.uint32(/* id 4, wireType 2 =*/34).string(message.description);
                    if (message.counterIds != null && message.counterIds.length)
                        for (var i = 0; i < message.counterIds.length; ++i)
                            writer.uint32(/* id 5, wireType 0 =*/40).uint32(message.counterIds[i]);
                    return writer;
                };

                /**
                 * Encodes the specified GpuCounterBlock message, length delimited. Does not implicitly {@link perfetto.protos.GpuCounterDescriptor.GpuCounterBlock.verify|verify} messages.
                 * @function encodeDelimited
                 * @memberof perfetto.protos.GpuCounterDescriptor.GpuCounterBlock
                 * @static
                 * @param {perfetto.protos.GpuCounterDescriptor.IGpuCounterBlock} message GpuCounterBlock message or plain object to encode
                 * @param {$protobuf.Writer} [writer] Writer to encode to
                 * @returns {$protobuf.Writer} Writer
                 */
                GpuCounterBlock.encodeDelimited = function encodeDelimited(message, writer) {
                    return this.encode(message, writer).ldelim();
                };

                /**
                 * Decodes a GpuCounterBlock message from the specified reader or buffer.
                 * @function decode
                 * @memberof perfetto.protos.GpuCounterDescriptor.GpuCounterBlock
                 * @static
                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                 * @param {number} [length] Message length if known beforehand
                 * @returns {perfetto.protos.GpuCounterDescriptor.GpuCounterBlock} GpuCounterBlock
                 * @throws {Error} If the payload is not a reader or valid buffer
                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
                 */
                GpuCounterBlock.decode = function decode(reader, length) {
                    if (!(reader instanceof $Reader))
                        reader = $Reader.create(reader);
                    var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.GpuCounterDescriptor.GpuCounterBlock();
                    while (reader.pos < end) {
                        var tag = reader.uint32();
                        switch (tag >>> 3) {
                        case 1:
                            message.blockId = reader.uint32();
                            break;
                        case 2:
                            message.blockCapacity = reader.uint32();
                            break;
                        case 3:
                            message.name = reader.string();
                            break;
                        case 4:
                            message.description = reader.string();
                            break;
                        case 5:
                            if (!(message.counterIds && message.counterIds.length))
                                message.counterIds = [];
                            if ((tag & 7) === 2) {
                                var end2 = reader.uint32() + reader.pos;
                                while (reader.pos < end2)
                                    message.counterIds.push(reader.uint32());
                            } else
                                message.counterIds.push(reader.uint32());
                            break;
                        default:
                            reader.skipType(tag & 7);
                            break;
                        }
                    }
                    return message;
                };

                /**
                 * Decodes a GpuCounterBlock message from the specified reader or buffer, length delimited.
                 * @function decodeDelimited
                 * @memberof perfetto.protos.GpuCounterDescriptor.GpuCounterBlock
                 * @static
                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                 * @returns {perfetto.protos.GpuCounterDescriptor.GpuCounterBlock} GpuCounterBlock
                 * @throws {Error} If the payload is not a reader or valid buffer
                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
                 */
                GpuCounterBlock.decodeDelimited = function decodeDelimited(reader) {
                    if (!(reader instanceof $Reader))
                        reader = new $Reader(reader);
                    return this.decode(reader, reader.uint32());
                };

                /**
                 * Verifies a GpuCounterBlock message.
                 * @function verify
                 * @memberof perfetto.protos.GpuCounterDescriptor.GpuCounterBlock
                 * @static
                 * @param {Object.<string,*>} message Plain object to verify
                 * @returns {string|null} `null` if valid, otherwise the reason why it is not
                 */
                GpuCounterBlock.verify = function verify(message) {
                    if (typeof message !== "object" || message === null)
                        return "object expected";
                    if (message.blockId != null && message.hasOwnProperty("blockId"))
                        if (!$util.isInteger(message.blockId))
                            return "blockId: integer expected";
                    if (message.blockCapacity != null && message.hasOwnProperty("blockCapacity"))
                        if (!$util.isInteger(message.blockCapacity))
                            return "blockCapacity: integer expected";
                    if (message.name != null && message.hasOwnProperty("name"))
                        if (!$util.isString(message.name))
                            return "name: string expected";
                    if (message.description != null && message.hasOwnProperty("description"))
                        if (!$util.isString(message.description))
                            return "description: string expected";
                    if (message.counterIds != null && message.hasOwnProperty("counterIds")) {
                        if (!Array.isArray(message.counterIds))
                            return "counterIds: array expected";
                        for (var i = 0; i < message.counterIds.length; ++i)
                            if (!$util.isInteger(message.counterIds[i]))
                                return "counterIds: integer[] expected";
                    }
                    return null;
                };

                /**
                 * Creates a GpuCounterBlock message from a plain object. Also converts values to their respective internal types.
                 * @function fromObject
                 * @memberof perfetto.protos.GpuCounterDescriptor.GpuCounterBlock
                 * @static
                 * @param {Object.<string,*>} object Plain object
                 * @returns {perfetto.protos.GpuCounterDescriptor.GpuCounterBlock} GpuCounterBlock
                 */
                GpuCounterBlock.fromObject = function fromObject(object) {
                    if (object instanceof $root.perfetto.protos.GpuCounterDescriptor.GpuCounterBlock)
                        return object;
                    var message = new $root.perfetto.protos.GpuCounterDescriptor.GpuCounterBlock();
                    if (object.blockId != null)
                        message.blockId = object.blockId >>> 0;
                    if (object.blockCapacity != null)
                        message.blockCapacity = object.blockCapacity >>> 0;
                    if (object.name != null)
                        message.name = String(object.name);
                    if (object.description != null)
                        message.description = String(object.description);
                    if (object.counterIds) {
                        if (!Array.isArray(object.counterIds))
                            throw TypeError(".perfetto.protos.GpuCounterDescriptor.GpuCounterBlock.counterIds: array expected");
                        message.counterIds = [];
                        for (var i = 0; i < object.counterIds.length; ++i)
                            message.counterIds[i] = object.counterIds[i] >>> 0;
                    }
                    return message;
                };

                /**
                 * Creates a plain object from a GpuCounterBlock message. Also converts values to other types if specified.
                 * @function toObject
                 * @memberof perfetto.protos.GpuCounterDescriptor.GpuCounterBlock
                 * @static
                 * @param {perfetto.protos.GpuCounterDescriptor.GpuCounterBlock} message GpuCounterBlock
                 * @param {$protobuf.IConversionOptions} [options] Conversion options
                 * @returns {Object.<string,*>} Plain object
                 */
                GpuCounterBlock.toObject = function toObject(message, options) {
                    if (!options)
                        options = {};
                    var object = {};
                    if (options.arrays || options.defaults)
                        object.counterIds = [];
                    if (options.defaults) {
                        object.blockId = 0;
                        object.blockCapacity = 0;
                        object.name = "";
                        object.description = "";
                    }
                    if (message.blockId != null && message.hasOwnProperty("blockId"))
                        object.blockId = message.blockId;
                    if (message.blockCapacity != null && message.hasOwnProperty("blockCapacity"))
                        object.blockCapacity = message.blockCapacity;
                    if (message.name != null && message.hasOwnProperty("name"))
                        object.name = message.name;
                    if (message.description != null && message.hasOwnProperty("description"))
                        object.description = message.description;
                    if (message.counterIds && message.counterIds.length) {
                        object.counterIds = [];
                        for (var j = 0; j < message.counterIds.length; ++j)
                            object.counterIds[j] = message.counterIds[j];
                    }
                    return object;
                };

                /**
                 * Converts this GpuCounterBlock to JSON.
                 * @function toJSON
                 * @memberof perfetto.protos.GpuCounterDescriptor.GpuCounterBlock
                 * @instance
                 * @returns {Object.<string,*>} JSON object
                 */
                GpuCounterBlock.prototype.toJSON = function toJSON() {
                    return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
                };

                return GpuCounterBlock;
            })();

            /**
             * MeasureUnit enum.
             * @name perfetto.protos.GpuCounterDescriptor.MeasureUnit
             * @enum {number}
             * @property {number} NONE=0 NONE value
             * @property {number} BIT=1 BIT value
             * @property {number} KILOBIT=2 KILOBIT value
             * @property {number} MEGABIT=3 MEGABIT value
             * @property {number} GIGABIT=4 GIGABIT value
             * @property {number} TERABIT=5 TERABIT value
             * @property {number} PETABIT=6 PETABIT value
             * @property {number} BYTE=7 BYTE value
             * @property {number} KILOBYTE=8 KILOBYTE value
             * @property {number} MEGABYTE=9 MEGABYTE value
             * @property {number} GIGABYTE=10 GIGABYTE value
             * @property {number} TERABYTE=11 TERABYTE value
             * @property {number} PETABYTE=12 PETABYTE value
             * @property {number} HERTZ=13 HERTZ value
             * @property {number} KILOHERTZ=14 KILOHERTZ value
             * @property {number} MEGAHERTZ=15 MEGAHERTZ value
             * @property {number} GIGAHERTZ=16 GIGAHERTZ value
             * @property {number} TERAHERTZ=17 TERAHERTZ value
             * @property {number} PETAHERTZ=18 PETAHERTZ value
             * @property {number} NANOSECOND=19 NANOSECOND value
             * @property {number} MICROSECOND=20 MICROSECOND value
             * @property {number} MILLISECOND=21 MILLISECOND value
             * @property {number} SECOND=22 SECOND value
             * @property {number} MINUTE=23 MINUTE value
             * @property {number} HOUR=24 HOUR value
             * @property {number} VERTEX=25 VERTEX value
             * @property {number} PIXEL=26 PIXEL value
             * @property {number} TRIANGLE=27 TRIANGLE value
             * @property {number} PRIMITIVE=38 PRIMITIVE value
             * @property {number} FRAGMENT=39 FRAGMENT value
             * @property {number} MILLIWATT=28 MILLIWATT value
             * @property {number} WATT=29 WATT value
             * @property {number} KILOWATT=30 KILOWATT value
             * @property {number} JOULE=31 JOULE value
             * @property {number} VOLT=32 VOLT value
             * @property {number} AMPERE=33 AMPERE value
             * @property {number} CELSIUS=34 CELSIUS value
             * @property {number} FAHRENHEIT=35 FAHRENHEIT value
             * @property {number} KELVIN=36 KELVIN value
             * @property {number} PERCENT=37 PERCENT value
             * @property {number} INSTRUCTION=40 INSTRUCTION value
             */
            GpuCounterDescriptor.MeasureUnit = (function() {
                var valuesById = {}, values = Object.create(valuesById);
                values[valuesById[0] = "NONE"] = 0;
                values[valuesById[1] = "BIT"] = 1;
                values[valuesById[2] = "KILOBIT"] = 2;
                values[valuesById[3] = "MEGABIT"] = 3;
                values[valuesById[4] = "GIGABIT"] = 4;
                values[valuesById[5] = "TERABIT"] = 5;
                values[valuesById[6] = "PETABIT"] = 6;
                values[valuesById[7] = "BYTE"] = 7;
                values[valuesById[8] = "KILOBYTE"] = 8;
                values[valuesById[9] = "MEGABYTE"] = 9;
                values[valuesById[10] = "GIGABYTE"] = 10;
                values[valuesById[11] = "TERABYTE"] = 11;
                values[valuesById[12] = "PETABYTE"] = 12;
                values[valuesById[13] = "HERTZ"] = 13;
                values[valuesById[14] = "KILOHERTZ"] = 14;
                values[valuesById[15] = "MEGAHERTZ"] = 15;
                values[valuesById[16] = "GIGAHERTZ"] = 16;
                values[valuesById[17] = "TERAHERTZ"] = 17;
                values[valuesById[18] = "PETAHERTZ"] = 18;
                values[valuesById[19] = "NANOSECOND"] = 19;
                values[valuesById[20] = "MICROSECOND"] = 20;
                values[valuesById[21] = "MILLISECOND"] = 21;
                values[valuesById[22] = "SECOND"] = 22;
                values[valuesById[23] = "MINUTE"] = 23;
                values[valuesById[24] = "HOUR"] = 24;
                values[valuesById[25] = "VERTEX"] = 25;
                values[valuesById[26] = "PIXEL"] = 26;
                values[valuesById[27] = "TRIANGLE"] = 27;
                values[valuesById[38] = "PRIMITIVE"] = 38;
                values[valuesById[39] = "FRAGMENT"] = 39;
                values[valuesById[28] = "MILLIWATT"] = 28;
                values[valuesById[29] = "WATT"] = 29;
                values[valuesById[30] = "KILOWATT"] = 30;
                values[valuesById[31] = "JOULE"] = 31;
                values[valuesById[32] = "VOLT"] = 32;
                values[valuesById[33] = "AMPERE"] = 33;
                values[valuesById[34] = "CELSIUS"] = 34;
                values[valuesById[35] = "FAHRENHEIT"] = 35;
                values[valuesById[36] = "KELVIN"] = 36;
                values[valuesById[37] = "PERCENT"] = 37;
                values[valuesById[40] = "INSTRUCTION"] = 40;
                return values;
            })();

            return GpuCounterDescriptor;
        })();

        protos.TrackEventCategory = (function() {

            /**
             * Properties of a TrackEventCategory.
             * @memberof perfetto.protos
             * @interface ITrackEventCategory
             * @property {string|null} [name] TrackEventCategory name
             * @property {string|null} [description] TrackEventCategory description
             * @property {Array.<string>|null} [tags] TrackEventCategory tags
             */

            /**
             * Constructs a new TrackEventCategory.
             * @memberof perfetto.protos
             * @classdesc Represents a TrackEventCategory.
             * @implements ITrackEventCategory
             * @constructor
             * @param {perfetto.protos.ITrackEventCategory=} [properties] Properties to set
             */
            function TrackEventCategory(properties) {
                this.tags = [];
                if (properties)
                    for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                        if (properties[keys[i]] != null)
                            this[keys[i]] = properties[keys[i]];
            }

            /**
             * TrackEventCategory name.
             * @member {string} name
             * @memberof perfetto.protos.TrackEventCategory
             * @instance
             */
            TrackEventCategory.prototype.name = "";

            /**
             * TrackEventCategory description.
             * @member {string} description
             * @memberof perfetto.protos.TrackEventCategory
             * @instance
             */
            TrackEventCategory.prototype.description = "";

            /**
             * TrackEventCategory tags.
             * @member {Array.<string>} tags
             * @memberof perfetto.protos.TrackEventCategory
             * @instance
             */
            TrackEventCategory.prototype.tags = $util.emptyArray;

            /**
             * Creates a new TrackEventCategory instance using the specified properties.
             * @function create
             * @memberof perfetto.protos.TrackEventCategory
             * @static
             * @param {perfetto.protos.ITrackEventCategory=} [properties] Properties to set
             * @returns {perfetto.protos.TrackEventCategory} TrackEventCategory instance
             */
            TrackEventCategory.create = function create(properties) {
                return new TrackEventCategory(properties);
            };

            /**
             * Encodes the specified TrackEventCategory message. Does not implicitly {@link perfetto.protos.TrackEventCategory.verify|verify} messages.
             * @function encode
             * @memberof perfetto.protos.TrackEventCategory
             * @static
             * @param {perfetto.protos.ITrackEventCategory} message TrackEventCategory message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            TrackEventCategory.encode = function encode(message, writer) {
                if (!writer)
                    writer = $Writer.create();
                if (message.name != null && Object.hasOwnProperty.call(message, "name"))
                    writer.uint32(/* id 1, wireType 2 =*/10).string(message.name);
                if (message.description != null && Object.hasOwnProperty.call(message, "description"))
                    writer.uint32(/* id 2, wireType 2 =*/18).string(message.description);
                if (message.tags != null && message.tags.length)
                    for (var i = 0; i < message.tags.length; ++i)
                        writer.uint32(/* id 3, wireType 2 =*/26).string(message.tags[i]);
                return writer;
            };

            /**
             * Encodes the specified TrackEventCategory message, length delimited. Does not implicitly {@link perfetto.protos.TrackEventCategory.verify|verify} messages.
             * @function encodeDelimited
             * @memberof perfetto.protos.TrackEventCategory
             * @static
             * @param {perfetto.protos.ITrackEventCategory} message TrackEventCategory message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            TrackEventCategory.encodeDelimited = function encodeDelimited(message, writer) {
                return this.encode(message, writer).ldelim();
            };

            /**
             * Decodes a TrackEventCategory message from the specified reader or buffer.
             * @function decode
             * @memberof perfetto.protos.TrackEventCategory
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @param {number} [length] Message length if known beforehand
             * @returns {perfetto.protos.TrackEventCategory} TrackEventCategory
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            TrackEventCategory.decode = function decode(reader, length) {
                if (!(reader instanceof $Reader))
                    reader = $Reader.create(reader);
                var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.TrackEventCategory();
                while (reader.pos < end) {
                    var tag = reader.uint32();
                    switch (tag >>> 3) {
                    case 1:
                        message.name = reader.string();
                        break;
                    case 2:
                        message.description = reader.string();
                        break;
                    case 3:
                        if (!(message.tags && message.tags.length))
                            message.tags = [];
                        message.tags.push(reader.string());
                        break;
                    default:
                        reader.skipType(tag & 7);
                        break;
                    }
                }
                return message;
            };

            /**
             * Decodes a TrackEventCategory message from the specified reader or buffer, length delimited.
             * @function decodeDelimited
             * @memberof perfetto.protos.TrackEventCategory
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @returns {perfetto.protos.TrackEventCategory} TrackEventCategory
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            TrackEventCategory.decodeDelimited = function decodeDelimited(reader) {
                if (!(reader instanceof $Reader))
                    reader = new $Reader(reader);
                return this.decode(reader, reader.uint32());
            };

            /**
             * Verifies a TrackEventCategory message.
             * @function verify
             * @memberof perfetto.protos.TrackEventCategory
             * @static
             * @param {Object.<string,*>} message Plain object to verify
             * @returns {string|null} `null` if valid, otherwise the reason why it is not
             */
            TrackEventCategory.verify = function verify(message) {
                if (typeof message !== "object" || message === null)
                    return "object expected";
                if (message.name != null && message.hasOwnProperty("name"))
                    if (!$util.isString(message.name))
                        return "name: string expected";
                if (message.description != null && message.hasOwnProperty("description"))
                    if (!$util.isString(message.description))
                        return "description: string expected";
                if (message.tags != null && message.hasOwnProperty("tags")) {
                    if (!Array.isArray(message.tags))
                        return "tags: array expected";
                    for (var i = 0; i < message.tags.length; ++i)
                        if (!$util.isString(message.tags[i]))
                            return "tags: string[] expected";
                }
                return null;
            };

            /**
             * Creates a TrackEventCategory message from a plain object. Also converts values to their respective internal types.
             * @function fromObject
             * @memberof perfetto.protos.TrackEventCategory
             * @static
             * @param {Object.<string,*>} object Plain object
             * @returns {perfetto.protos.TrackEventCategory} TrackEventCategory
             */
            TrackEventCategory.fromObject = function fromObject(object) {
                if (object instanceof $root.perfetto.protos.TrackEventCategory)
                    return object;
                var message = new $root.perfetto.protos.TrackEventCategory();
                if (object.name != null)
                    message.name = String(object.name);
                if (object.description != null)
                    message.description = String(object.description);
                if (object.tags) {
                    if (!Array.isArray(object.tags))
                        throw TypeError(".perfetto.protos.TrackEventCategory.tags: array expected");
                    message.tags = [];
                    for (var i = 0; i < object.tags.length; ++i)
                        message.tags[i] = String(object.tags[i]);
                }
                return message;
            };

            /**
             * Creates a plain object from a TrackEventCategory message. Also converts values to other types if specified.
             * @function toObject
             * @memberof perfetto.protos.TrackEventCategory
             * @static
             * @param {perfetto.protos.TrackEventCategory} message TrackEventCategory
             * @param {$protobuf.IConversionOptions} [options] Conversion options
             * @returns {Object.<string,*>} Plain object
             */
            TrackEventCategory.toObject = function toObject(message, options) {
                if (!options)
                    options = {};
                var object = {};
                if (options.arrays || options.defaults)
                    object.tags = [];
                if (options.defaults) {
                    object.name = "";
                    object.description = "";
                }
                if (message.name != null && message.hasOwnProperty("name"))
                    object.name = message.name;
                if (message.description != null && message.hasOwnProperty("description"))
                    object.description = message.description;
                if (message.tags && message.tags.length) {
                    object.tags = [];
                    for (var j = 0; j < message.tags.length; ++j)
                        object.tags[j] = message.tags[j];
                }
                return object;
            };

            /**
             * Converts this TrackEventCategory to JSON.
             * @function toJSON
             * @memberof perfetto.protos.TrackEventCategory
             * @instance
             * @returns {Object.<string,*>} JSON object
             */
            TrackEventCategory.prototype.toJSON = function toJSON() {
                return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
            };

            return TrackEventCategory;
        })();

        protos.TrackEventDescriptor = (function() {

            /**
             * Properties of a TrackEventDescriptor.
             * @memberof perfetto.protos
             * @interface ITrackEventDescriptor
             * @property {Array.<perfetto.protos.ITrackEventCategory>|null} [availableCategories] TrackEventDescriptor availableCategories
             */

            /**
             * Constructs a new TrackEventDescriptor.
             * @memberof perfetto.protos
             * @classdesc Represents a TrackEventDescriptor.
             * @implements ITrackEventDescriptor
             * @constructor
             * @param {perfetto.protos.ITrackEventDescriptor=} [properties] Properties to set
             */
            function TrackEventDescriptor(properties) {
                this.availableCategories = [];
                if (properties)
                    for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                        if (properties[keys[i]] != null)
                            this[keys[i]] = properties[keys[i]];
            }

            /**
             * TrackEventDescriptor availableCategories.
             * @member {Array.<perfetto.protos.ITrackEventCategory>} availableCategories
             * @memberof perfetto.protos.TrackEventDescriptor
             * @instance
             */
            TrackEventDescriptor.prototype.availableCategories = $util.emptyArray;

            /**
             * Creates a new TrackEventDescriptor instance using the specified properties.
             * @function create
             * @memberof perfetto.protos.TrackEventDescriptor
             * @static
             * @param {perfetto.protos.ITrackEventDescriptor=} [properties] Properties to set
             * @returns {perfetto.protos.TrackEventDescriptor} TrackEventDescriptor instance
             */
            TrackEventDescriptor.create = function create(properties) {
                return new TrackEventDescriptor(properties);
            };

            /**
             * Encodes the specified TrackEventDescriptor message. Does not implicitly {@link perfetto.protos.TrackEventDescriptor.verify|verify} messages.
             * @function encode
             * @memberof perfetto.protos.TrackEventDescriptor
             * @static
             * @param {perfetto.protos.ITrackEventDescriptor} message TrackEventDescriptor message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            TrackEventDescriptor.encode = function encode(message, writer) {
                if (!writer)
                    writer = $Writer.create();
                if (message.availableCategories != null && message.availableCategories.length)
                    for (var i = 0; i < message.availableCategories.length; ++i)
                        $root.perfetto.protos.TrackEventCategory.encode(message.availableCategories[i], writer.uint32(/* id 1, wireType 2 =*/10).fork()).ldelim();
                return writer;
            };

            /**
             * Encodes the specified TrackEventDescriptor message, length delimited. Does not implicitly {@link perfetto.protos.TrackEventDescriptor.verify|verify} messages.
             * @function encodeDelimited
             * @memberof perfetto.protos.TrackEventDescriptor
             * @static
             * @param {perfetto.protos.ITrackEventDescriptor} message TrackEventDescriptor message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            TrackEventDescriptor.encodeDelimited = function encodeDelimited(message, writer) {
                return this.encode(message, writer).ldelim();
            };

            /**
             * Decodes a TrackEventDescriptor message from the specified reader or buffer.
             * @function decode
             * @memberof perfetto.protos.TrackEventDescriptor
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @param {number} [length] Message length if known beforehand
             * @returns {perfetto.protos.TrackEventDescriptor} TrackEventDescriptor
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            TrackEventDescriptor.decode = function decode(reader, length) {
                if (!(reader instanceof $Reader))
                    reader = $Reader.create(reader);
                var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.TrackEventDescriptor();
                while (reader.pos < end) {
                    var tag = reader.uint32();
                    switch (tag >>> 3) {
                    case 1:
                        if (!(message.availableCategories && message.availableCategories.length))
                            message.availableCategories = [];
                        message.availableCategories.push($root.perfetto.protos.TrackEventCategory.decode(reader, reader.uint32()));
                        break;
                    default:
                        reader.skipType(tag & 7);
                        break;
                    }
                }
                return message;
            };

            /**
             * Decodes a TrackEventDescriptor message from the specified reader or buffer, length delimited.
             * @function decodeDelimited
             * @memberof perfetto.protos.TrackEventDescriptor
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @returns {perfetto.protos.TrackEventDescriptor} TrackEventDescriptor
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            TrackEventDescriptor.decodeDelimited = function decodeDelimited(reader) {
                if (!(reader instanceof $Reader))
                    reader = new $Reader(reader);
                return this.decode(reader, reader.uint32());
            };

            /**
             * Verifies a TrackEventDescriptor message.
             * @function verify
             * @memberof perfetto.protos.TrackEventDescriptor
             * @static
             * @param {Object.<string,*>} message Plain object to verify
             * @returns {string|null} `null` if valid, otherwise the reason why it is not
             */
            TrackEventDescriptor.verify = function verify(message) {
                if (typeof message !== "object" || message === null)
                    return "object expected";
                if (message.availableCategories != null && message.hasOwnProperty("availableCategories")) {
                    if (!Array.isArray(message.availableCategories))
                        return "availableCategories: array expected";
                    for (var i = 0; i < message.availableCategories.length; ++i) {
                        var error = $root.perfetto.protos.TrackEventCategory.verify(message.availableCategories[i]);
                        if (error)
                            return "availableCategories." + error;
                    }
                }
                return null;
            };

            /**
             * Creates a TrackEventDescriptor message from a plain object. Also converts values to their respective internal types.
             * @function fromObject
             * @memberof perfetto.protos.TrackEventDescriptor
             * @static
             * @param {Object.<string,*>} object Plain object
             * @returns {perfetto.protos.TrackEventDescriptor} TrackEventDescriptor
             */
            TrackEventDescriptor.fromObject = function fromObject(object) {
                if (object instanceof $root.perfetto.protos.TrackEventDescriptor)
                    return object;
                var message = new $root.perfetto.protos.TrackEventDescriptor();
                if (object.availableCategories) {
                    if (!Array.isArray(object.availableCategories))
                        throw TypeError(".perfetto.protos.TrackEventDescriptor.availableCategories: array expected");
                    message.availableCategories = [];
                    for (var i = 0; i < object.availableCategories.length; ++i) {
                        if (typeof object.availableCategories[i] !== "object")
                            throw TypeError(".perfetto.protos.TrackEventDescriptor.availableCategories: object expected");
                        message.availableCategories[i] = $root.perfetto.protos.TrackEventCategory.fromObject(object.availableCategories[i]);
                    }
                }
                return message;
            };

            /**
             * Creates a plain object from a TrackEventDescriptor message. Also converts values to other types if specified.
             * @function toObject
             * @memberof perfetto.protos.TrackEventDescriptor
             * @static
             * @param {perfetto.protos.TrackEventDescriptor} message TrackEventDescriptor
             * @param {$protobuf.IConversionOptions} [options] Conversion options
             * @returns {Object.<string,*>} Plain object
             */
            TrackEventDescriptor.toObject = function toObject(message, options) {
                if (!options)
                    options = {};
                var object = {};
                if (options.arrays || options.defaults)
                    object.availableCategories = [];
                if (message.availableCategories && message.availableCategories.length) {
                    object.availableCategories = [];
                    for (var j = 0; j < message.availableCategories.length; ++j)
                        object.availableCategories[j] = $root.perfetto.protos.TrackEventCategory.toObject(message.availableCategories[j], options);
                }
                return object;
            };

            /**
             * Converts this TrackEventDescriptor to JSON.
             * @function toJSON
             * @memberof perfetto.protos.TrackEventDescriptor
             * @instance
             * @returns {Object.<string,*>} JSON object
             */
            TrackEventDescriptor.prototype.toJSON = function toJSON() {
                return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
            };

            return TrackEventDescriptor;
        })();

        protos.DataSourceDescriptor = (function() {

            /**
             * Properties of a DataSourceDescriptor.
             * @memberof perfetto.protos
             * @interface IDataSourceDescriptor
             * @property {string|null} [name] DataSourceDescriptor name
             * @property {boolean|null} [willNotifyOnStop] DataSourceDescriptor willNotifyOnStop
             * @property {boolean|null} [willNotifyOnStart] DataSourceDescriptor willNotifyOnStart
             * @property {boolean|null} [handlesIncrementalStateClear] DataSourceDescriptor handlesIncrementalStateClear
             * @property {perfetto.protos.IGpuCounterDescriptor|null} [gpuCounterDescriptor] DataSourceDescriptor gpuCounterDescriptor
             * @property {perfetto.protos.ITrackEventDescriptor|null} [trackEventDescriptor] DataSourceDescriptor trackEventDescriptor
             */

            /**
             * Constructs a new DataSourceDescriptor.
             * @memberof perfetto.protos
             * @classdesc Represents a DataSourceDescriptor.
             * @implements IDataSourceDescriptor
             * @constructor
             * @param {perfetto.protos.IDataSourceDescriptor=} [properties] Properties to set
             */
            function DataSourceDescriptor(properties) {
                if (properties)
                    for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                        if (properties[keys[i]] != null)
                            this[keys[i]] = properties[keys[i]];
            }

            /**
             * DataSourceDescriptor name.
             * @member {string} name
             * @memberof perfetto.protos.DataSourceDescriptor
             * @instance
             */
            DataSourceDescriptor.prototype.name = "";

            /**
             * DataSourceDescriptor willNotifyOnStop.
             * @member {boolean} willNotifyOnStop
             * @memberof perfetto.protos.DataSourceDescriptor
             * @instance
             */
            DataSourceDescriptor.prototype.willNotifyOnStop = false;

            /**
             * DataSourceDescriptor willNotifyOnStart.
             * @member {boolean} willNotifyOnStart
             * @memberof perfetto.protos.DataSourceDescriptor
             * @instance
             */
            DataSourceDescriptor.prototype.willNotifyOnStart = false;

            /**
             * DataSourceDescriptor handlesIncrementalStateClear.
             * @member {boolean} handlesIncrementalStateClear
             * @memberof perfetto.protos.DataSourceDescriptor
             * @instance
             */
            DataSourceDescriptor.prototype.handlesIncrementalStateClear = false;

            /**
             * DataSourceDescriptor gpuCounterDescriptor.
             * @member {perfetto.protos.IGpuCounterDescriptor|null|undefined} gpuCounterDescriptor
             * @memberof perfetto.protos.DataSourceDescriptor
             * @instance
             */
            DataSourceDescriptor.prototype.gpuCounterDescriptor = null;

            /**
             * DataSourceDescriptor trackEventDescriptor.
             * @member {perfetto.protos.ITrackEventDescriptor|null|undefined} trackEventDescriptor
             * @memberof perfetto.protos.DataSourceDescriptor
             * @instance
             */
            DataSourceDescriptor.prototype.trackEventDescriptor = null;

            /**
             * Creates a new DataSourceDescriptor instance using the specified properties.
             * @function create
             * @memberof perfetto.protos.DataSourceDescriptor
             * @static
             * @param {perfetto.protos.IDataSourceDescriptor=} [properties] Properties to set
             * @returns {perfetto.protos.DataSourceDescriptor} DataSourceDescriptor instance
             */
            DataSourceDescriptor.create = function create(properties) {
                return new DataSourceDescriptor(properties);
            };

            /**
             * Encodes the specified DataSourceDescriptor message. Does not implicitly {@link perfetto.protos.DataSourceDescriptor.verify|verify} messages.
             * @function encode
             * @memberof perfetto.protos.DataSourceDescriptor
             * @static
             * @param {perfetto.protos.IDataSourceDescriptor} message DataSourceDescriptor message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            DataSourceDescriptor.encode = function encode(message, writer) {
                if (!writer)
                    writer = $Writer.create();
                if (message.name != null && Object.hasOwnProperty.call(message, "name"))
                    writer.uint32(/* id 1, wireType 2 =*/10).string(message.name);
                if (message.willNotifyOnStop != null && Object.hasOwnProperty.call(message, "willNotifyOnStop"))
                    writer.uint32(/* id 2, wireType 0 =*/16).bool(message.willNotifyOnStop);
                if (message.willNotifyOnStart != null && Object.hasOwnProperty.call(message, "willNotifyOnStart"))
                    writer.uint32(/* id 3, wireType 0 =*/24).bool(message.willNotifyOnStart);
                if (message.handlesIncrementalStateClear != null && Object.hasOwnProperty.call(message, "handlesIncrementalStateClear"))
                    writer.uint32(/* id 4, wireType 0 =*/32).bool(message.handlesIncrementalStateClear);
                if (message.gpuCounterDescriptor != null && Object.hasOwnProperty.call(message, "gpuCounterDescriptor"))
                    $root.perfetto.protos.GpuCounterDescriptor.encode(message.gpuCounterDescriptor, writer.uint32(/* id 5, wireType 2 =*/42).fork()).ldelim();
                if (message.trackEventDescriptor != null && Object.hasOwnProperty.call(message, "trackEventDescriptor"))
                    $root.perfetto.protos.TrackEventDescriptor.encode(message.trackEventDescriptor, writer.uint32(/* id 6, wireType 2 =*/50).fork()).ldelim();
                return writer;
            };

            /**
             * Encodes the specified DataSourceDescriptor message, length delimited. Does not implicitly {@link perfetto.protos.DataSourceDescriptor.verify|verify} messages.
             * @function encodeDelimited
             * @memberof perfetto.protos.DataSourceDescriptor
             * @static
             * @param {perfetto.protos.IDataSourceDescriptor} message DataSourceDescriptor message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            DataSourceDescriptor.encodeDelimited = function encodeDelimited(message, writer) {
                return this.encode(message, writer).ldelim();
            };

            /**
             * Decodes a DataSourceDescriptor message from the specified reader or buffer.
             * @function decode
             * @memberof perfetto.protos.DataSourceDescriptor
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @param {number} [length] Message length if known beforehand
             * @returns {perfetto.protos.DataSourceDescriptor} DataSourceDescriptor
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            DataSourceDescriptor.decode = function decode(reader, length) {
                if (!(reader instanceof $Reader))
                    reader = $Reader.create(reader);
                var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.DataSourceDescriptor();
                while (reader.pos < end) {
                    var tag = reader.uint32();
                    switch (tag >>> 3) {
                    case 1:
                        message.name = reader.string();
                        break;
                    case 2:
                        message.willNotifyOnStop = reader.bool();
                        break;
                    case 3:
                        message.willNotifyOnStart = reader.bool();
                        break;
                    case 4:
                        message.handlesIncrementalStateClear = reader.bool();
                        break;
                    case 5:
                        message.gpuCounterDescriptor = $root.perfetto.protos.GpuCounterDescriptor.decode(reader, reader.uint32());
                        break;
                    case 6:
                        message.trackEventDescriptor = $root.perfetto.protos.TrackEventDescriptor.decode(reader, reader.uint32());
                        break;
                    default:
                        reader.skipType(tag & 7);
                        break;
                    }
                }
                return message;
            };

            /**
             * Decodes a DataSourceDescriptor message from the specified reader or buffer, length delimited.
             * @function decodeDelimited
             * @memberof perfetto.protos.DataSourceDescriptor
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @returns {perfetto.protos.DataSourceDescriptor} DataSourceDescriptor
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            DataSourceDescriptor.decodeDelimited = function decodeDelimited(reader) {
                if (!(reader instanceof $Reader))
                    reader = new $Reader(reader);
                return this.decode(reader, reader.uint32());
            };

            /**
             * Verifies a DataSourceDescriptor message.
             * @function verify
             * @memberof perfetto.protos.DataSourceDescriptor
             * @static
             * @param {Object.<string,*>} message Plain object to verify
             * @returns {string|null} `null` if valid, otherwise the reason why it is not
             */
            DataSourceDescriptor.verify = function verify(message) {
                if (typeof message !== "object" || message === null)
                    return "object expected";
                if (message.name != null && message.hasOwnProperty("name"))
                    if (!$util.isString(message.name))
                        return "name: string expected";
                if (message.willNotifyOnStop != null && message.hasOwnProperty("willNotifyOnStop"))
                    if (typeof message.willNotifyOnStop !== "boolean")
                        return "willNotifyOnStop: boolean expected";
                if (message.willNotifyOnStart != null && message.hasOwnProperty("willNotifyOnStart"))
                    if (typeof message.willNotifyOnStart !== "boolean")
                        return "willNotifyOnStart: boolean expected";
                if (message.handlesIncrementalStateClear != null && message.hasOwnProperty("handlesIncrementalStateClear"))
                    if (typeof message.handlesIncrementalStateClear !== "boolean")
                        return "handlesIncrementalStateClear: boolean expected";
                if (message.gpuCounterDescriptor != null && message.hasOwnProperty("gpuCounterDescriptor")) {
                    var error = $root.perfetto.protos.GpuCounterDescriptor.verify(message.gpuCounterDescriptor);
                    if (error)
                        return "gpuCounterDescriptor." + error;
                }
                if (message.trackEventDescriptor != null && message.hasOwnProperty("trackEventDescriptor")) {
                    var error = $root.perfetto.protos.TrackEventDescriptor.verify(message.trackEventDescriptor);
                    if (error)
                        return "trackEventDescriptor." + error;
                }
                return null;
            };

            /**
             * Creates a DataSourceDescriptor message from a plain object. Also converts values to their respective internal types.
             * @function fromObject
             * @memberof perfetto.protos.DataSourceDescriptor
             * @static
             * @param {Object.<string,*>} object Plain object
             * @returns {perfetto.protos.DataSourceDescriptor} DataSourceDescriptor
             */
            DataSourceDescriptor.fromObject = function fromObject(object) {
                if (object instanceof $root.perfetto.protos.DataSourceDescriptor)
                    return object;
                var message = new $root.perfetto.protos.DataSourceDescriptor();
                if (object.name != null)
                    message.name = String(object.name);
                if (object.willNotifyOnStop != null)
                    message.willNotifyOnStop = Boolean(object.willNotifyOnStop);
                if (object.willNotifyOnStart != null)
                    message.willNotifyOnStart = Boolean(object.willNotifyOnStart);
                if (object.handlesIncrementalStateClear != null)
                    message.handlesIncrementalStateClear = Boolean(object.handlesIncrementalStateClear);
                if (object.gpuCounterDescriptor != null) {
                    if (typeof object.gpuCounterDescriptor !== "object")
                        throw TypeError(".perfetto.protos.DataSourceDescriptor.gpuCounterDescriptor: object expected");
                    message.gpuCounterDescriptor = $root.perfetto.protos.GpuCounterDescriptor.fromObject(object.gpuCounterDescriptor);
                }
                if (object.trackEventDescriptor != null) {
                    if (typeof object.trackEventDescriptor !== "object")
                        throw TypeError(".perfetto.protos.DataSourceDescriptor.trackEventDescriptor: object expected");
                    message.trackEventDescriptor = $root.perfetto.protos.TrackEventDescriptor.fromObject(object.trackEventDescriptor);
                }
                return message;
            };

            /**
             * Creates a plain object from a DataSourceDescriptor message. Also converts values to other types if specified.
             * @function toObject
             * @memberof perfetto.protos.DataSourceDescriptor
             * @static
             * @param {perfetto.protos.DataSourceDescriptor} message DataSourceDescriptor
             * @param {$protobuf.IConversionOptions} [options] Conversion options
             * @returns {Object.<string,*>} Plain object
             */
            DataSourceDescriptor.toObject = function toObject(message, options) {
                if (!options)
                    options = {};
                var object = {};
                if (options.defaults) {
                    object.name = "";
                    object.willNotifyOnStop = false;
                    object.willNotifyOnStart = false;
                    object.handlesIncrementalStateClear = false;
                    object.gpuCounterDescriptor = null;
                    object.trackEventDescriptor = null;
                }
                if (message.name != null && message.hasOwnProperty("name"))
                    object.name = message.name;
                if (message.willNotifyOnStop != null && message.hasOwnProperty("willNotifyOnStop"))
                    object.willNotifyOnStop = message.willNotifyOnStop;
                if (message.willNotifyOnStart != null && message.hasOwnProperty("willNotifyOnStart"))
                    object.willNotifyOnStart = message.willNotifyOnStart;
                if (message.handlesIncrementalStateClear != null && message.hasOwnProperty("handlesIncrementalStateClear"))
                    object.handlesIncrementalStateClear = message.handlesIncrementalStateClear;
                if (message.gpuCounterDescriptor != null && message.hasOwnProperty("gpuCounterDescriptor"))
                    object.gpuCounterDescriptor = $root.perfetto.protos.GpuCounterDescriptor.toObject(message.gpuCounterDescriptor, options);
                if (message.trackEventDescriptor != null && message.hasOwnProperty("trackEventDescriptor"))
                    object.trackEventDescriptor = $root.perfetto.protos.TrackEventDescriptor.toObject(message.trackEventDescriptor, options);
                return object;
            };

            /**
             * Converts this DataSourceDescriptor to JSON.
             * @function toJSON
             * @memberof perfetto.protos.DataSourceDescriptor
             * @instance
             * @returns {Object.<string,*>} JSON object
             */
            DataSourceDescriptor.prototype.toJSON = function toJSON() {
                return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
            };

            return DataSourceDescriptor;
        })();

        protos.TracingServiceState = (function() {

            /**
             * Properties of a TracingServiceState.
             * @memberof perfetto.protos
             * @interface ITracingServiceState
             * @property {Array.<perfetto.protos.TracingServiceState.IProducer>|null} [producers] TracingServiceState producers
             * @property {Array.<perfetto.protos.TracingServiceState.IDataSource>|null} [dataSources] TracingServiceState dataSources
             * @property {number|null} [numSessions] TracingServiceState numSessions
             * @property {number|null} [numSessionsStarted] TracingServiceState numSessionsStarted
             * @property {string|null} [tracingServiceVersion] TracingServiceState tracingServiceVersion
             */

            /**
             * Constructs a new TracingServiceState.
             * @memberof perfetto.protos
             * @classdesc Represents a TracingServiceState.
             * @implements ITracingServiceState
             * @constructor
             * @param {perfetto.protos.ITracingServiceState=} [properties] Properties to set
             */
            function TracingServiceState(properties) {
                this.producers = [];
                this.dataSources = [];
                if (properties)
                    for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                        if (properties[keys[i]] != null)
                            this[keys[i]] = properties[keys[i]];
            }

            /**
             * TracingServiceState producers.
             * @member {Array.<perfetto.protos.TracingServiceState.IProducer>} producers
             * @memberof perfetto.protos.TracingServiceState
             * @instance
             */
            TracingServiceState.prototype.producers = $util.emptyArray;

            /**
             * TracingServiceState dataSources.
             * @member {Array.<perfetto.protos.TracingServiceState.IDataSource>} dataSources
             * @memberof perfetto.protos.TracingServiceState
             * @instance
             */
            TracingServiceState.prototype.dataSources = $util.emptyArray;

            /**
             * TracingServiceState numSessions.
             * @member {number} numSessions
             * @memberof perfetto.protos.TracingServiceState
             * @instance
             */
            TracingServiceState.prototype.numSessions = 0;

            /**
             * TracingServiceState numSessionsStarted.
             * @member {number} numSessionsStarted
             * @memberof perfetto.protos.TracingServiceState
             * @instance
             */
            TracingServiceState.prototype.numSessionsStarted = 0;

            /**
             * TracingServiceState tracingServiceVersion.
             * @member {string} tracingServiceVersion
             * @memberof perfetto.protos.TracingServiceState
             * @instance
             */
            TracingServiceState.prototype.tracingServiceVersion = "";

            /**
             * Creates a new TracingServiceState instance using the specified properties.
             * @function create
             * @memberof perfetto.protos.TracingServiceState
             * @static
             * @param {perfetto.protos.ITracingServiceState=} [properties] Properties to set
             * @returns {perfetto.protos.TracingServiceState} TracingServiceState instance
             */
            TracingServiceState.create = function create(properties) {
                return new TracingServiceState(properties);
            };

            /**
             * Encodes the specified TracingServiceState message. Does not implicitly {@link perfetto.protos.TracingServiceState.verify|verify} messages.
             * @function encode
             * @memberof perfetto.protos.TracingServiceState
             * @static
             * @param {perfetto.protos.ITracingServiceState} message TracingServiceState message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            TracingServiceState.encode = function encode(message, writer) {
                if (!writer)
                    writer = $Writer.create();
                if (message.producers != null && message.producers.length)
                    for (var i = 0; i < message.producers.length; ++i)
                        $root.perfetto.protos.TracingServiceState.Producer.encode(message.producers[i], writer.uint32(/* id 1, wireType 2 =*/10).fork()).ldelim();
                if (message.dataSources != null && message.dataSources.length)
                    for (var i = 0; i < message.dataSources.length; ++i)
                        $root.perfetto.protos.TracingServiceState.DataSource.encode(message.dataSources[i], writer.uint32(/* id 2, wireType 2 =*/18).fork()).ldelim();
                if (message.numSessions != null && Object.hasOwnProperty.call(message, "numSessions"))
                    writer.uint32(/* id 3, wireType 0 =*/24).int32(message.numSessions);
                if (message.numSessionsStarted != null && Object.hasOwnProperty.call(message, "numSessionsStarted"))
                    writer.uint32(/* id 4, wireType 0 =*/32).int32(message.numSessionsStarted);
                if (message.tracingServiceVersion != null && Object.hasOwnProperty.call(message, "tracingServiceVersion"))
                    writer.uint32(/* id 5, wireType 2 =*/42).string(message.tracingServiceVersion);
                return writer;
            };

            /**
             * Encodes the specified TracingServiceState message, length delimited. Does not implicitly {@link perfetto.protos.TracingServiceState.verify|verify} messages.
             * @function encodeDelimited
             * @memberof perfetto.protos.TracingServiceState
             * @static
             * @param {perfetto.protos.ITracingServiceState} message TracingServiceState message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            TracingServiceState.encodeDelimited = function encodeDelimited(message, writer) {
                return this.encode(message, writer).ldelim();
            };

            /**
             * Decodes a TracingServiceState message from the specified reader or buffer.
             * @function decode
             * @memberof perfetto.protos.TracingServiceState
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @param {number} [length] Message length if known beforehand
             * @returns {perfetto.protos.TracingServiceState} TracingServiceState
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            TracingServiceState.decode = function decode(reader, length) {
                if (!(reader instanceof $Reader))
                    reader = $Reader.create(reader);
                var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.TracingServiceState();
                while (reader.pos < end) {
                    var tag = reader.uint32();
                    switch (tag >>> 3) {
                    case 1:
                        if (!(message.producers && message.producers.length))
                            message.producers = [];
                        message.producers.push($root.perfetto.protos.TracingServiceState.Producer.decode(reader, reader.uint32()));
                        break;
                    case 2:
                        if (!(message.dataSources && message.dataSources.length))
                            message.dataSources = [];
                        message.dataSources.push($root.perfetto.protos.TracingServiceState.DataSource.decode(reader, reader.uint32()));
                        break;
                    case 3:
                        message.numSessions = reader.int32();
                        break;
                    case 4:
                        message.numSessionsStarted = reader.int32();
                        break;
                    case 5:
                        message.tracingServiceVersion = reader.string();
                        break;
                    default:
                        reader.skipType(tag & 7);
                        break;
                    }
                }
                return message;
            };

            /**
             * Decodes a TracingServiceState message from the specified reader or buffer, length delimited.
             * @function decodeDelimited
             * @memberof perfetto.protos.TracingServiceState
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @returns {perfetto.protos.TracingServiceState} TracingServiceState
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            TracingServiceState.decodeDelimited = function decodeDelimited(reader) {
                if (!(reader instanceof $Reader))
                    reader = new $Reader(reader);
                return this.decode(reader, reader.uint32());
            };

            /**
             * Verifies a TracingServiceState message.
             * @function verify
             * @memberof perfetto.protos.TracingServiceState
             * @static
             * @param {Object.<string,*>} message Plain object to verify
             * @returns {string|null} `null` if valid, otherwise the reason why it is not
             */
            TracingServiceState.verify = function verify(message) {
                if (typeof message !== "object" || message === null)
                    return "object expected";
                if (message.producers != null && message.hasOwnProperty("producers")) {
                    if (!Array.isArray(message.producers))
                        return "producers: array expected";
                    for (var i = 0; i < message.producers.length; ++i) {
                        var error = $root.perfetto.protos.TracingServiceState.Producer.verify(message.producers[i]);
                        if (error)
                            return "producers." + error;
                    }
                }
                if (message.dataSources != null && message.hasOwnProperty("dataSources")) {
                    if (!Array.isArray(message.dataSources))
                        return "dataSources: array expected";
                    for (var i = 0; i < message.dataSources.length; ++i) {
                        var error = $root.perfetto.protos.TracingServiceState.DataSource.verify(message.dataSources[i]);
                        if (error)
                            return "dataSources." + error;
                    }
                }
                if (message.numSessions != null && message.hasOwnProperty("numSessions"))
                    if (!$util.isInteger(message.numSessions))
                        return "numSessions: integer expected";
                if (message.numSessionsStarted != null && message.hasOwnProperty("numSessionsStarted"))
                    if (!$util.isInteger(message.numSessionsStarted))
                        return "numSessionsStarted: integer expected";
                if (message.tracingServiceVersion != null && message.hasOwnProperty("tracingServiceVersion"))
                    if (!$util.isString(message.tracingServiceVersion))
                        return "tracingServiceVersion: string expected";
                return null;
            };

            /**
             * Creates a TracingServiceState message from a plain object. Also converts values to their respective internal types.
             * @function fromObject
             * @memberof perfetto.protos.TracingServiceState
             * @static
             * @param {Object.<string,*>} object Plain object
             * @returns {perfetto.protos.TracingServiceState} TracingServiceState
             */
            TracingServiceState.fromObject = function fromObject(object) {
                if (object instanceof $root.perfetto.protos.TracingServiceState)
                    return object;
                var message = new $root.perfetto.protos.TracingServiceState();
                if (object.producers) {
                    if (!Array.isArray(object.producers))
                        throw TypeError(".perfetto.protos.TracingServiceState.producers: array expected");
                    message.producers = [];
                    for (var i = 0; i < object.producers.length; ++i) {
                        if (typeof object.producers[i] !== "object")
                            throw TypeError(".perfetto.protos.TracingServiceState.producers: object expected");
                        message.producers[i] = $root.perfetto.protos.TracingServiceState.Producer.fromObject(object.producers[i]);
                    }
                }
                if (object.dataSources) {
                    if (!Array.isArray(object.dataSources))
                        throw TypeError(".perfetto.protos.TracingServiceState.dataSources: array expected");
                    message.dataSources = [];
                    for (var i = 0; i < object.dataSources.length; ++i) {
                        if (typeof object.dataSources[i] !== "object")
                            throw TypeError(".perfetto.protos.TracingServiceState.dataSources: object expected");
                        message.dataSources[i] = $root.perfetto.protos.TracingServiceState.DataSource.fromObject(object.dataSources[i]);
                    }
                }
                if (object.numSessions != null)
                    message.numSessions = object.numSessions | 0;
                if (object.numSessionsStarted != null)
                    message.numSessionsStarted = object.numSessionsStarted | 0;
                if (object.tracingServiceVersion != null)
                    message.tracingServiceVersion = String(object.tracingServiceVersion);
                return message;
            };

            /**
             * Creates a plain object from a TracingServiceState message. Also converts values to other types if specified.
             * @function toObject
             * @memberof perfetto.protos.TracingServiceState
             * @static
             * @param {perfetto.protos.TracingServiceState} message TracingServiceState
             * @param {$protobuf.IConversionOptions} [options] Conversion options
             * @returns {Object.<string,*>} Plain object
             */
            TracingServiceState.toObject = function toObject(message, options) {
                if (!options)
                    options = {};
                var object = {};
                if (options.arrays || options.defaults) {
                    object.producers = [];
                    object.dataSources = [];
                }
                if (options.defaults) {
                    object.numSessions = 0;
                    object.numSessionsStarted = 0;
                    object.tracingServiceVersion = "";
                }
                if (message.producers && message.producers.length) {
                    object.producers = [];
                    for (var j = 0; j < message.producers.length; ++j)
                        object.producers[j] = $root.perfetto.protos.TracingServiceState.Producer.toObject(message.producers[j], options);
                }
                if (message.dataSources && message.dataSources.length) {
                    object.dataSources = [];
                    for (var j = 0; j < message.dataSources.length; ++j)
                        object.dataSources[j] = $root.perfetto.protos.TracingServiceState.DataSource.toObject(message.dataSources[j], options);
                }
                if (message.numSessions != null && message.hasOwnProperty("numSessions"))
                    object.numSessions = message.numSessions;
                if (message.numSessionsStarted != null && message.hasOwnProperty("numSessionsStarted"))
                    object.numSessionsStarted = message.numSessionsStarted;
                if (message.tracingServiceVersion != null && message.hasOwnProperty("tracingServiceVersion"))
                    object.tracingServiceVersion = message.tracingServiceVersion;
                return object;
            };

            /**
             * Converts this TracingServiceState to JSON.
             * @function toJSON
             * @memberof perfetto.protos.TracingServiceState
             * @instance
             * @returns {Object.<string,*>} JSON object
             */
            TracingServiceState.prototype.toJSON = function toJSON() {
                return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
            };

            TracingServiceState.Producer = (function() {

                /**
                 * Properties of a Producer.
                 * @memberof perfetto.protos.TracingServiceState
                 * @interface IProducer
                 * @property {number|null} [id] Producer id
                 * @property {string|null} [name] Producer name
                 * @property {number|null} [uid] Producer uid
                 * @property {string|null} [sdkVersion] Producer sdkVersion
                 */

                /**
                 * Constructs a new Producer.
                 * @memberof perfetto.protos.TracingServiceState
                 * @classdesc Represents a Producer.
                 * @implements IProducer
                 * @constructor
                 * @param {perfetto.protos.TracingServiceState.IProducer=} [properties] Properties to set
                 */
                function Producer(properties) {
                    if (properties)
                        for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                            if (properties[keys[i]] != null)
                                this[keys[i]] = properties[keys[i]];
                }

                /**
                 * Producer id.
                 * @member {number} id
                 * @memberof perfetto.protos.TracingServiceState.Producer
                 * @instance
                 */
                Producer.prototype.id = 0;

                /**
                 * Producer name.
                 * @member {string} name
                 * @memberof perfetto.protos.TracingServiceState.Producer
                 * @instance
                 */
                Producer.prototype.name = "";

                /**
                 * Producer uid.
                 * @member {number} uid
                 * @memberof perfetto.protos.TracingServiceState.Producer
                 * @instance
                 */
                Producer.prototype.uid = 0;

                /**
                 * Producer sdkVersion.
                 * @member {string} sdkVersion
                 * @memberof perfetto.protos.TracingServiceState.Producer
                 * @instance
                 */
                Producer.prototype.sdkVersion = "";

                /**
                 * Creates a new Producer instance using the specified properties.
                 * @function create
                 * @memberof perfetto.protos.TracingServiceState.Producer
                 * @static
                 * @param {perfetto.protos.TracingServiceState.IProducer=} [properties] Properties to set
                 * @returns {perfetto.protos.TracingServiceState.Producer} Producer instance
                 */
                Producer.create = function create(properties) {
                    return new Producer(properties);
                };

                /**
                 * Encodes the specified Producer message. Does not implicitly {@link perfetto.protos.TracingServiceState.Producer.verify|verify} messages.
                 * @function encode
                 * @memberof perfetto.protos.TracingServiceState.Producer
                 * @static
                 * @param {perfetto.protos.TracingServiceState.IProducer} message Producer message or plain object to encode
                 * @param {$protobuf.Writer} [writer] Writer to encode to
                 * @returns {$protobuf.Writer} Writer
                 */
                Producer.encode = function encode(message, writer) {
                    if (!writer)
                        writer = $Writer.create();
                    if (message.id != null && Object.hasOwnProperty.call(message, "id"))
                        writer.uint32(/* id 1, wireType 0 =*/8).int32(message.id);
                    if (message.name != null && Object.hasOwnProperty.call(message, "name"))
                        writer.uint32(/* id 2, wireType 2 =*/18).string(message.name);
                    if (message.uid != null && Object.hasOwnProperty.call(message, "uid"))
                        writer.uint32(/* id 3, wireType 0 =*/24).int32(message.uid);
                    if (message.sdkVersion != null && Object.hasOwnProperty.call(message, "sdkVersion"))
                        writer.uint32(/* id 4, wireType 2 =*/34).string(message.sdkVersion);
                    return writer;
                };

                /**
                 * Encodes the specified Producer message, length delimited. Does not implicitly {@link perfetto.protos.TracingServiceState.Producer.verify|verify} messages.
                 * @function encodeDelimited
                 * @memberof perfetto.protos.TracingServiceState.Producer
                 * @static
                 * @param {perfetto.protos.TracingServiceState.IProducer} message Producer message or plain object to encode
                 * @param {$protobuf.Writer} [writer] Writer to encode to
                 * @returns {$protobuf.Writer} Writer
                 */
                Producer.encodeDelimited = function encodeDelimited(message, writer) {
                    return this.encode(message, writer).ldelim();
                };

                /**
                 * Decodes a Producer message from the specified reader or buffer.
                 * @function decode
                 * @memberof perfetto.protos.TracingServiceState.Producer
                 * @static
                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                 * @param {number} [length] Message length if known beforehand
                 * @returns {perfetto.protos.TracingServiceState.Producer} Producer
                 * @throws {Error} If the payload is not a reader or valid buffer
                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
                 */
                Producer.decode = function decode(reader, length) {
                    if (!(reader instanceof $Reader))
                        reader = $Reader.create(reader);
                    var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.TracingServiceState.Producer();
                    while (reader.pos < end) {
                        var tag = reader.uint32();
                        switch (tag >>> 3) {
                        case 1:
                            message.id = reader.int32();
                            break;
                        case 2:
                            message.name = reader.string();
                            break;
                        case 3:
                            message.uid = reader.int32();
                            break;
                        case 4:
                            message.sdkVersion = reader.string();
                            break;
                        default:
                            reader.skipType(tag & 7);
                            break;
                        }
                    }
                    return message;
                };

                /**
                 * Decodes a Producer message from the specified reader or buffer, length delimited.
                 * @function decodeDelimited
                 * @memberof perfetto.protos.TracingServiceState.Producer
                 * @static
                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                 * @returns {perfetto.protos.TracingServiceState.Producer} Producer
                 * @throws {Error} If the payload is not a reader or valid buffer
                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
                 */
                Producer.decodeDelimited = function decodeDelimited(reader) {
                    if (!(reader instanceof $Reader))
                        reader = new $Reader(reader);
                    return this.decode(reader, reader.uint32());
                };

                /**
                 * Verifies a Producer message.
                 * @function verify
                 * @memberof perfetto.protos.TracingServiceState.Producer
                 * @static
                 * @param {Object.<string,*>} message Plain object to verify
                 * @returns {string|null} `null` if valid, otherwise the reason why it is not
                 */
                Producer.verify = function verify(message) {
                    if (typeof message !== "object" || message === null)
                        return "object expected";
                    if (message.id != null && message.hasOwnProperty("id"))
                        if (!$util.isInteger(message.id))
                            return "id: integer expected";
                    if (message.name != null && message.hasOwnProperty("name"))
                        if (!$util.isString(message.name))
                            return "name: string expected";
                    if (message.uid != null && message.hasOwnProperty("uid"))
                        if (!$util.isInteger(message.uid))
                            return "uid: integer expected";
                    if (message.sdkVersion != null && message.hasOwnProperty("sdkVersion"))
                        if (!$util.isString(message.sdkVersion))
                            return "sdkVersion: string expected";
                    return null;
                };

                /**
                 * Creates a Producer message from a plain object. Also converts values to their respective internal types.
                 * @function fromObject
                 * @memberof perfetto.protos.TracingServiceState.Producer
                 * @static
                 * @param {Object.<string,*>} object Plain object
                 * @returns {perfetto.protos.TracingServiceState.Producer} Producer
                 */
                Producer.fromObject = function fromObject(object) {
                    if (object instanceof $root.perfetto.protos.TracingServiceState.Producer)
                        return object;
                    var message = new $root.perfetto.protos.TracingServiceState.Producer();
                    if (object.id != null)
                        message.id = object.id | 0;
                    if (object.name != null)
                        message.name = String(object.name);
                    if (object.uid != null)
                        message.uid = object.uid | 0;
                    if (object.sdkVersion != null)
                        message.sdkVersion = String(object.sdkVersion);
                    return message;
                };

                /**
                 * Creates a plain object from a Producer message. Also converts values to other types if specified.
                 * @function toObject
                 * @memberof perfetto.protos.TracingServiceState.Producer
                 * @static
                 * @param {perfetto.protos.TracingServiceState.Producer} message Producer
                 * @param {$protobuf.IConversionOptions} [options] Conversion options
                 * @returns {Object.<string,*>} Plain object
                 */
                Producer.toObject = function toObject(message, options) {
                    if (!options)
                        options = {};
                    var object = {};
                    if (options.defaults) {
                        object.id = 0;
                        object.name = "";
                        object.uid = 0;
                        object.sdkVersion = "";
                    }
                    if (message.id != null && message.hasOwnProperty("id"))
                        object.id = message.id;
                    if (message.name != null && message.hasOwnProperty("name"))
                        object.name = message.name;
                    if (message.uid != null && message.hasOwnProperty("uid"))
                        object.uid = message.uid;
                    if (message.sdkVersion != null && message.hasOwnProperty("sdkVersion"))
                        object.sdkVersion = message.sdkVersion;
                    return object;
                };

                /**
                 * Converts this Producer to JSON.
                 * @function toJSON
                 * @memberof perfetto.protos.TracingServiceState.Producer
                 * @instance
                 * @returns {Object.<string,*>} JSON object
                 */
                Producer.prototype.toJSON = function toJSON() {
                    return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
                };

                return Producer;
            })();

            TracingServiceState.DataSource = (function() {

                /**
                 * Properties of a DataSource.
                 * @memberof perfetto.protos.TracingServiceState
                 * @interface IDataSource
                 * @property {perfetto.protos.IDataSourceDescriptor|null} [dsDescriptor] DataSource dsDescriptor
                 * @property {number|null} [producerId] DataSource producerId
                 */

                /**
                 * Constructs a new DataSource.
                 * @memberof perfetto.protos.TracingServiceState
                 * @classdesc Represents a DataSource.
                 * @implements IDataSource
                 * @constructor
                 * @param {perfetto.protos.TracingServiceState.IDataSource=} [properties] Properties to set
                 */
                function DataSource(properties) {
                    if (properties)
                        for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                            if (properties[keys[i]] != null)
                                this[keys[i]] = properties[keys[i]];
                }

                /**
                 * DataSource dsDescriptor.
                 * @member {perfetto.protos.IDataSourceDescriptor|null|undefined} dsDescriptor
                 * @memberof perfetto.protos.TracingServiceState.DataSource
                 * @instance
                 */
                DataSource.prototype.dsDescriptor = null;

                /**
                 * DataSource producerId.
                 * @member {number} producerId
                 * @memberof perfetto.protos.TracingServiceState.DataSource
                 * @instance
                 */
                DataSource.prototype.producerId = 0;

                /**
                 * Creates a new DataSource instance using the specified properties.
                 * @function create
                 * @memberof perfetto.protos.TracingServiceState.DataSource
                 * @static
                 * @param {perfetto.protos.TracingServiceState.IDataSource=} [properties] Properties to set
                 * @returns {perfetto.protos.TracingServiceState.DataSource} DataSource instance
                 */
                DataSource.create = function create(properties) {
                    return new DataSource(properties);
                };

                /**
                 * Encodes the specified DataSource message. Does not implicitly {@link perfetto.protos.TracingServiceState.DataSource.verify|verify} messages.
                 * @function encode
                 * @memberof perfetto.protos.TracingServiceState.DataSource
                 * @static
                 * @param {perfetto.protos.TracingServiceState.IDataSource} message DataSource message or plain object to encode
                 * @param {$protobuf.Writer} [writer] Writer to encode to
                 * @returns {$protobuf.Writer} Writer
                 */
                DataSource.encode = function encode(message, writer) {
                    if (!writer)
                        writer = $Writer.create();
                    if (message.dsDescriptor != null && Object.hasOwnProperty.call(message, "dsDescriptor"))
                        $root.perfetto.protos.DataSourceDescriptor.encode(message.dsDescriptor, writer.uint32(/* id 1, wireType 2 =*/10).fork()).ldelim();
                    if (message.producerId != null && Object.hasOwnProperty.call(message, "producerId"))
                        writer.uint32(/* id 2, wireType 0 =*/16).int32(message.producerId);
                    return writer;
                };

                /**
                 * Encodes the specified DataSource message, length delimited. Does not implicitly {@link perfetto.protos.TracingServiceState.DataSource.verify|verify} messages.
                 * @function encodeDelimited
                 * @memberof perfetto.protos.TracingServiceState.DataSource
                 * @static
                 * @param {perfetto.protos.TracingServiceState.IDataSource} message DataSource message or plain object to encode
                 * @param {$protobuf.Writer} [writer] Writer to encode to
                 * @returns {$protobuf.Writer} Writer
                 */
                DataSource.encodeDelimited = function encodeDelimited(message, writer) {
                    return this.encode(message, writer).ldelim();
                };

                /**
                 * Decodes a DataSource message from the specified reader or buffer.
                 * @function decode
                 * @memberof perfetto.protos.TracingServiceState.DataSource
                 * @static
                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                 * @param {number} [length] Message length if known beforehand
                 * @returns {perfetto.protos.TracingServiceState.DataSource} DataSource
                 * @throws {Error} If the payload is not a reader or valid buffer
                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
                 */
                DataSource.decode = function decode(reader, length) {
                    if (!(reader instanceof $Reader))
                        reader = $Reader.create(reader);
                    var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.TracingServiceState.DataSource();
                    while (reader.pos < end) {
                        var tag = reader.uint32();
                        switch (tag >>> 3) {
                        case 1:
                            message.dsDescriptor = $root.perfetto.protos.DataSourceDescriptor.decode(reader, reader.uint32());
                            break;
                        case 2:
                            message.producerId = reader.int32();
                            break;
                        default:
                            reader.skipType(tag & 7);
                            break;
                        }
                    }
                    return message;
                };

                /**
                 * Decodes a DataSource message from the specified reader or buffer, length delimited.
                 * @function decodeDelimited
                 * @memberof perfetto.protos.TracingServiceState.DataSource
                 * @static
                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                 * @returns {perfetto.protos.TracingServiceState.DataSource} DataSource
                 * @throws {Error} If the payload is not a reader or valid buffer
                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
                 */
                DataSource.decodeDelimited = function decodeDelimited(reader) {
                    if (!(reader instanceof $Reader))
                        reader = new $Reader(reader);
                    return this.decode(reader, reader.uint32());
                };

                /**
                 * Verifies a DataSource message.
                 * @function verify
                 * @memberof perfetto.protos.TracingServiceState.DataSource
                 * @static
                 * @param {Object.<string,*>} message Plain object to verify
                 * @returns {string|null} `null` if valid, otherwise the reason why it is not
                 */
                DataSource.verify = function verify(message) {
                    if (typeof message !== "object" || message === null)
                        return "object expected";
                    if (message.dsDescriptor != null && message.hasOwnProperty("dsDescriptor")) {
                        var error = $root.perfetto.protos.DataSourceDescriptor.verify(message.dsDescriptor);
                        if (error)
                            return "dsDescriptor." + error;
                    }
                    if (message.producerId != null && message.hasOwnProperty("producerId"))
                        if (!$util.isInteger(message.producerId))
                            return "producerId: integer expected";
                    return null;
                };

                /**
                 * Creates a DataSource message from a plain object. Also converts values to their respective internal types.
                 * @function fromObject
                 * @memberof perfetto.protos.TracingServiceState.DataSource
                 * @static
                 * @param {Object.<string,*>} object Plain object
                 * @returns {perfetto.protos.TracingServiceState.DataSource} DataSource
                 */
                DataSource.fromObject = function fromObject(object) {
                    if (object instanceof $root.perfetto.protos.TracingServiceState.DataSource)
                        return object;
                    var message = new $root.perfetto.protos.TracingServiceState.DataSource();
                    if (object.dsDescriptor != null) {
                        if (typeof object.dsDescriptor !== "object")
                            throw TypeError(".perfetto.protos.TracingServiceState.DataSource.dsDescriptor: object expected");
                        message.dsDescriptor = $root.perfetto.protos.DataSourceDescriptor.fromObject(object.dsDescriptor);
                    }
                    if (object.producerId != null)
                        message.producerId = object.producerId | 0;
                    return message;
                };

                /**
                 * Creates a plain object from a DataSource message. Also converts values to other types if specified.
                 * @function toObject
                 * @memberof perfetto.protos.TracingServiceState.DataSource
                 * @static
                 * @param {perfetto.protos.TracingServiceState.DataSource} message DataSource
                 * @param {$protobuf.IConversionOptions} [options] Conversion options
                 * @returns {Object.<string,*>} Plain object
                 */
                DataSource.toObject = function toObject(message, options) {
                    if (!options)
                        options = {};
                    var object = {};
                    if (options.defaults) {
                        object.dsDescriptor = null;
                        object.producerId = 0;
                    }
                    if (message.dsDescriptor != null && message.hasOwnProperty("dsDescriptor"))
                        object.dsDescriptor = $root.perfetto.protos.DataSourceDescriptor.toObject(message.dsDescriptor, options);
                    if (message.producerId != null && message.hasOwnProperty("producerId"))
                        object.producerId = message.producerId;
                    return object;
                };

                /**
                 * Converts this DataSource to JSON.
                 * @function toJSON
                 * @memberof perfetto.protos.TracingServiceState.DataSource
                 * @instance
                 * @returns {Object.<string,*>} JSON object
                 */
                DataSource.prototype.toJSON = function toJSON() {
                    return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
                };

                return DataSource;
            })();

            return TracingServiceState;
        })();

        /**
         * BuiltinClock enum.
         * @name perfetto.protos.BuiltinClock
         * @enum {number}
         * @property {number} BUILTIN_CLOCK_UNKNOWN=0 BUILTIN_CLOCK_UNKNOWN value
         * @property {number} BUILTIN_CLOCK_REALTIME=1 BUILTIN_CLOCK_REALTIME value
         * @property {number} BUILTIN_CLOCK_REALTIME_COARSE=2 BUILTIN_CLOCK_REALTIME_COARSE value
         * @property {number} BUILTIN_CLOCK_MONOTONIC=3 BUILTIN_CLOCK_MONOTONIC value
         * @property {number} BUILTIN_CLOCK_MONOTONIC_COARSE=4 BUILTIN_CLOCK_MONOTONIC_COARSE value
         * @property {number} BUILTIN_CLOCK_MONOTONIC_RAW=5 BUILTIN_CLOCK_MONOTONIC_RAW value
         * @property {number} BUILTIN_CLOCK_BOOTTIME=6 BUILTIN_CLOCK_BOOTTIME value
         * @property {number} BUILTIN_CLOCK_MAX_ID=63 BUILTIN_CLOCK_MAX_ID value
         */
        protos.BuiltinClock = (function() {
            var valuesById = {}, values = Object.create(valuesById);
            values[valuesById[0] = "BUILTIN_CLOCK_UNKNOWN"] = 0;
            values[valuesById[1] = "BUILTIN_CLOCK_REALTIME"] = 1;
            values[valuesById[2] = "BUILTIN_CLOCK_REALTIME_COARSE"] = 2;
            values[valuesById[3] = "BUILTIN_CLOCK_MONOTONIC"] = 3;
            values[valuesById[4] = "BUILTIN_CLOCK_MONOTONIC_COARSE"] = 4;
            values[valuesById[5] = "BUILTIN_CLOCK_MONOTONIC_RAW"] = 5;
            values[valuesById[6] = "BUILTIN_CLOCK_BOOTTIME"] = 6;
            values[valuesById[63] = "BUILTIN_CLOCK_MAX_ID"] = 63;
            return values;
        })();

        /**
         * AndroidLogId enum.
         * @name perfetto.protos.AndroidLogId
         * @enum {number}
         * @property {number} LID_DEFAULT=0 LID_DEFAULT value
         * @property {number} LID_RADIO=1 LID_RADIO value
         * @property {number} LID_EVENTS=2 LID_EVENTS value
         * @property {number} LID_SYSTEM=3 LID_SYSTEM value
         * @property {number} LID_CRASH=4 LID_CRASH value
         * @property {number} LID_STATS=5 LID_STATS value
         * @property {number} LID_SECURITY=6 LID_SECURITY value
         * @property {number} LID_KERNEL=7 LID_KERNEL value
         */
        protos.AndroidLogId = (function() {
            var valuesById = {}, values = Object.create(valuesById);
            values[valuesById[0] = "LID_DEFAULT"] = 0;
            values[valuesById[1] = "LID_RADIO"] = 1;
            values[valuesById[2] = "LID_EVENTS"] = 2;
            values[valuesById[3] = "LID_SYSTEM"] = 3;
            values[valuesById[4] = "LID_CRASH"] = 4;
            values[valuesById[5] = "LID_STATS"] = 5;
            values[valuesById[6] = "LID_SECURITY"] = 6;
            values[valuesById[7] = "LID_KERNEL"] = 7;
            return values;
        })();

        /**
         * AndroidLogPriority enum.
         * @name perfetto.protos.AndroidLogPriority
         * @enum {number}
         * @property {number} PRIO_UNSPECIFIED=0 PRIO_UNSPECIFIED value
         * @property {number} PRIO_UNUSED=1 PRIO_UNUSED value
         * @property {number} PRIO_VERBOSE=2 PRIO_VERBOSE value
         * @property {number} PRIO_DEBUG=3 PRIO_DEBUG value
         * @property {number} PRIO_INFO=4 PRIO_INFO value
         * @property {number} PRIO_WARN=5 PRIO_WARN value
         * @property {number} PRIO_ERROR=6 PRIO_ERROR value
         * @property {number} PRIO_FATAL=7 PRIO_FATAL value
         */
        protos.AndroidLogPriority = (function() {
            var valuesById = {}, values = Object.create(valuesById);
            values[valuesById[0] = "PRIO_UNSPECIFIED"] = 0;
            values[valuesById[1] = "PRIO_UNUSED"] = 1;
            values[valuesById[2] = "PRIO_VERBOSE"] = 2;
            values[valuesById[3] = "PRIO_DEBUG"] = 3;
            values[valuesById[4] = "PRIO_INFO"] = 4;
            values[valuesById[5] = "PRIO_WARN"] = 5;
            values[valuesById[6] = "PRIO_ERROR"] = 6;
            values[valuesById[7] = "PRIO_FATAL"] = 7;
            return values;
        })();

        protos.AndroidLogConfig = (function() {

            /**
             * Properties of an AndroidLogConfig.
             * @memberof perfetto.protos
             * @interface IAndroidLogConfig
             * @property {Array.<perfetto.protos.AndroidLogId>|null} [logIds] AndroidLogConfig logIds
             * @property {perfetto.protos.AndroidLogPriority|null} [minPrio] AndroidLogConfig minPrio
             * @property {Array.<string>|null} [filterTags] AndroidLogConfig filterTags
             */

            /**
             * Constructs a new AndroidLogConfig.
             * @memberof perfetto.protos
             * @classdesc Represents an AndroidLogConfig.
             * @implements IAndroidLogConfig
             * @constructor
             * @param {perfetto.protos.IAndroidLogConfig=} [properties] Properties to set
             */
            function AndroidLogConfig(properties) {
                this.logIds = [];
                this.filterTags = [];
                if (properties)
                    for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                        if (properties[keys[i]] != null)
                            this[keys[i]] = properties[keys[i]];
            }

            /**
             * AndroidLogConfig logIds.
             * @member {Array.<perfetto.protos.AndroidLogId>} logIds
             * @memberof perfetto.protos.AndroidLogConfig
             * @instance
             */
            AndroidLogConfig.prototype.logIds = $util.emptyArray;

            /**
             * AndroidLogConfig minPrio.
             * @member {perfetto.protos.AndroidLogPriority} minPrio
             * @memberof perfetto.protos.AndroidLogConfig
             * @instance
             */
            AndroidLogConfig.prototype.minPrio = 0;

            /**
             * AndroidLogConfig filterTags.
             * @member {Array.<string>} filterTags
             * @memberof perfetto.protos.AndroidLogConfig
             * @instance
             */
            AndroidLogConfig.prototype.filterTags = $util.emptyArray;

            /**
             * Creates a new AndroidLogConfig instance using the specified properties.
             * @function create
             * @memberof perfetto.protos.AndroidLogConfig
             * @static
             * @param {perfetto.protos.IAndroidLogConfig=} [properties] Properties to set
             * @returns {perfetto.protos.AndroidLogConfig} AndroidLogConfig instance
             */
            AndroidLogConfig.create = function create(properties) {
                return new AndroidLogConfig(properties);
            };

            /**
             * Encodes the specified AndroidLogConfig message. Does not implicitly {@link perfetto.protos.AndroidLogConfig.verify|verify} messages.
             * @function encode
             * @memberof perfetto.protos.AndroidLogConfig
             * @static
             * @param {perfetto.protos.IAndroidLogConfig} message AndroidLogConfig message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            AndroidLogConfig.encode = function encode(message, writer) {
                if (!writer)
                    writer = $Writer.create();
                if (message.logIds != null && message.logIds.length)
                    for (var i = 0; i < message.logIds.length; ++i)
                        writer.uint32(/* id 1, wireType 0 =*/8).int32(message.logIds[i]);
                if (message.minPrio != null && Object.hasOwnProperty.call(message, "minPrio"))
                    writer.uint32(/* id 3, wireType 0 =*/24).int32(message.minPrio);
                if (message.filterTags != null && message.filterTags.length)
                    for (var i = 0; i < message.filterTags.length; ++i)
                        writer.uint32(/* id 4, wireType 2 =*/34).string(message.filterTags[i]);
                return writer;
            };

            /**
             * Encodes the specified AndroidLogConfig message, length delimited. Does not implicitly {@link perfetto.protos.AndroidLogConfig.verify|verify} messages.
             * @function encodeDelimited
             * @memberof perfetto.protos.AndroidLogConfig
             * @static
             * @param {perfetto.protos.IAndroidLogConfig} message AndroidLogConfig message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            AndroidLogConfig.encodeDelimited = function encodeDelimited(message, writer) {
                return this.encode(message, writer).ldelim();
            };

            /**
             * Decodes an AndroidLogConfig message from the specified reader or buffer.
             * @function decode
             * @memberof perfetto.protos.AndroidLogConfig
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @param {number} [length] Message length if known beforehand
             * @returns {perfetto.protos.AndroidLogConfig} AndroidLogConfig
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            AndroidLogConfig.decode = function decode(reader, length) {
                if (!(reader instanceof $Reader))
                    reader = $Reader.create(reader);
                var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.AndroidLogConfig();
                while (reader.pos < end) {
                    var tag = reader.uint32();
                    switch (tag >>> 3) {
                    case 1:
                        if (!(message.logIds && message.logIds.length))
                            message.logIds = [];
                        if ((tag & 7) === 2) {
                            var end2 = reader.uint32() + reader.pos;
                            while (reader.pos < end2)
                                message.logIds.push(reader.int32());
                        } else
                            message.logIds.push(reader.int32());
                        break;
                    case 3:
                        message.minPrio = reader.int32();
                        break;
                    case 4:
                        if (!(message.filterTags && message.filterTags.length))
                            message.filterTags = [];
                        message.filterTags.push(reader.string());
                        break;
                    default:
                        reader.skipType(tag & 7);
                        break;
                    }
                }
                return message;
            };

            /**
             * Decodes an AndroidLogConfig message from the specified reader or buffer, length delimited.
             * @function decodeDelimited
             * @memberof perfetto.protos.AndroidLogConfig
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @returns {perfetto.protos.AndroidLogConfig} AndroidLogConfig
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            AndroidLogConfig.decodeDelimited = function decodeDelimited(reader) {
                if (!(reader instanceof $Reader))
                    reader = new $Reader(reader);
                return this.decode(reader, reader.uint32());
            };

            /**
             * Verifies an AndroidLogConfig message.
             * @function verify
             * @memberof perfetto.protos.AndroidLogConfig
             * @static
             * @param {Object.<string,*>} message Plain object to verify
             * @returns {string|null} `null` if valid, otherwise the reason why it is not
             */
            AndroidLogConfig.verify = function verify(message) {
                if (typeof message !== "object" || message === null)
                    return "object expected";
                if (message.logIds != null && message.hasOwnProperty("logIds")) {
                    if (!Array.isArray(message.logIds))
                        return "logIds: array expected";
                    for (var i = 0; i < message.logIds.length; ++i)
                        switch (message.logIds[i]) {
                        default:
                            return "logIds: enum value[] expected";
                        case 0:
                        case 1:
                        case 2:
                        case 3:
                        case 4:
                        case 5:
                        case 6:
                        case 7:
                            break;
                        }
                }
                if (message.minPrio != null && message.hasOwnProperty("minPrio"))
                    switch (message.minPrio) {
                    default:
                        return "minPrio: enum value expected";
                    case 0:
                    case 1:
                    case 2:
                    case 3:
                    case 4:
                    case 5:
                    case 6:
                    case 7:
                        break;
                    }
                if (message.filterTags != null && message.hasOwnProperty("filterTags")) {
                    if (!Array.isArray(message.filterTags))
                        return "filterTags: array expected";
                    for (var i = 0; i < message.filterTags.length; ++i)
                        if (!$util.isString(message.filterTags[i]))
                            return "filterTags: string[] expected";
                }
                return null;
            };

            /**
             * Creates an AndroidLogConfig message from a plain object. Also converts values to their respective internal types.
             * @function fromObject
             * @memberof perfetto.protos.AndroidLogConfig
             * @static
             * @param {Object.<string,*>} object Plain object
             * @returns {perfetto.protos.AndroidLogConfig} AndroidLogConfig
             */
            AndroidLogConfig.fromObject = function fromObject(object) {
                if (object instanceof $root.perfetto.protos.AndroidLogConfig)
                    return object;
                var message = new $root.perfetto.protos.AndroidLogConfig();
                if (object.logIds) {
                    if (!Array.isArray(object.logIds))
                        throw TypeError(".perfetto.protos.AndroidLogConfig.logIds: array expected");
                    message.logIds = [];
                    for (var i = 0; i < object.logIds.length; ++i)
                        switch (object.logIds[i]) {
                        default:
                        case "LID_DEFAULT":
                        case 0:
                            message.logIds[i] = 0;
                            break;
                        case "LID_RADIO":
                        case 1:
                            message.logIds[i] = 1;
                            break;
                        case "LID_EVENTS":
                        case 2:
                            message.logIds[i] = 2;
                            break;
                        case "LID_SYSTEM":
                        case 3:
                            message.logIds[i] = 3;
                            break;
                        case "LID_CRASH":
                        case 4:
                            message.logIds[i] = 4;
                            break;
                        case "LID_STATS":
                        case 5:
                            message.logIds[i] = 5;
                            break;
                        case "LID_SECURITY":
                        case 6:
                            message.logIds[i] = 6;
                            break;
                        case "LID_KERNEL":
                        case 7:
                            message.logIds[i] = 7;
                            break;
                        }
                }
                switch (object.minPrio) {
                case "PRIO_UNSPECIFIED":
                case 0:
                    message.minPrio = 0;
                    break;
                case "PRIO_UNUSED":
                case 1:
                    message.minPrio = 1;
                    break;
                case "PRIO_VERBOSE":
                case 2:
                    message.minPrio = 2;
                    break;
                case "PRIO_DEBUG":
                case 3:
                    message.minPrio = 3;
                    break;
                case "PRIO_INFO":
                case 4:
                    message.minPrio = 4;
                    break;
                case "PRIO_WARN":
                case 5:
                    message.minPrio = 5;
                    break;
                case "PRIO_ERROR":
                case 6:
                    message.minPrio = 6;
                    break;
                case "PRIO_FATAL":
                case 7:
                    message.minPrio = 7;
                    break;
                }
                if (object.filterTags) {
                    if (!Array.isArray(object.filterTags))
                        throw TypeError(".perfetto.protos.AndroidLogConfig.filterTags: array expected");
                    message.filterTags = [];
                    for (var i = 0; i < object.filterTags.length; ++i)
                        message.filterTags[i] = String(object.filterTags[i]);
                }
                return message;
            };

            /**
             * Creates a plain object from an AndroidLogConfig message. Also converts values to other types if specified.
             * @function toObject
             * @memberof perfetto.protos.AndroidLogConfig
             * @static
             * @param {perfetto.protos.AndroidLogConfig} message AndroidLogConfig
             * @param {$protobuf.IConversionOptions} [options] Conversion options
             * @returns {Object.<string,*>} Plain object
             */
            AndroidLogConfig.toObject = function toObject(message, options) {
                if (!options)
                    options = {};
                var object = {};
                if (options.arrays || options.defaults) {
                    object.logIds = [];
                    object.filterTags = [];
                }
                if (options.defaults)
                    object.minPrio = options.enums === String ? "PRIO_UNSPECIFIED" : 0;
                if (message.logIds && message.logIds.length) {
                    object.logIds = [];
                    for (var j = 0; j < message.logIds.length; ++j)
                        object.logIds[j] = options.enums === String ? $root.perfetto.protos.AndroidLogId[message.logIds[j]] : message.logIds[j];
                }
                if (message.minPrio != null && message.hasOwnProperty("minPrio"))
                    object.minPrio = options.enums === String ? $root.perfetto.protos.AndroidLogPriority[message.minPrio] : message.minPrio;
                if (message.filterTags && message.filterTags.length) {
                    object.filterTags = [];
                    for (var j = 0; j < message.filterTags.length; ++j)
                        object.filterTags[j] = message.filterTags[j];
                }
                return object;
            };

            /**
             * Converts this AndroidLogConfig to JSON.
             * @function toJSON
             * @memberof perfetto.protos.AndroidLogConfig
             * @instance
             * @returns {Object.<string,*>} JSON object
             */
            AndroidLogConfig.prototype.toJSON = function toJSON() {
                return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
            };

            return AndroidLogConfig;
        })();

        protos.AndroidPolledStateConfig = (function() {

            /**
             * Properties of an AndroidPolledStateConfig.
             * @memberof perfetto.protos
             * @interface IAndroidPolledStateConfig
             * @property {number|null} [pollMs] AndroidPolledStateConfig pollMs
             */

            /**
             * Constructs a new AndroidPolledStateConfig.
             * @memberof perfetto.protos
             * @classdesc Represents an AndroidPolledStateConfig.
             * @implements IAndroidPolledStateConfig
             * @constructor
             * @param {perfetto.protos.IAndroidPolledStateConfig=} [properties] Properties to set
             */
            function AndroidPolledStateConfig(properties) {
                if (properties)
                    for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                        if (properties[keys[i]] != null)
                            this[keys[i]] = properties[keys[i]];
            }

            /**
             * AndroidPolledStateConfig pollMs.
             * @member {number} pollMs
             * @memberof perfetto.protos.AndroidPolledStateConfig
             * @instance
             */
            AndroidPolledStateConfig.prototype.pollMs = 0;

            /**
             * Creates a new AndroidPolledStateConfig instance using the specified properties.
             * @function create
             * @memberof perfetto.protos.AndroidPolledStateConfig
             * @static
             * @param {perfetto.protos.IAndroidPolledStateConfig=} [properties] Properties to set
             * @returns {perfetto.protos.AndroidPolledStateConfig} AndroidPolledStateConfig instance
             */
            AndroidPolledStateConfig.create = function create(properties) {
                return new AndroidPolledStateConfig(properties);
            };

            /**
             * Encodes the specified AndroidPolledStateConfig message. Does not implicitly {@link perfetto.protos.AndroidPolledStateConfig.verify|verify} messages.
             * @function encode
             * @memberof perfetto.protos.AndroidPolledStateConfig
             * @static
             * @param {perfetto.protos.IAndroidPolledStateConfig} message AndroidPolledStateConfig message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            AndroidPolledStateConfig.encode = function encode(message, writer) {
                if (!writer)
                    writer = $Writer.create();
                if (message.pollMs != null && Object.hasOwnProperty.call(message, "pollMs"))
                    writer.uint32(/* id 1, wireType 0 =*/8).uint32(message.pollMs);
                return writer;
            };

            /**
             * Encodes the specified AndroidPolledStateConfig message, length delimited. Does not implicitly {@link perfetto.protos.AndroidPolledStateConfig.verify|verify} messages.
             * @function encodeDelimited
             * @memberof perfetto.protos.AndroidPolledStateConfig
             * @static
             * @param {perfetto.protos.IAndroidPolledStateConfig} message AndroidPolledStateConfig message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            AndroidPolledStateConfig.encodeDelimited = function encodeDelimited(message, writer) {
                return this.encode(message, writer).ldelim();
            };

            /**
             * Decodes an AndroidPolledStateConfig message from the specified reader or buffer.
             * @function decode
             * @memberof perfetto.protos.AndroidPolledStateConfig
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @param {number} [length] Message length if known beforehand
             * @returns {perfetto.protos.AndroidPolledStateConfig} AndroidPolledStateConfig
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            AndroidPolledStateConfig.decode = function decode(reader, length) {
                if (!(reader instanceof $Reader))
                    reader = $Reader.create(reader);
                var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.AndroidPolledStateConfig();
                while (reader.pos < end) {
                    var tag = reader.uint32();
                    switch (tag >>> 3) {
                    case 1:
                        message.pollMs = reader.uint32();
                        break;
                    default:
                        reader.skipType(tag & 7);
                        break;
                    }
                }
                return message;
            };

            /**
             * Decodes an AndroidPolledStateConfig message from the specified reader or buffer, length delimited.
             * @function decodeDelimited
             * @memberof perfetto.protos.AndroidPolledStateConfig
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @returns {perfetto.protos.AndroidPolledStateConfig} AndroidPolledStateConfig
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            AndroidPolledStateConfig.decodeDelimited = function decodeDelimited(reader) {
                if (!(reader instanceof $Reader))
                    reader = new $Reader(reader);
                return this.decode(reader, reader.uint32());
            };

            /**
             * Verifies an AndroidPolledStateConfig message.
             * @function verify
             * @memberof perfetto.protos.AndroidPolledStateConfig
             * @static
             * @param {Object.<string,*>} message Plain object to verify
             * @returns {string|null} `null` if valid, otherwise the reason why it is not
             */
            AndroidPolledStateConfig.verify = function verify(message) {
                if (typeof message !== "object" || message === null)
                    return "object expected";
                if (message.pollMs != null && message.hasOwnProperty("pollMs"))
                    if (!$util.isInteger(message.pollMs))
                        return "pollMs: integer expected";
                return null;
            };

            /**
             * Creates an AndroidPolledStateConfig message from a plain object. Also converts values to their respective internal types.
             * @function fromObject
             * @memberof perfetto.protos.AndroidPolledStateConfig
             * @static
             * @param {Object.<string,*>} object Plain object
             * @returns {perfetto.protos.AndroidPolledStateConfig} AndroidPolledStateConfig
             */
            AndroidPolledStateConfig.fromObject = function fromObject(object) {
                if (object instanceof $root.perfetto.protos.AndroidPolledStateConfig)
                    return object;
                var message = new $root.perfetto.protos.AndroidPolledStateConfig();
                if (object.pollMs != null)
                    message.pollMs = object.pollMs >>> 0;
                return message;
            };

            /**
             * Creates a plain object from an AndroidPolledStateConfig message. Also converts values to other types if specified.
             * @function toObject
             * @memberof perfetto.protos.AndroidPolledStateConfig
             * @static
             * @param {perfetto.protos.AndroidPolledStateConfig} message AndroidPolledStateConfig
             * @param {$protobuf.IConversionOptions} [options] Conversion options
             * @returns {Object.<string,*>} Plain object
             */
            AndroidPolledStateConfig.toObject = function toObject(message, options) {
                if (!options)
                    options = {};
                var object = {};
                if (options.defaults)
                    object.pollMs = 0;
                if (message.pollMs != null && message.hasOwnProperty("pollMs"))
                    object.pollMs = message.pollMs;
                return object;
            };

            /**
             * Converts this AndroidPolledStateConfig to JSON.
             * @function toJSON
             * @memberof perfetto.protos.AndroidPolledStateConfig
             * @instance
             * @returns {Object.<string,*>} JSON object
             */
            AndroidPolledStateConfig.prototype.toJSON = function toJSON() {
                return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
            };

            return AndroidPolledStateConfig;
        })();

        protos.PackagesListConfig = (function() {

            /**
             * Properties of a PackagesListConfig.
             * @memberof perfetto.protos
             * @interface IPackagesListConfig
             * @property {Array.<string>|null} [packageNameFilter] PackagesListConfig packageNameFilter
             */

            /**
             * Constructs a new PackagesListConfig.
             * @memberof perfetto.protos
             * @classdesc Represents a PackagesListConfig.
             * @implements IPackagesListConfig
             * @constructor
             * @param {perfetto.protos.IPackagesListConfig=} [properties] Properties to set
             */
            function PackagesListConfig(properties) {
                this.packageNameFilter = [];
                if (properties)
                    for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                        if (properties[keys[i]] != null)
                            this[keys[i]] = properties[keys[i]];
            }

            /**
             * PackagesListConfig packageNameFilter.
             * @member {Array.<string>} packageNameFilter
             * @memberof perfetto.protos.PackagesListConfig
             * @instance
             */
            PackagesListConfig.prototype.packageNameFilter = $util.emptyArray;

            /**
             * Creates a new PackagesListConfig instance using the specified properties.
             * @function create
             * @memberof perfetto.protos.PackagesListConfig
             * @static
             * @param {perfetto.protos.IPackagesListConfig=} [properties] Properties to set
             * @returns {perfetto.protos.PackagesListConfig} PackagesListConfig instance
             */
            PackagesListConfig.create = function create(properties) {
                return new PackagesListConfig(properties);
            };

            /**
             * Encodes the specified PackagesListConfig message. Does not implicitly {@link perfetto.protos.PackagesListConfig.verify|verify} messages.
             * @function encode
             * @memberof perfetto.protos.PackagesListConfig
             * @static
             * @param {perfetto.protos.IPackagesListConfig} message PackagesListConfig message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            PackagesListConfig.encode = function encode(message, writer) {
                if (!writer)
                    writer = $Writer.create();
                if (message.packageNameFilter != null && message.packageNameFilter.length)
                    for (var i = 0; i < message.packageNameFilter.length; ++i)
                        writer.uint32(/* id 1, wireType 2 =*/10).string(message.packageNameFilter[i]);
                return writer;
            };

            /**
             * Encodes the specified PackagesListConfig message, length delimited. Does not implicitly {@link perfetto.protos.PackagesListConfig.verify|verify} messages.
             * @function encodeDelimited
             * @memberof perfetto.protos.PackagesListConfig
             * @static
             * @param {perfetto.protos.IPackagesListConfig} message PackagesListConfig message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            PackagesListConfig.encodeDelimited = function encodeDelimited(message, writer) {
                return this.encode(message, writer).ldelim();
            };

            /**
             * Decodes a PackagesListConfig message from the specified reader or buffer.
             * @function decode
             * @memberof perfetto.protos.PackagesListConfig
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @param {number} [length] Message length if known beforehand
             * @returns {perfetto.protos.PackagesListConfig} PackagesListConfig
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            PackagesListConfig.decode = function decode(reader, length) {
                if (!(reader instanceof $Reader))
                    reader = $Reader.create(reader);
                var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.PackagesListConfig();
                while (reader.pos < end) {
                    var tag = reader.uint32();
                    switch (tag >>> 3) {
                    case 1:
                        if (!(message.packageNameFilter && message.packageNameFilter.length))
                            message.packageNameFilter = [];
                        message.packageNameFilter.push(reader.string());
                        break;
                    default:
                        reader.skipType(tag & 7);
                        break;
                    }
                }
                return message;
            };

            /**
             * Decodes a PackagesListConfig message from the specified reader or buffer, length delimited.
             * @function decodeDelimited
             * @memberof perfetto.protos.PackagesListConfig
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @returns {perfetto.protos.PackagesListConfig} PackagesListConfig
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            PackagesListConfig.decodeDelimited = function decodeDelimited(reader) {
                if (!(reader instanceof $Reader))
                    reader = new $Reader(reader);
                return this.decode(reader, reader.uint32());
            };

            /**
             * Verifies a PackagesListConfig message.
             * @function verify
             * @memberof perfetto.protos.PackagesListConfig
             * @static
             * @param {Object.<string,*>} message Plain object to verify
             * @returns {string|null} `null` if valid, otherwise the reason why it is not
             */
            PackagesListConfig.verify = function verify(message) {
                if (typeof message !== "object" || message === null)
                    return "object expected";
                if (message.packageNameFilter != null && message.hasOwnProperty("packageNameFilter")) {
                    if (!Array.isArray(message.packageNameFilter))
                        return "packageNameFilter: array expected";
                    for (var i = 0; i < message.packageNameFilter.length; ++i)
                        if (!$util.isString(message.packageNameFilter[i]))
                            return "packageNameFilter: string[] expected";
                }
                return null;
            };

            /**
             * Creates a PackagesListConfig message from a plain object. Also converts values to their respective internal types.
             * @function fromObject
             * @memberof perfetto.protos.PackagesListConfig
             * @static
             * @param {Object.<string,*>} object Plain object
             * @returns {perfetto.protos.PackagesListConfig} PackagesListConfig
             */
            PackagesListConfig.fromObject = function fromObject(object) {
                if (object instanceof $root.perfetto.protos.PackagesListConfig)
                    return object;
                var message = new $root.perfetto.protos.PackagesListConfig();
                if (object.packageNameFilter) {
                    if (!Array.isArray(object.packageNameFilter))
                        throw TypeError(".perfetto.protos.PackagesListConfig.packageNameFilter: array expected");
                    message.packageNameFilter = [];
                    for (var i = 0; i < object.packageNameFilter.length; ++i)
                        message.packageNameFilter[i] = String(object.packageNameFilter[i]);
                }
                return message;
            };

            /**
             * Creates a plain object from a PackagesListConfig message. Also converts values to other types if specified.
             * @function toObject
             * @memberof perfetto.protos.PackagesListConfig
             * @static
             * @param {perfetto.protos.PackagesListConfig} message PackagesListConfig
             * @param {$protobuf.IConversionOptions} [options] Conversion options
             * @returns {Object.<string,*>} Plain object
             */
            PackagesListConfig.toObject = function toObject(message, options) {
                if (!options)
                    options = {};
                var object = {};
                if (options.arrays || options.defaults)
                    object.packageNameFilter = [];
                if (message.packageNameFilter && message.packageNameFilter.length) {
                    object.packageNameFilter = [];
                    for (var j = 0; j < message.packageNameFilter.length; ++j)
                        object.packageNameFilter[j] = message.packageNameFilter[j];
                }
                return object;
            };

            /**
             * Converts this PackagesListConfig to JSON.
             * @function toJSON
             * @memberof perfetto.protos.PackagesListConfig
             * @instance
             * @returns {Object.<string,*>} JSON object
             */
            PackagesListConfig.prototype.toJSON = function toJSON() {
                return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
            };

            return PackagesListConfig;
        })();

        protos.ChromeConfig = (function() {

            /**
             * Properties of a ChromeConfig.
             * @memberof perfetto.protos
             * @interface IChromeConfig
             * @property {string|null} [traceConfig] ChromeConfig traceConfig
             * @property {boolean|null} [privacyFilteringEnabled] ChromeConfig privacyFilteringEnabled
             * @property {boolean|null} [convertToLegacyJson] ChromeConfig convertToLegacyJson
             * @property {perfetto.protos.ChromeConfig.ClientPriority|null} [clientPriority] ChromeConfig clientPriority
             * @property {string|null} [jsonAgentLabelFilter] ChromeConfig jsonAgentLabelFilter
             */

            /**
             * Constructs a new ChromeConfig.
             * @memberof perfetto.protos
             * @classdesc Represents a ChromeConfig.
             * @implements IChromeConfig
             * @constructor
             * @param {perfetto.protos.IChromeConfig=} [properties] Properties to set
             */
            function ChromeConfig(properties) {
                if (properties)
                    for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                        if (properties[keys[i]] != null)
                            this[keys[i]] = properties[keys[i]];
            }

            /**
             * ChromeConfig traceConfig.
             * @member {string} traceConfig
             * @memberof perfetto.protos.ChromeConfig
             * @instance
             */
            ChromeConfig.prototype.traceConfig = "";

            /**
             * ChromeConfig privacyFilteringEnabled.
             * @member {boolean} privacyFilteringEnabled
             * @memberof perfetto.protos.ChromeConfig
             * @instance
             */
            ChromeConfig.prototype.privacyFilteringEnabled = false;

            /**
             * ChromeConfig convertToLegacyJson.
             * @member {boolean} convertToLegacyJson
             * @memberof perfetto.protos.ChromeConfig
             * @instance
             */
            ChromeConfig.prototype.convertToLegacyJson = false;

            /**
             * ChromeConfig clientPriority.
             * @member {perfetto.protos.ChromeConfig.ClientPriority} clientPriority
             * @memberof perfetto.protos.ChromeConfig
             * @instance
             */
            ChromeConfig.prototype.clientPriority = 0;

            /**
             * ChromeConfig jsonAgentLabelFilter.
             * @member {string} jsonAgentLabelFilter
             * @memberof perfetto.protos.ChromeConfig
             * @instance
             */
            ChromeConfig.prototype.jsonAgentLabelFilter = "";

            /**
             * Creates a new ChromeConfig instance using the specified properties.
             * @function create
             * @memberof perfetto.protos.ChromeConfig
             * @static
             * @param {perfetto.protos.IChromeConfig=} [properties] Properties to set
             * @returns {perfetto.protos.ChromeConfig} ChromeConfig instance
             */
            ChromeConfig.create = function create(properties) {
                return new ChromeConfig(properties);
            };

            /**
             * Encodes the specified ChromeConfig message. Does not implicitly {@link perfetto.protos.ChromeConfig.verify|verify} messages.
             * @function encode
             * @memberof perfetto.protos.ChromeConfig
             * @static
             * @param {perfetto.protos.IChromeConfig} message ChromeConfig message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            ChromeConfig.encode = function encode(message, writer) {
                if (!writer)
                    writer = $Writer.create();
                if (message.traceConfig != null && Object.hasOwnProperty.call(message, "traceConfig"))
                    writer.uint32(/* id 1, wireType 2 =*/10).string(message.traceConfig);
                if (message.privacyFilteringEnabled != null && Object.hasOwnProperty.call(message, "privacyFilteringEnabled"))
                    writer.uint32(/* id 2, wireType 0 =*/16).bool(message.privacyFilteringEnabled);
                if (message.convertToLegacyJson != null && Object.hasOwnProperty.call(message, "convertToLegacyJson"))
                    writer.uint32(/* id 3, wireType 0 =*/24).bool(message.convertToLegacyJson);
                if (message.clientPriority != null && Object.hasOwnProperty.call(message, "clientPriority"))
                    writer.uint32(/* id 4, wireType 0 =*/32).int32(message.clientPriority);
                if (message.jsonAgentLabelFilter != null && Object.hasOwnProperty.call(message, "jsonAgentLabelFilter"))
                    writer.uint32(/* id 5, wireType 2 =*/42).string(message.jsonAgentLabelFilter);
                return writer;
            };

            /**
             * Encodes the specified ChromeConfig message, length delimited. Does not implicitly {@link perfetto.protos.ChromeConfig.verify|verify} messages.
             * @function encodeDelimited
             * @memberof perfetto.protos.ChromeConfig
             * @static
             * @param {perfetto.protos.IChromeConfig} message ChromeConfig message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            ChromeConfig.encodeDelimited = function encodeDelimited(message, writer) {
                return this.encode(message, writer).ldelim();
            };

            /**
             * Decodes a ChromeConfig message from the specified reader or buffer.
             * @function decode
             * @memberof perfetto.protos.ChromeConfig
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @param {number} [length] Message length if known beforehand
             * @returns {perfetto.protos.ChromeConfig} ChromeConfig
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            ChromeConfig.decode = function decode(reader, length) {
                if (!(reader instanceof $Reader))
                    reader = $Reader.create(reader);
                var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.ChromeConfig();
                while (reader.pos < end) {
                    var tag = reader.uint32();
                    switch (tag >>> 3) {
                    case 1:
                        message.traceConfig = reader.string();
                        break;
                    case 2:
                        message.privacyFilteringEnabled = reader.bool();
                        break;
                    case 3:
                        message.convertToLegacyJson = reader.bool();
                        break;
                    case 4:
                        message.clientPriority = reader.int32();
                        break;
                    case 5:
                        message.jsonAgentLabelFilter = reader.string();
                        break;
                    default:
                        reader.skipType(tag & 7);
                        break;
                    }
                }
                return message;
            };

            /**
             * Decodes a ChromeConfig message from the specified reader or buffer, length delimited.
             * @function decodeDelimited
             * @memberof perfetto.protos.ChromeConfig
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @returns {perfetto.protos.ChromeConfig} ChromeConfig
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            ChromeConfig.decodeDelimited = function decodeDelimited(reader) {
                if (!(reader instanceof $Reader))
                    reader = new $Reader(reader);
                return this.decode(reader, reader.uint32());
            };

            /**
             * Verifies a ChromeConfig message.
             * @function verify
             * @memberof perfetto.protos.ChromeConfig
             * @static
             * @param {Object.<string,*>} message Plain object to verify
             * @returns {string|null} `null` if valid, otherwise the reason why it is not
             */
            ChromeConfig.verify = function verify(message) {
                if (typeof message !== "object" || message === null)
                    return "object expected";
                if (message.traceConfig != null && message.hasOwnProperty("traceConfig"))
                    if (!$util.isString(message.traceConfig))
                        return "traceConfig: string expected";
                if (message.privacyFilteringEnabled != null && message.hasOwnProperty("privacyFilteringEnabled"))
                    if (typeof message.privacyFilteringEnabled !== "boolean")
                        return "privacyFilteringEnabled: boolean expected";
                if (message.convertToLegacyJson != null && message.hasOwnProperty("convertToLegacyJson"))
                    if (typeof message.convertToLegacyJson !== "boolean")
                        return "convertToLegacyJson: boolean expected";
                if (message.clientPriority != null && message.hasOwnProperty("clientPriority"))
                    switch (message.clientPriority) {
                    default:
                        return "clientPriority: enum value expected";
                    case 0:
                    case 1:
                    case 2:
                        break;
                    }
                if (message.jsonAgentLabelFilter != null && message.hasOwnProperty("jsonAgentLabelFilter"))
                    if (!$util.isString(message.jsonAgentLabelFilter))
                        return "jsonAgentLabelFilter: string expected";
                return null;
            };

            /**
             * Creates a ChromeConfig message from a plain object. Also converts values to their respective internal types.
             * @function fromObject
             * @memberof perfetto.protos.ChromeConfig
             * @static
             * @param {Object.<string,*>} object Plain object
             * @returns {perfetto.protos.ChromeConfig} ChromeConfig
             */
            ChromeConfig.fromObject = function fromObject(object) {
                if (object instanceof $root.perfetto.protos.ChromeConfig)
                    return object;
                var message = new $root.perfetto.protos.ChromeConfig();
                if (object.traceConfig != null)
                    message.traceConfig = String(object.traceConfig);
                if (object.privacyFilteringEnabled != null)
                    message.privacyFilteringEnabled = Boolean(object.privacyFilteringEnabled);
                if (object.convertToLegacyJson != null)
                    message.convertToLegacyJson = Boolean(object.convertToLegacyJson);
                switch (object.clientPriority) {
                case "UNKNOWN":
                case 0:
                    message.clientPriority = 0;
                    break;
                case "BACKGROUND":
                case 1:
                    message.clientPriority = 1;
                    break;
                case "USER_INITIATED":
                case 2:
                    message.clientPriority = 2;
                    break;
                }
                if (object.jsonAgentLabelFilter != null)
                    message.jsonAgentLabelFilter = String(object.jsonAgentLabelFilter);
                return message;
            };

            /**
             * Creates a plain object from a ChromeConfig message. Also converts values to other types if specified.
             * @function toObject
             * @memberof perfetto.protos.ChromeConfig
             * @static
             * @param {perfetto.protos.ChromeConfig} message ChromeConfig
             * @param {$protobuf.IConversionOptions} [options] Conversion options
             * @returns {Object.<string,*>} Plain object
             */
            ChromeConfig.toObject = function toObject(message, options) {
                if (!options)
                    options = {};
                var object = {};
                if (options.defaults) {
                    object.traceConfig = "";
                    object.privacyFilteringEnabled = false;
                    object.convertToLegacyJson = false;
                    object.clientPriority = options.enums === String ? "UNKNOWN" : 0;
                    object.jsonAgentLabelFilter = "";
                }
                if (message.traceConfig != null && message.hasOwnProperty("traceConfig"))
                    object.traceConfig = message.traceConfig;
                if (message.privacyFilteringEnabled != null && message.hasOwnProperty("privacyFilteringEnabled"))
                    object.privacyFilteringEnabled = message.privacyFilteringEnabled;
                if (message.convertToLegacyJson != null && message.hasOwnProperty("convertToLegacyJson"))
                    object.convertToLegacyJson = message.convertToLegacyJson;
                if (message.clientPriority != null && message.hasOwnProperty("clientPriority"))
                    object.clientPriority = options.enums === String ? $root.perfetto.protos.ChromeConfig.ClientPriority[message.clientPriority] : message.clientPriority;
                if (message.jsonAgentLabelFilter != null && message.hasOwnProperty("jsonAgentLabelFilter"))
                    object.jsonAgentLabelFilter = message.jsonAgentLabelFilter;
                return object;
            };

            /**
             * Converts this ChromeConfig to JSON.
             * @function toJSON
             * @memberof perfetto.protos.ChromeConfig
             * @instance
             * @returns {Object.<string,*>} JSON object
             */
            ChromeConfig.prototype.toJSON = function toJSON() {
                return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
            };

            /**
             * ClientPriority enum.
             * @name perfetto.protos.ChromeConfig.ClientPriority
             * @enum {number}
             * @property {number} UNKNOWN=0 UNKNOWN value
             * @property {number} BACKGROUND=1 BACKGROUND value
             * @property {number} USER_INITIATED=2 USER_INITIATED value
             */
            ChromeConfig.ClientPriority = (function() {
                var valuesById = {}, values = Object.create(valuesById);
                values[valuesById[0] = "UNKNOWN"] = 0;
                values[valuesById[1] = "BACKGROUND"] = 1;
                values[valuesById[2] = "USER_INITIATED"] = 2;
                return values;
            })();

            return ChromeConfig;
        })();

        protos.FtraceConfig = (function() {

            /**
             * Properties of a FtraceConfig.
             * @memberof perfetto.protos
             * @interface IFtraceConfig
             * @property {Array.<string>|null} [ftraceEvents] FtraceConfig ftraceEvents
             * @property {Array.<string>|null} [atraceCategories] FtraceConfig atraceCategories
             * @property {Array.<string>|null} [atraceApps] FtraceConfig atraceApps
             * @property {number|null} [bufferSizeKb] FtraceConfig bufferSizeKb
             * @property {number|null} [drainPeriodMs] FtraceConfig drainPeriodMs
             * @property {perfetto.protos.FtraceConfig.ICompactSchedConfig|null} [compactSched] FtraceConfig compactSched
             * @property {boolean|null} [symbolizeKsyms] FtraceConfig symbolizeKsyms
             * @property {boolean|null} [initializeKsymsSynchronouslyForTesting] FtraceConfig initializeKsymsSynchronouslyForTesting
             */

            /**
             * Constructs a new FtraceConfig.
             * @memberof perfetto.protos
             * @classdesc Represents a FtraceConfig.
             * @implements IFtraceConfig
             * @constructor
             * @param {perfetto.protos.IFtraceConfig=} [properties] Properties to set
             */
            function FtraceConfig(properties) {
                this.ftraceEvents = [];
                this.atraceCategories = [];
                this.atraceApps = [];
                if (properties)
                    for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                        if (properties[keys[i]] != null)
                            this[keys[i]] = properties[keys[i]];
            }

            /**
             * FtraceConfig ftraceEvents.
             * @member {Array.<string>} ftraceEvents
             * @memberof perfetto.protos.FtraceConfig
             * @instance
             */
            FtraceConfig.prototype.ftraceEvents = $util.emptyArray;

            /**
             * FtraceConfig atraceCategories.
             * @member {Array.<string>} atraceCategories
             * @memberof perfetto.protos.FtraceConfig
             * @instance
             */
            FtraceConfig.prototype.atraceCategories = $util.emptyArray;

            /**
             * FtraceConfig atraceApps.
             * @member {Array.<string>} atraceApps
             * @memberof perfetto.protos.FtraceConfig
             * @instance
             */
            FtraceConfig.prototype.atraceApps = $util.emptyArray;

            /**
             * FtraceConfig bufferSizeKb.
             * @member {number} bufferSizeKb
             * @memberof perfetto.protos.FtraceConfig
             * @instance
             */
            FtraceConfig.prototype.bufferSizeKb = 0;

            /**
             * FtraceConfig drainPeriodMs.
             * @member {number} drainPeriodMs
             * @memberof perfetto.protos.FtraceConfig
             * @instance
             */
            FtraceConfig.prototype.drainPeriodMs = 0;

            /**
             * FtraceConfig compactSched.
             * @member {perfetto.protos.FtraceConfig.ICompactSchedConfig|null|undefined} compactSched
             * @memberof perfetto.protos.FtraceConfig
             * @instance
             */
            FtraceConfig.prototype.compactSched = null;

            /**
             * FtraceConfig symbolizeKsyms.
             * @member {boolean} symbolizeKsyms
             * @memberof perfetto.protos.FtraceConfig
             * @instance
             */
            FtraceConfig.prototype.symbolizeKsyms = false;

            /**
             * FtraceConfig initializeKsymsSynchronouslyForTesting.
             * @member {boolean} initializeKsymsSynchronouslyForTesting
             * @memberof perfetto.protos.FtraceConfig
             * @instance
             */
            FtraceConfig.prototype.initializeKsymsSynchronouslyForTesting = false;

            /**
             * Creates a new FtraceConfig instance using the specified properties.
             * @function create
             * @memberof perfetto.protos.FtraceConfig
             * @static
             * @param {perfetto.protos.IFtraceConfig=} [properties] Properties to set
             * @returns {perfetto.protos.FtraceConfig} FtraceConfig instance
             */
            FtraceConfig.create = function create(properties) {
                return new FtraceConfig(properties);
            };

            /**
             * Encodes the specified FtraceConfig message. Does not implicitly {@link perfetto.protos.FtraceConfig.verify|verify} messages.
             * @function encode
             * @memberof perfetto.protos.FtraceConfig
             * @static
             * @param {perfetto.protos.IFtraceConfig} message FtraceConfig message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            FtraceConfig.encode = function encode(message, writer) {
                if (!writer)
                    writer = $Writer.create();
                if (message.ftraceEvents != null && message.ftraceEvents.length)
                    for (var i = 0; i < message.ftraceEvents.length; ++i)
                        writer.uint32(/* id 1, wireType 2 =*/10).string(message.ftraceEvents[i]);
                if (message.atraceCategories != null && message.atraceCategories.length)
                    for (var i = 0; i < message.atraceCategories.length; ++i)
                        writer.uint32(/* id 2, wireType 2 =*/18).string(message.atraceCategories[i]);
                if (message.atraceApps != null && message.atraceApps.length)
                    for (var i = 0; i < message.atraceApps.length; ++i)
                        writer.uint32(/* id 3, wireType 2 =*/26).string(message.atraceApps[i]);
                if (message.bufferSizeKb != null && Object.hasOwnProperty.call(message, "bufferSizeKb"))
                    writer.uint32(/* id 10, wireType 0 =*/80).uint32(message.bufferSizeKb);
                if (message.drainPeriodMs != null && Object.hasOwnProperty.call(message, "drainPeriodMs"))
                    writer.uint32(/* id 11, wireType 0 =*/88).uint32(message.drainPeriodMs);
                if (message.compactSched != null && Object.hasOwnProperty.call(message, "compactSched"))
                    $root.perfetto.protos.FtraceConfig.CompactSchedConfig.encode(message.compactSched, writer.uint32(/* id 12, wireType 2 =*/98).fork()).ldelim();
                if (message.symbolizeKsyms != null && Object.hasOwnProperty.call(message, "symbolizeKsyms"))
                    writer.uint32(/* id 13, wireType 0 =*/104).bool(message.symbolizeKsyms);
                if (message.initializeKsymsSynchronouslyForTesting != null && Object.hasOwnProperty.call(message, "initializeKsymsSynchronouslyForTesting"))
                    writer.uint32(/* id 14, wireType 0 =*/112).bool(message.initializeKsymsSynchronouslyForTesting);
                return writer;
            };

            /**
             * Encodes the specified FtraceConfig message, length delimited. Does not implicitly {@link perfetto.protos.FtraceConfig.verify|verify} messages.
             * @function encodeDelimited
             * @memberof perfetto.protos.FtraceConfig
             * @static
             * @param {perfetto.protos.IFtraceConfig} message FtraceConfig message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            FtraceConfig.encodeDelimited = function encodeDelimited(message, writer) {
                return this.encode(message, writer).ldelim();
            };

            /**
             * Decodes a FtraceConfig message from the specified reader or buffer.
             * @function decode
             * @memberof perfetto.protos.FtraceConfig
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @param {number} [length] Message length if known beforehand
             * @returns {perfetto.protos.FtraceConfig} FtraceConfig
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            FtraceConfig.decode = function decode(reader, length) {
                if (!(reader instanceof $Reader))
                    reader = $Reader.create(reader);
                var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.FtraceConfig();
                while (reader.pos < end) {
                    var tag = reader.uint32();
                    switch (tag >>> 3) {
                    case 1:
                        if (!(message.ftraceEvents && message.ftraceEvents.length))
                            message.ftraceEvents = [];
                        message.ftraceEvents.push(reader.string());
                        break;
                    case 2:
                        if (!(message.atraceCategories && message.atraceCategories.length))
                            message.atraceCategories = [];
                        message.atraceCategories.push(reader.string());
                        break;
                    case 3:
                        if (!(message.atraceApps && message.atraceApps.length))
                            message.atraceApps = [];
                        message.atraceApps.push(reader.string());
                        break;
                    case 10:
                        message.bufferSizeKb = reader.uint32();
                        break;
                    case 11:
                        message.drainPeriodMs = reader.uint32();
                        break;
                    case 12:
                        message.compactSched = $root.perfetto.protos.FtraceConfig.CompactSchedConfig.decode(reader, reader.uint32());
                        break;
                    case 13:
                        message.symbolizeKsyms = reader.bool();
                        break;
                    case 14:
                        message.initializeKsymsSynchronouslyForTesting = reader.bool();
                        break;
                    default:
                        reader.skipType(tag & 7);
                        break;
                    }
                }
                return message;
            };

            /**
             * Decodes a FtraceConfig message from the specified reader or buffer, length delimited.
             * @function decodeDelimited
             * @memberof perfetto.protos.FtraceConfig
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @returns {perfetto.protos.FtraceConfig} FtraceConfig
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            FtraceConfig.decodeDelimited = function decodeDelimited(reader) {
                if (!(reader instanceof $Reader))
                    reader = new $Reader(reader);
                return this.decode(reader, reader.uint32());
            };

            /**
             * Verifies a FtraceConfig message.
             * @function verify
             * @memberof perfetto.protos.FtraceConfig
             * @static
             * @param {Object.<string,*>} message Plain object to verify
             * @returns {string|null} `null` if valid, otherwise the reason why it is not
             */
            FtraceConfig.verify = function verify(message) {
                if (typeof message !== "object" || message === null)
                    return "object expected";
                if (message.ftraceEvents != null && message.hasOwnProperty("ftraceEvents")) {
                    if (!Array.isArray(message.ftraceEvents))
                        return "ftraceEvents: array expected";
                    for (var i = 0; i < message.ftraceEvents.length; ++i)
                        if (!$util.isString(message.ftraceEvents[i]))
                            return "ftraceEvents: string[] expected";
                }
                if (message.atraceCategories != null && message.hasOwnProperty("atraceCategories")) {
                    if (!Array.isArray(message.atraceCategories))
                        return "atraceCategories: array expected";
                    for (var i = 0; i < message.atraceCategories.length; ++i)
                        if (!$util.isString(message.atraceCategories[i]))
                            return "atraceCategories: string[] expected";
                }
                if (message.atraceApps != null && message.hasOwnProperty("atraceApps")) {
                    if (!Array.isArray(message.atraceApps))
                        return "atraceApps: array expected";
                    for (var i = 0; i < message.atraceApps.length; ++i)
                        if (!$util.isString(message.atraceApps[i]))
                            return "atraceApps: string[] expected";
                }
                if (message.bufferSizeKb != null && message.hasOwnProperty("bufferSizeKb"))
                    if (!$util.isInteger(message.bufferSizeKb))
                        return "bufferSizeKb: integer expected";
                if (message.drainPeriodMs != null && message.hasOwnProperty("drainPeriodMs"))
                    if (!$util.isInteger(message.drainPeriodMs))
                        return "drainPeriodMs: integer expected";
                if (message.compactSched != null && message.hasOwnProperty("compactSched")) {
                    var error = $root.perfetto.protos.FtraceConfig.CompactSchedConfig.verify(message.compactSched);
                    if (error)
                        return "compactSched." + error;
                }
                if (message.symbolizeKsyms != null && message.hasOwnProperty("symbolizeKsyms"))
                    if (typeof message.symbolizeKsyms !== "boolean")
                        return "symbolizeKsyms: boolean expected";
                if (message.initializeKsymsSynchronouslyForTesting != null && message.hasOwnProperty("initializeKsymsSynchronouslyForTesting"))
                    if (typeof message.initializeKsymsSynchronouslyForTesting !== "boolean")
                        return "initializeKsymsSynchronouslyForTesting: boolean expected";
                return null;
            };

            /**
             * Creates a FtraceConfig message from a plain object. Also converts values to their respective internal types.
             * @function fromObject
             * @memberof perfetto.protos.FtraceConfig
             * @static
             * @param {Object.<string,*>} object Plain object
             * @returns {perfetto.protos.FtraceConfig} FtraceConfig
             */
            FtraceConfig.fromObject = function fromObject(object) {
                if (object instanceof $root.perfetto.protos.FtraceConfig)
                    return object;
                var message = new $root.perfetto.protos.FtraceConfig();
                if (object.ftraceEvents) {
                    if (!Array.isArray(object.ftraceEvents))
                        throw TypeError(".perfetto.protos.FtraceConfig.ftraceEvents: array expected");
                    message.ftraceEvents = [];
                    for (var i = 0; i < object.ftraceEvents.length; ++i)
                        message.ftraceEvents[i] = String(object.ftraceEvents[i]);
                }
                if (object.atraceCategories) {
                    if (!Array.isArray(object.atraceCategories))
                        throw TypeError(".perfetto.protos.FtraceConfig.atraceCategories: array expected");
                    message.atraceCategories = [];
                    for (var i = 0; i < object.atraceCategories.length; ++i)
                        message.atraceCategories[i] = String(object.atraceCategories[i]);
                }
                if (object.atraceApps) {
                    if (!Array.isArray(object.atraceApps))
                        throw TypeError(".perfetto.protos.FtraceConfig.atraceApps: array expected");
                    message.atraceApps = [];
                    for (var i = 0; i < object.atraceApps.length; ++i)
                        message.atraceApps[i] = String(object.atraceApps[i]);
                }
                if (object.bufferSizeKb != null)
                    message.bufferSizeKb = object.bufferSizeKb >>> 0;
                if (object.drainPeriodMs != null)
                    message.drainPeriodMs = object.drainPeriodMs >>> 0;
                if (object.compactSched != null) {
                    if (typeof object.compactSched !== "object")
                        throw TypeError(".perfetto.protos.FtraceConfig.compactSched: object expected");
                    message.compactSched = $root.perfetto.protos.FtraceConfig.CompactSchedConfig.fromObject(object.compactSched);
                }
                if (object.symbolizeKsyms != null)
                    message.symbolizeKsyms = Boolean(object.symbolizeKsyms);
                if (object.initializeKsymsSynchronouslyForTesting != null)
                    message.initializeKsymsSynchronouslyForTesting = Boolean(object.initializeKsymsSynchronouslyForTesting);
                return message;
            };

            /**
             * Creates a plain object from a FtraceConfig message. Also converts values to other types if specified.
             * @function toObject
             * @memberof perfetto.protos.FtraceConfig
             * @static
             * @param {perfetto.protos.FtraceConfig} message FtraceConfig
             * @param {$protobuf.IConversionOptions} [options] Conversion options
             * @returns {Object.<string,*>} Plain object
             */
            FtraceConfig.toObject = function toObject(message, options) {
                if (!options)
                    options = {};
                var object = {};
                if (options.arrays || options.defaults) {
                    object.ftraceEvents = [];
                    object.atraceCategories = [];
                    object.atraceApps = [];
                }
                if (options.defaults) {
                    object.bufferSizeKb = 0;
                    object.drainPeriodMs = 0;
                    object.compactSched = null;
                    object.symbolizeKsyms = false;
                    object.initializeKsymsSynchronouslyForTesting = false;
                }
                if (message.ftraceEvents && message.ftraceEvents.length) {
                    object.ftraceEvents = [];
                    for (var j = 0; j < message.ftraceEvents.length; ++j)
                        object.ftraceEvents[j] = message.ftraceEvents[j];
                }
                if (message.atraceCategories && message.atraceCategories.length) {
                    object.atraceCategories = [];
                    for (var j = 0; j < message.atraceCategories.length; ++j)
                        object.atraceCategories[j] = message.atraceCategories[j];
                }
                if (message.atraceApps && message.atraceApps.length) {
                    object.atraceApps = [];
                    for (var j = 0; j < message.atraceApps.length; ++j)
                        object.atraceApps[j] = message.atraceApps[j];
                }
                if (message.bufferSizeKb != null && message.hasOwnProperty("bufferSizeKb"))
                    object.bufferSizeKb = message.bufferSizeKb;
                if (message.drainPeriodMs != null && message.hasOwnProperty("drainPeriodMs"))
                    object.drainPeriodMs = message.drainPeriodMs;
                if (message.compactSched != null && message.hasOwnProperty("compactSched"))
                    object.compactSched = $root.perfetto.protos.FtraceConfig.CompactSchedConfig.toObject(message.compactSched, options);
                if (message.symbolizeKsyms != null && message.hasOwnProperty("symbolizeKsyms"))
                    object.symbolizeKsyms = message.symbolizeKsyms;
                if (message.initializeKsymsSynchronouslyForTesting != null && message.hasOwnProperty("initializeKsymsSynchronouslyForTesting"))
                    object.initializeKsymsSynchronouslyForTesting = message.initializeKsymsSynchronouslyForTesting;
                return object;
            };

            /**
             * Converts this FtraceConfig to JSON.
             * @function toJSON
             * @memberof perfetto.protos.FtraceConfig
             * @instance
             * @returns {Object.<string,*>} JSON object
             */
            FtraceConfig.prototype.toJSON = function toJSON() {
                return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
            };

            FtraceConfig.CompactSchedConfig = (function() {

                /**
                 * Properties of a CompactSchedConfig.
                 * @memberof perfetto.protos.FtraceConfig
                 * @interface ICompactSchedConfig
                 * @property {boolean|null} [enabled] CompactSchedConfig enabled
                 */

                /**
                 * Constructs a new CompactSchedConfig.
                 * @memberof perfetto.protos.FtraceConfig
                 * @classdesc Represents a CompactSchedConfig.
                 * @implements ICompactSchedConfig
                 * @constructor
                 * @param {perfetto.protos.FtraceConfig.ICompactSchedConfig=} [properties] Properties to set
                 */
                function CompactSchedConfig(properties) {
                    if (properties)
                        for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                            if (properties[keys[i]] != null)
                                this[keys[i]] = properties[keys[i]];
                }

                /**
                 * CompactSchedConfig enabled.
                 * @member {boolean} enabled
                 * @memberof perfetto.protos.FtraceConfig.CompactSchedConfig
                 * @instance
                 */
                CompactSchedConfig.prototype.enabled = false;

                /**
                 * Creates a new CompactSchedConfig instance using the specified properties.
                 * @function create
                 * @memberof perfetto.protos.FtraceConfig.CompactSchedConfig
                 * @static
                 * @param {perfetto.protos.FtraceConfig.ICompactSchedConfig=} [properties] Properties to set
                 * @returns {perfetto.protos.FtraceConfig.CompactSchedConfig} CompactSchedConfig instance
                 */
                CompactSchedConfig.create = function create(properties) {
                    return new CompactSchedConfig(properties);
                };

                /**
                 * Encodes the specified CompactSchedConfig message. Does not implicitly {@link perfetto.protos.FtraceConfig.CompactSchedConfig.verify|verify} messages.
                 * @function encode
                 * @memberof perfetto.protos.FtraceConfig.CompactSchedConfig
                 * @static
                 * @param {perfetto.protos.FtraceConfig.ICompactSchedConfig} message CompactSchedConfig message or plain object to encode
                 * @param {$protobuf.Writer} [writer] Writer to encode to
                 * @returns {$protobuf.Writer} Writer
                 */
                CompactSchedConfig.encode = function encode(message, writer) {
                    if (!writer)
                        writer = $Writer.create();
                    if (message.enabled != null && Object.hasOwnProperty.call(message, "enabled"))
                        writer.uint32(/* id 1, wireType 0 =*/8).bool(message.enabled);
                    return writer;
                };

                /**
                 * Encodes the specified CompactSchedConfig message, length delimited. Does not implicitly {@link perfetto.protos.FtraceConfig.CompactSchedConfig.verify|verify} messages.
                 * @function encodeDelimited
                 * @memberof perfetto.protos.FtraceConfig.CompactSchedConfig
                 * @static
                 * @param {perfetto.protos.FtraceConfig.ICompactSchedConfig} message CompactSchedConfig message or plain object to encode
                 * @param {$protobuf.Writer} [writer] Writer to encode to
                 * @returns {$protobuf.Writer} Writer
                 */
                CompactSchedConfig.encodeDelimited = function encodeDelimited(message, writer) {
                    return this.encode(message, writer).ldelim();
                };

                /**
                 * Decodes a CompactSchedConfig message from the specified reader or buffer.
                 * @function decode
                 * @memberof perfetto.protos.FtraceConfig.CompactSchedConfig
                 * @static
                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                 * @param {number} [length] Message length if known beforehand
                 * @returns {perfetto.protos.FtraceConfig.CompactSchedConfig} CompactSchedConfig
                 * @throws {Error} If the payload is not a reader or valid buffer
                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
                 */
                CompactSchedConfig.decode = function decode(reader, length) {
                    if (!(reader instanceof $Reader))
                        reader = $Reader.create(reader);
                    var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.FtraceConfig.CompactSchedConfig();
                    while (reader.pos < end) {
                        var tag = reader.uint32();
                        switch (tag >>> 3) {
                        case 1:
                            message.enabled = reader.bool();
                            break;
                        default:
                            reader.skipType(tag & 7);
                            break;
                        }
                    }
                    return message;
                };

                /**
                 * Decodes a CompactSchedConfig message from the specified reader or buffer, length delimited.
                 * @function decodeDelimited
                 * @memberof perfetto.protos.FtraceConfig.CompactSchedConfig
                 * @static
                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                 * @returns {perfetto.protos.FtraceConfig.CompactSchedConfig} CompactSchedConfig
                 * @throws {Error} If the payload is not a reader or valid buffer
                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
                 */
                CompactSchedConfig.decodeDelimited = function decodeDelimited(reader) {
                    if (!(reader instanceof $Reader))
                        reader = new $Reader(reader);
                    return this.decode(reader, reader.uint32());
                };

                /**
                 * Verifies a CompactSchedConfig message.
                 * @function verify
                 * @memberof perfetto.protos.FtraceConfig.CompactSchedConfig
                 * @static
                 * @param {Object.<string,*>} message Plain object to verify
                 * @returns {string|null} `null` if valid, otherwise the reason why it is not
                 */
                CompactSchedConfig.verify = function verify(message) {
                    if (typeof message !== "object" || message === null)
                        return "object expected";
                    if (message.enabled != null && message.hasOwnProperty("enabled"))
                        if (typeof message.enabled !== "boolean")
                            return "enabled: boolean expected";
                    return null;
                };

                /**
                 * Creates a CompactSchedConfig message from a plain object. Also converts values to their respective internal types.
                 * @function fromObject
                 * @memberof perfetto.protos.FtraceConfig.CompactSchedConfig
                 * @static
                 * @param {Object.<string,*>} object Plain object
                 * @returns {perfetto.protos.FtraceConfig.CompactSchedConfig} CompactSchedConfig
                 */
                CompactSchedConfig.fromObject = function fromObject(object) {
                    if (object instanceof $root.perfetto.protos.FtraceConfig.CompactSchedConfig)
                        return object;
                    var message = new $root.perfetto.protos.FtraceConfig.CompactSchedConfig();
                    if (object.enabled != null)
                        message.enabled = Boolean(object.enabled);
                    return message;
                };

                /**
                 * Creates a plain object from a CompactSchedConfig message. Also converts values to other types if specified.
                 * @function toObject
                 * @memberof perfetto.protos.FtraceConfig.CompactSchedConfig
                 * @static
                 * @param {perfetto.protos.FtraceConfig.CompactSchedConfig} message CompactSchedConfig
                 * @param {$protobuf.IConversionOptions} [options] Conversion options
                 * @returns {Object.<string,*>} Plain object
                 */
                CompactSchedConfig.toObject = function toObject(message, options) {
                    if (!options)
                        options = {};
                    var object = {};
                    if (options.defaults)
                        object.enabled = false;
                    if (message.enabled != null && message.hasOwnProperty("enabled"))
                        object.enabled = message.enabled;
                    return object;
                };

                /**
                 * Converts this CompactSchedConfig to JSON.
                 * @function toJSON
                 * @memberof perfetto.protos.FtraceConfig.CompactSchedConfig
                 * @instance
                 * @returns {Object.<string,*>} JSON object
                 */
                CompactSchedConfig.prototype.toJSON = function toJSON() {
                    return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
                };

                return CompactSchedConfig;
            })();

            return FtraceConfig;
        })();

        protos.GpuCounterConfig = (function() {

            /**
             * Properties of a GpuCounterConfig.
             * @memberof perfetto.protos
             * @interface IGpuCounterConfig
             * @property {number|null} [counterPeriodNs] GpuCounterConfig counterPeriodNs
             * @property {Array.<number>|null} [counterIds] GpuCounterConfig counterIds
             * @property {boolean|null} [instrumentedSampling] GpuCounterConfig instrumentedSampling
             * @property {boolean|null} [fixGpuClock] GpuCounterConfig fixGpuClock
             */

            /**
             * Constructs a new GpuCounterConfig.
             * @memberof perfetto.protos
             * @classdesc Represents a GpuCounterConfig.
             * @implements IGpuCounterConfig
             * @constructor
             * @param {perfetto.protos.IGpuCounterConfig=} [properties] Properties to set
             */
            function GpuCounterConfig(properties) {
                this.counterIds = [];
                if (properties)
                    for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                        if (properties[keys[i]] != null)
                            this[keys[i]] = properties[keys[i]];
            }

            /**
             * GpuCounterConfig counterPeriodNs.
             * @member {number} counterPeriodNs
             * @memberof perfetto.protos.GpuCounterConfig
             * @instance
             */
            GpuCounterConfig.prototype.counterPeriodNs = $util.Long ? $util.Long.fromBits(0,0,true) : 0;

            /**
             * GpuCounterConfig counterIds.
             * @member {Array.<number>} counterIds
             * @memberof perfetto.protos.GpuCounterConfig
             * @instance
             */
            GpuCounterConfig.prototype.counterIds = $util.emptyArray;

            /**
             * GpuCounterConfig instrumentedSampling.
             * @member {boolean} instrumentedSampling
             * @memberof perfetto.protos.GpuCounterConfig
             * @instance
             */
            GpuCounterConfig.prototype.instrumentedSampling = false;

            /**
             * GpuCounterConfig fixGpuClock.
             * @member {boolean} fixGpuClock
             * @memberof perfetto.protos.GpuCounterConfig
             * @instance
             */
            GpuCounterConfig.prototype.fixGpuClock = false;

            /**
             * Creates a new GpuCounterConfig instance using the specified properties.
             * @function create
             * @memberof perfetto.protos.GpuCounterConfig
             * @static
             * @param {perfetto.protos.IGpuCounterConfig=} [properties] Properties to set
             * @returns {perfetto.protos.GpuCounterConfig} GpuCounterConfig instance
             */
            GpuCounterConfig.create = function create(properties) {
                return new GpuCounterConfig(properties);
            };

            /**
             * Encodes the specified GpuCounterConfig message. Does not implicitly {@link perfetto.protos.GpuCounterConfig.verify|verify} messages.
             * @function encode
             * @memberof perfetto.protos.GpuCounterConfig
             * @static
             * @param {perfetto.protos.IGpuCounterConfig} message GpuCounterConfig message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            GpuCounterConfig.encode = function encode(message, writer) {
                if (!writer)
                    writer = $Writer.create();
                if (message.counterPeriodNs != null && Object.hasOwnProperty.call(message, "counterPeriodNs"))
                    writer.uint32(/* id 1, wireType 0 =*/8).uint64(message.counterPeriodNs);
                if (message.counterIds != null && message.counterIds.length)
                    for (var i = 0; i < message.counterIds.length; ++i)
                        writer.uint32(/* id 2, wireType 0 =*/16).uint32(message.counterIds[i]);
                if (message.instrumentedSampling != null && Object.hasOwnProperty.call(message, "instrumentedSampling"))
                    writer.uint32(/* id 3, wireType 0 =*/24).bool(message.instrumentedSampling);
                if (message.fixGpuClock != null && Object.hasOwnProperty.call(message, "fixGpuClock"))
                    writer.uint32(/* id 4, wireType 0 =*/32).bool(message.fixGpuClock);
                return writer;
            };

            /**
             * Encodes the specified GpuCounterConfig message, length delimited. Does not implicitly {@link perfetto.protos.GpuCounterConfig.verify|verify} messages.
             * @function encodeDelimited
             * @memberof perfetto.protos.GpuCounterConfig
             * @static
             * @param {perfetto.protos.IGpuCounterConfig} message GpuCounterConfig message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            GpuCounterConfig.encodeDelimited = function encodeDelimited(message, writer) {
                return this.encode(message, writer).ldelim();
            };

            /**
             * Decodes a GpuCounterConfig message from the specified reader or buffer.
             * @function decode
             * @memberof perfetto.protos.GpuCounterConfig
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @param {number} [length] Message length if known beforehand
             * @returns {perfetto.protos.GpuCounterConfig} GpuCounterConfig
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            GpuCounterConfig.decode = function decode(reader, length) {
                if (!(reader instanceof $Reader))
                    reader = $Reader.create(reader);
                var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.GpuCounterConfig();
                while (reader.pos < end) {
                    var tag = reader.uint32();
                    switch (tag >>> 3) {
                    case 1:
                        message.counterPeriodNs = reader.uint64();
                        break;
                    case 2:
                        if (!(message.counterIds && message.counterIds.length))
                            message.counterIds = [];
                        if ((tag & 7) === 2) {
                            var end2 = reader.uint32() + reader.pos;
                            while (reader.pos < end2)
                                message.counterIds.push(reader.uint32());
                        } else
                            message.counterIds.push(reader.uint32());
                        break;
                    case 3:
                        message.instrumentedSampling = reader.bool();
                        break;
                    case 4:
                        message.fixGpuClock = reader.bool();
                        break;
                    default:
                        reader.skipType(tag & 7);
                        break;
                    }
                }
                return message;
            };

            /**
             * Decodes a GpuCounterConfig message from the specified reader or buffer, length delimited.
             * @function decodeDelimited
             * @memberof perfetto.protos.GpuCounterConfig
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @returns {perfetto.protos.GpuCounterConfig} GpuCounterConfig
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            GpuCounterConfig.decodeDelimited = function decodeDelimited(reader) {
                if (!(reader instanceof $Reader))
                    reader = new $Reader(reader);
                return this.decode(reader, reader.uint32());
            };

            /**
             * Verifies a GpuCounterConfig message.
             * @function verify
             * @memberof perfetto.protos.GpuCounterConfig
             * @static
             * @param {Object.<string,*>} message Plain object to verify
             * @returns {string|null} `null` if valid, otherwise the reason why it is not
             */
            GpuCounterConfig.verify = function verify(message) {
                if (typeof message !== "object" || message === null)
                    return "object expected";
                if (message.counterPeriodNs != null && message.hasOwnProperty("counterPeriodNs"))
                    if (!$util.isInteger(message.counterPeriodNs) && !(message.counterPeriodNs && $util.isInteger(message.counterPeriodNs.low) && $util.isInteger(message.counterPeriodNs.high)))
                        return "counterPeriodNs: integer|Long expected";
                if (message.counterIds != null && message.hasOwnProperty("counterIds")) {
                    if (!Array.isArray(message.counterIds))
                        return "counterIds: array expected";
                    for (var i = 0; i < message.counterIds.length; ++i)
                        if (!$util.isInteger(message.counterIds[i]))
                            return "counterIds: integer[] expected";
                }
                if (message.instrumentedSampling != null && message.hasOwnProperty("instrumentedSampling"))
                    if (typeof message.instrumentedSampling !== "boolean")
                        return "instrumentedSampling: boolean expected";
                if (message.fixGpuClock != null && message.hasOwnProperty("fixGpuClock"))
                    if (typeof message.fixGpuClock !== "boolean")
                        return "fixGpuClock: boolean expected";
                return null;
            };

            /**
             * Creates a GpuCounterConfig message from a plain object. Also converts values to their respective internal types.
             * @function fromObject
             * @memberof perfetto.protos.GpuCounterConfig
             * @static
             * @param {Object.<string,*>} object Plain object
             * @returns {perfetto.protos.GpuCounterConfig} GpuCounterConfig
             */
            GpuCounterConfig.fromObject = function fromObject(object) {
                if (object instanceof $root.perfetto.protos.GpuCounterConfig)
                    return object;
                var message = new $root.perfetto.protos.GpuCounterConfig();
                if (object.counterPeriodNs != null)
                    if ($util.Long)
                        (message.counterPeriodNs = $util.Long.fromValue(object.counterPeriodNs)).unsigned = true;
                    else if (typeof object.counterPeriodNs === "string")
                        message.counterPeriodNs = parseInt(object.counterPeriodNs, 10);
                    else if (typeof object.counterPeriodNs === "number")
                        message.counterPeriodNs = object.counterPeriodNs;
                    else if (typeof object.counterPeriodNs === "object")
                        message.counterPeriodNs = new $util.LongBits(object.counterPeriodNs.low >>> 0, object.counterPeriodNs.high >>> 0).toNumber(true);
                if (object.counterIds) {
                    if (!Array.isArray(object.counterIds))
                        throw TypeError(".perfetto.protos.GpuCounterConfig.counterIds: array expected");
                    message.counterIds = [];
                    for (var i = 0; i < object.counterIds.length; ++i)
                        message.counterIds[i] = object.counterIds[i] >>> 0;
                }
                if (object.instrumentedSampling != null)
                    message.instrumentedSampling = Boolean(object.instrumentedSampling);
                if (object.fixGpuClock != null)
                    message.fixGpuClock = Boolean(object.fixGpuClock);
                return message;
            };

            /**
             * Creates a plain object from a GpuCounterConfig message. Also converts values to other types if specified.
             * @function toObject
             * @memberof perfetto.protos.GpuCounterConfig
             * @static
             * @param {perfetto.protos.GpuCounterConfig} message GpuCounterConfig
             * @param {$protobuf.IConversionOptions} [options] Conversion options
             * @returns {Object.<string,*>} Plain object
             */
            GpuCounterConfig.toObject = function toObject(message, options) {
                if (!options)
                    options = {};
                var object = {};
                if (options.arrays || options.defaults)
                    object.counterIds = [];
                if (options.defaults) {
                    if ($util.Long) {
                        var long = new $util.Long(0, 0, true);
                        object.counterPeriodNs = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
                    } else
                        object.counterPeriodNs = options.longs === String ? "0" : 0;
                    object.instrumentedSampling = false;
                    object.fixGpuClock = false;
                }
                if (message.counterPeriodNs != null && message.hasOwnProperty("counterPeriodNs"))
                    if (typeof message.counterPeriodNs === "number")
                        object.counterPeriodNs = options.longs === String ? String(message.counterPeriodNs) : message.counterPeriodNs;
                    else
                        object.counterPeriodNs = options.longs === String ? $util.Long.prototype.toString.call(message.counterPeriodNs) : options.longs === Number ? new $util.LongBits(message.counterPeriodNs.low >>> 0, message.counterPeriodNs.high >>> 0).toNumber(true) : message.counterPeriodNs;
                if (message.counterIds && message.counterIds.length) {
                    object.counterIds = [];
                    for (var j = 0; j < message.counterIds.length; ++j)
                        object.counterIds[j] = message.counterIds[j];
                }
                if (message.instrumentedSampling != null && message.hasOwnProperty("instrumentedSampling"))
                    object.instrumentedSampling = message.instrumentedSampling;
                if (message.fixGpuClock != null && message.hasOwnProperty("fixGpuClock"))
                    object.fixGpuClock = message.fixGpuClock;
                return object;
            };

            /**
             * Converts this GpuCounterConfig to JSON.
             * @function toJSON
             * @memberof perfetto.protos.GpuCounterConfig
             * @instance
             * @returns {Object.<string,*>} JSON object
             */
            GpuCounterConfig.prototype.toJSON = function toJSON() {
                return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
            };

            return GpuCounterConfig;
        })();

        protos.VulkanMemoryConfig = (function() {

            /**
             * Properties of a VulkanMemoryConfig.
             * @memberof perfetto.protos
             * @interface IVulkanMemoryConfig
             * @property {boolean|null} [trackDriverMemoryUsage] VulkanMemoryConfig trackDriverMemoryUsage
             * @property {boolean|null} [trackDeviceMemoryUsage] VulkanMemoryConfig trackDeviceMemoryUsage
             */

            /**
             * Constructs a new VulkanMemoryConfig.
             * @memberof perfetto.protos
             * @classdesc Represents a VulkanMemoryConfig.
             * @implements IVulkanMemoryConfig
             * @constructor
             * @param {perfetto.protos.IVulkanMemoryConfig=} [properties] Properties to set
             */
            function VulkanMemoryConfig(properties) {
                if (properties)
                    for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                        if (properties[keys[i]] != null)
                            this[keys[i]] = properties[keys[i]];
            }

            /**
             * VulkanMemoryConfig trackDriverMemoryUsage.
             * @member {boolean} trackDriverMemoryUsage
             * @memberof perfetto.protos.VulkanMemoryConfig
             * @instance
             */
            VulkanMemoryConfig.prototype.trackDriverMemoryUsage = false;

            /**
             * VulkanMemoryConfig trackDeviceMemoryUsage.
             * @member {boolean} trackDeviceMemoryUsage
             * @memberof perfetto.protos.VulkanMemoryConfig
             * @instance
             */
            VulkanMemoryConfig.prototype.trackDeviceMemoryUsage = false;

            /**
             * Creates a new VulkanMemoryConfig instance using the specified properties.
             * @function create
             * @memberof perfetto.protos.VulkanMemoryConfig
             * @static
             * @param {perfetto.protos.IVulkanMemoryConfig=} [properties] Properties to set
             * @returns {perfetto.protos.VulkanMemoryConfig} VulkanMemoryConfig instance
             */
            VulkanMemoryConfig.create = function create(properties) {
                return new VulkanMemoryConfig(properties);
            };

            /**
             * Encodes the specified VulkanMemoryConfig message. Does not implicitly {@link perfetto.protos.VulkanMemoryConfig.verify|verify} messages.
             * @function encode
             * @memberof perfetto.protos.VulkanMemoryConfig
             * @static
             * @param {perfetto.protos.IVulkanMemoryConfig} message VulkanMemoryConfig message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            VulkanMemoryConfig.encode = function encode(message, writer) {
                if (!writer)
                    writer = $Writer.create();
                if (message.trackDriverMemoryUsage != null && Object.hasOwnProperty.call(message, "trackDriverMemoryUsage"))
                    writer.uint32(/* id 1, wireType 0 =*/8).bool(message.trackDriverMemoryUsage);
                if (message.trackDeviceMemoryUsage != null && Object.hasOwnProperty.call(message, "trackDeviceMemoryUsage"))
                    writer.uint32(/* id 2, wireType 0 =*/16).bool(message.trackDeviceMemoryUsage);
                return writer;
            };

            /**
             * Encodes the specified VulkanMemoryConfig message, length delimited. Does not implicitly {@link perfetto.protos.VulkanMemoryConfig.verify|verify} messages.
             * @function encodeDelimited
             * @memberof perfetto.protos.VulkanMemoryConfig
             * @static
             * @param {perfetto.protos.IVulkanMemoryConfig} message VulkanMemoryConfig message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            VulkanMemoryConfig.encodeDelimited = function encodeDelimited(message, writer) {
                return this.encode(message, writer).ldelim();
            };

            /**
             * Decodes a VulkanMemoryConfig message from the specified reader or buffer.
             * @function decode
             * @memberof perfetto.protos.VulkanMemoryConfig
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @param {number} [length] Message length if known beforehand
             * @returns {perfetto.protos.VulkanMemoryConfig} VulkanMemoryConfig
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            VulkanMemoryConfig.decode = function decode(reader, length) {
                if (!(reader instanceof $Reader))
                    reader = $Reader.create(reader);
                var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.VulkanMemoryConfig();
                while (reader.pos < end) {
                    var tag = reader.uint32();
                    switch (tag >>> 3) {
                    case 1:
                        message.trackDriverMemoryUsage = reader.bool();
                        break;
                    case 2:
                        message.trackDeviceMemoryUsage = reader.bool();
                        break;
                    default:
                        reader.skipType(tag & 7);
                        break;
                    }
                }
                return message;
            };

            /**
             * Decodes a VulkanMemoryConfig message from the specified reader or buffer, length delimited.
             * @function decodeDelimited
             * @memberof perfetto.protos.VulkanMemoryConfig
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @returns {perfetto.protos.VulkanMemoryConfig} VulkanMemoryConfig
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            VulkanMemoryConfig.decodeDelimited = function decodeDelimited(reader) {
                if (!(reader instanceof $Reader))
                    reader = new $Reader(reader);
                return this.decode(reader, reader.uint32());
            };

            /**
             * Verifies a VulkanMemoryConfig message.
             * @function verify
             * @memberof perfetto.protos.VulkanMemoryConfig
             * @static
             * @param {Object.<string,*>} message Plain object to verify
             * @returns {string|null} `null` if valid, otherwise the reason why it is not
             */
            VulkanMemoryConfig.verify = function verify(message) {
                if (typeof message !== "object" || message === null)
                    return "object expected";
                if (message.trackDriverMemoryUsage != null && message.hasOwnProperty("trackDriverMemoryUsage"))
                    if (typeof message.trackDriverMemoryUsage !== "boolean")
                        return "trackDriverMemoryUsage: boolean expected";
                if (message.trackDeviceMemoryUsage != null && message.hasOwnProperty("trackDeviceMemoryUsage"))
                    if (typeof message.trackDeviceMemoryUsage !== "boolean")
                        return "trackDeviceMemoryUsage: boolean expected";
                return null;
            };

            /**
             * Creates a VulkanMemoryConfig message from a plain object. Also converts values to their respective internal types.
             * @function fromObject
             * @memberof perfetto.protos.VulkanMemoryConfig
             * @static
             * @param {Object.<string,*>} object Plain object
             * @returns {perfetto.protos.VulkanMemoryConfig} VulkanMemoryConfig
             */
            VulkanMemoryConfig.fromObject = function fromObject(object) {
                if (object instanceof $root.perfetto.protos.VulkanMemoryConfig)
                    return object;
                var message = new $root.perfetto.protos.VulkanMemoryConfig();
                if (object.trackDriverMemoryUsage != null)
                    message.trackDriverMemoryUsage = Boolean(object.trackDriverMemoryUsage);
                if (object.trackDeviceMemoryUsage != null)
                    message.trackDeviceMemoryUsage = Boolean(object.trackDeviceMemoryUsage);
                return message;
            };

            /**
             * Creates a plain object from a VulkanMemoryConfig message. Also converts values to other types if specified.
             * @function toObject
             * @memberof perfetto.protos.VulkanMemoryConfig
             * @static
             * @param {perfetto.protos.VulkanMemoryConfig} message VulkanMemoryConfig
             * @param {$protobuf.IConversionOptions} [options] Conversion options
             * @returns {Object.<string,*>} Plain object
             */
            VulkanMemoryConfig.toObject = function toObject(message, options) {
                if (!options)
                    options = {};
                var object = {};
                if (options.defaults) {
                    object.trackDriverMemoryUsage = false;
                    object.trackDeviceMemoryUsage = false;
                }
                if (message.trackDriverMemoryUsage != null && message.hasOwnProperty("trackDriverMemoryUsage"))
                    object.trackDriverMemoryUsage = message.trackDriverMemoryUsage;
                if (message.trackDeviceMemoryUsage != null && message.hasOwnProperty("trackDeviceMemoryUsage"))
                    object.trackDeviceMemoryUsage = message.trackDeviceMemoryUsage;
                return object;
            };

            /**
             * Converts this VulkanMemoryConfig to JSON.
             * @function toJSON
             * @memberof perfetto.protos.VulkanMemoryConfig
             * @instance
             * @returns {Object.<string,*>} JSON object
             */
            VulkanMemoryConfig.prototype.toJSON = function toJSON() {
                return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
            };

            return VulkanMemoryConfig;
        })();

        protos.InodeFileConfig = (function() {

            /**
             * Properties of an InodeFileConfig.
             * @memberof perfetto.protos
             * @interface IInodeFileConfig
             * @property {number|null} [scanIntervalMs] InodeFileConfig scanIntervalMs
             * @property {number|null} [scanDelayMs] InodeFileConfig scanDelayMs
             * @property {number|null} [scanBatchSize] InodeFileConfig scanBatchSize
             * @property {boolean|null} [doNotScan] InodeFileConfig doNotScan
             * @property {Array.<string>|null} [scanMountPoints] InodeFileConfig scanMountPoints
             * @property {Array.<perfetto.protos.InodeFileConfig.IMountPointMappingEntry>|null} [mountPointMapping] InodeFileConfig mountPointMapping
             */

            /**
             * Constructs a new InodeFileConfig.
             * @memberof perfetto.protos
             * @classdesc Represents an InodeFileConfig.
             * @implements IInodeFileConfig
             * @constructor
             * @param {perfetto.protos.IInodeFileConfig=} [properties] Properties to set
             */
            function InodeFileConfig(properties) {
                this.scanMountPoints = [];
                this.mountPointMapping = [];
                if (properties)
                    for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                        if (properties[keys[i]] != null)
                            this[keys[i]] = properties[keys[i]];
            }

            /**
             * InodeFileConfig scanIntervalMs.
             * @member {number} scanIntervalMs
             * @memberof perfetto.protos.InodeFileConfig
             * @instance
             */
            InodeFileConfig.prototype.scanIntervalMs = 0;

            /**
             * InodeFileConfig scanDelayMs.
             * @member {number} scanDelayMs
             * @memberof perfetto.protos.InodeFileConfig
             * @instance
             */
            InodeFileConfig.prototype.scanDelayMs = 0;

            /**
             * InodeFileConfig scanBatchSize.
             * @member {number} scanBatchSize
             * @memberof perfetto.protos.InodeFileConfig
             * @instance
             */
            InodeFileConfig.prototype.scanBatchSize = 0;

            /**
             * InodeFileConfig doNotScan.
             * @member {boolean} doNotScan
             * @memberof perfetto.protos.InodeFileConfig
             * @instance
             */
            InodeFileConfig.prototype.doNotScan = false;

            /**
             * InodeFileConfig scanMountPoints.
             * @member {Array.<string>} scanMountPoints
             * @memberof perfetto.protos.InodeFileConfig
             * @instance
             */
            InodeFileConfig.prototype.scanMountPoints = $util.emptyArray;

            /**
             * InodeFileConfig mountPointMapping.
             * @member {Array.<perfetto.protos.InodeFileConfig.IMountPointMappingEntry>} mountPointMapping
             * @memberof perfetto.protos.InodeFileConfig
             * @instance
             */
            InodeFileConfig.prototype.mountPointMapping = $util.emptyArray;

            /**
             * Creates a new InodeFileConfig instance using the specified properties.
             * @function create
             * @memberof perfetto.protos.InodeFileConfig
             * @static
             * @param {perfetto.protos.IInodeFileConfig=} [properties] Properties to set
             * @returns {perfetto.protos.InodeFileConfig} InodeFileConfig instance
             */
            InodeFileConfig.create = function create(properties) {
                return new InodeFileConfig(properties);
            };

            /**
             * Encodes the specified InodeFileConfig message. Does not implicitly {@link perfetto.protos.InodeFileConfig.verify|verify} messages.
             * @function encode
             * @memberof perfetto.protos.InodeFileConfig
             * @static
             * @param {perfetto.protos.IInodeFileConfig} message InodeFileConfig message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            InodeFileConfig.encode = function encode(message, writer) {
                if (!writer)
                    writer = $Writer.create();
                if (message.scanIntervalMs != null && Object.hasOwnProperty.call(message, "scanIntervalMs"))
                    writer.uint32(/* id 1, wireType 0 =*/8).uint32(message.scanIntervalMs);
                if (message.scanDelayMs != null && Object.hasOwnProperty.call(message, "scanDelayMs"))
                    writer.uint32(/* id 2, wireType 0 =*/16).uint32(message.scanDelayMs);
                if (message.scanBatchSize != null && Object.hasOwnProperty.call(message, "scanBatchSize"))
                    writer.uint32(/* id 3, wireType 0 =*/24).uint32(message.scanBatchSize);
                if (message.doNotScan != null && Object.hasOwnProperty.call(message, "doNotScan"))
                    writer.uint32(/* id 4, wireType 0 =*/32).bool(message.doNotScan);
                if (message.scanMountPoints != null && message.scanMountPoints.length)
                    for (var i = 0; i < message.scanMountPoints.length; ++i)
                        writer.uint32(/* id 5, wireType 2 =*/42).string(message.scanMountPoints[i]);
                if (message.mountPointMapping != null && message.mountPointMapping.length)
                    for (var i = 0; i < message.mountPointMapping.length; ++i)
                        $root.perfetto.protos.InodeFileConfig.MountPointMappingEntry.encode(message.mountPointMapping[i], writer.uint32(/* id 6, wireType 2 =*/50).fork()).ldelim();
                return writer;
            };

            /**
             * Encodes the specified InodeFileConfig message, length delimited. Does not implicitly {@link perfetto.protos.InodeFileConfig.verify|verify} messages.
             * @function encodeDelimited
             * @memberof perfetto.protos.InodeFileConfig
             * @static
             * @param {perfetto.protos.IInodeFileConfig} message InodeFileConfig message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            InodeFileConfig.encodeDelimited = function encodeDelimited(message, writer) {
                return this.encode(message, writer).ldelim();
            };

            /**
             * Decodes an InodeFileConfig message from the specified reader or buffer.
             * @function decode
             * @memberof perfetto.protos.InodeFileConfig
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @param {number} [length] Message length if known beforehand
             * @returns {perfetto.protos.InodeFileConfig} InodeFileConfig
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            InodeFileConfig.decode = function decode(reader, length) {
                if (!(reader instanceof $Reader))
                    reader = $Reader.create(reader);
                var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.InodeFileConfig();
                while (reader.pos < end) {
                    var tag = reader.uint32();
                    switch (tag >>> 3) {
                    case 1:
                        message.scanIntervalMs = reader.uint32();
                        break;
                    case 2:
                        message.scanDelayMs = reader.uint32();
                        break;
                    case 3:
                        message.scanBatchSize = reader.uint32();
                        break;
                    case 4:
                        message.doNotScan = reader.bool();
                        break;
                    case 5:
                        if (!(message.scanMountPoints && message.scanMountPoints.length))
                            message.scanMountPoints = [];
                        message.scanMountPoints.push(reader.string());
                        break;
                    case 6:
                        if (!(message.mountPointMapping && message.mountPointMapping.length))
                            message.mountPointMapping = [];
                        message.mountPointMapping.push($root.perfetto.protos.InodeFileConfig.MountPointMappingEntry.decode(reader, reader.uint32()));
                        break;
                    default:
                        reader.skipType(tag & 7);
                        break;
                    }
                }
                return message;
            };

            /**
             * Decodes an InodeFileConfig message from the specified reader or buffer, length delimited.
             * @function decodeDelimited
             * @memberof perfetto.protos.InodeFileConfig
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @returns {perfetto.protos.InodeFileConfig} InodeFileConfig
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            InodeFileConfig.decodeDelimited = function decodeDelimited(reader) {
                if (!(reader instanceof $Reader))
                    reader = new $Reader(reader);
                return this.decode(reader, reader.uint32());
            };

            /**
             * Verifies an InodeFileConfig message.
             * @function verify
             * @memberof perfetto.protos.InodeFileConfig
             * @static
             * @param {Object.<string,*>} message Plain object to verify
             * @returns {string|null} `null` if valid, otherwise the reason why it is not
             */
            InodeFileConfig.verify = function verify(message) {
                if (typeof message !== "object" || message === null)
                    return "object expected";
                if (message.scanIntervalMs != null && message.hasOwnProperty("scanIntervalMs"))
                    if (!$util.isInteger(message.scanIntervalMs))
                        return "scanIntervalMs: integer expected";
                if (message.scanDelayMs != null && message.hasOwnProperty("scanDelayMs"))
                    if (!$util.isInteger(message.scanDelayMs))
                        return "scanDelayMs: integer expected";
                if (message.scanBatchSize != null && message.hasOwnProperty("scanBatchSize"))
                    if (!$util.isInteger(message.scanBatchSize))
                        return "scanBatchSize: integer expected";
                if (message.doNotScan != null && message.hasOwnProperty("doNotScan"))
                    if (typeof message.doNotScan !== "boolean")
                        return "doNotScan: boolean expected";
                if (message.scanMountPoints != null && message.hasOwnProperty("scanMountPoints")) {
                    if (!Array.isArray(message.scanMountPoints))
                        return "scanMountPoints: array expected";
                    for (var i = 0; i < message.scanMountPoints.length; ++i)
                        if (!$util.isString(message.scanMountPoints[i]))
                            return "scanMountPoints: string[] expected";
                }
                if (message.mountPointMapping != null && message.hasOwnProperty("mountPointMapping")) {
                    if (!Array.isArray(message.mountPointMapping))
                        return "mountPointMapping: array expected";
                    for (var i = 0; i < message.mountPointMapping.length; ++i) {
                        var error = $root.perfetto.protos.InodeFileConfig.MountPointMappingEntry.verify(message.mountPointMapping[i]);
                        if (error)
                            return "mountPointMapping." + error;
                    }
                }
                return null;
            };

            /**
             * Creates an InodeFileConfig message from a plain object. Also converts values to their respective internal types.
             * @function fromObject
             * @memberof perfetto.protos.InodeFileConfig
             * @static
             * @param {Object.<string,*>} object Plain object
             * @returns {perfetto.protos.InodeFileConfig} InodeFileConfig
             */
            InodeFileConfig.fromObject = function fromObject(object) {
                if (object instanceof $root.perfetto.protos.InodeFileConfig)
                    return object;
                var message = new $root.perfetto.protos.InodeFileConfig();
                if (object.scanIntervalMs != null)
                    message.scanIntervalMs = object.scanIntervalMs >>> 0;
                if (object.scanDelayMs != null)
                    message.scanDelayMs = object.scanDelayMs >>> 0;
                if (object.scanBatchSize != null)
                    message.scanBatchSize = object.scanBatchSize >>> 0;
                if (object.doNotScan != null)
                    message.doNotScan = Boolean(object.doNotScan);
                if (object.scanMountPoints) {
                    if (!Array.isArray(object.scanMountPoints))
                        throw TypeError(".perfetto.protos.InodeFileConfig.scanMountPoints: array expected");
                    message.scanMountPoints = [];
                    for (var i = 0; i < object.scanMountPoints.length; ++i)
                        message.scanMountPoints[i] = String(object.scanMountPoints[i]);
                }
                if (object.mountPointMapping) {
                    if (!Array.isArray(object.mountPointMapping))
                        throw TypeError(".perfetto.protos.InodeFileConfig.mountPointMapping: array expected");
                    message.mountPointMapping = [];
                    for (var i = 0; i < object.mountPointMapping.length; ++i) {
                        if (typeof object.mountPointMapping[i] !== "object")
                            throw TypeError(".perfetto.protos.InodeFileConfig.mountPointMapping: object expected");
                        message.mountPointMapping[i] = $root.perfetto.protos.InodeFileConfig.MountPointMappingEntry.fromObject(object.mountPointMapping[i]);
                    }
                }
                return message;
            };

            /**
             * Creates a plain object from an InodeFileConfig message. Also converts values to other types if specified.
             * @function toObject
             * @memberof perfetto.protos.InodeFileConfig
             * @static
             * @param {perfetto.protos.InodeFileConfig} message InodeFileConfig
             * @param {$protobuf.IConversionOptions} [options] Conversion options
             * @returns {Object.<string,*>} Plain object
             */
            InodeFileConfig.toObject = function toObject(message, options) {
                if (!options)
                    options = {};
                var object = {};
                if (options.arrays || options.defaults) {
                    object.scanMountPoints = [];
                    object.mountPointMapping = [];
                }
                if (options.defaults) {
                    object.scanIntervalMs = 0;
                    object.scanDelayMs = 0;
                    object.scanBatchSize = 0;
                    object.doNotScan = false;
                }
                if (message.scanIntervalMs != null && message.hasOwnProperty("scanIntervalMs"))
                    object.scanIntervalMs = message.scanIntervalMs;
                if (message.scanDelayMs != null && message.hasOwnProperty("scanDelayMs"))
                    object.scanDelayMs = message.scanDelayMs;
                if (message.scanBatchSize != null && message.hasOwnProperty("scanBatchSize"))
                    object.scanBatchSize = message.scanBatchSize;
                if (message.doNotScan != null && message.hasOwnProperty("doNotScan"))
                    object.doNotScan = message.doNotScan;
                if (message.scanMountPoints && message.scanMountPoints.length) {
                    object.scanMountPoints = [];
                    for (var j = 0; j < message.scanMountPoints.length; ++j)
                        object.scanMountPoints[j] = message.scanMountPoints[j];
                }
                if (message.mountPointMapping && message.mountPointMapping.length) {
                    object.mountPointMapping = [];
                    for (var j = 0; j < message.mountPointMapping.length; ++j)
                        object.mountPointMapping[j] = $root.perfetto.protos.InodeFileConfig.MountPointMappingEntry.toObject(message.mountPointMapping[j], options);
                }
                return object;
            };

            /**
             * Converts this InodeFileConfig to JSON.
             * @function toJSON
             * @memberof perfetto.protos.InodeFileConfig
             * @instance
             * @returns {Object.<string,*>} JSON object
             */
            InodeFileConfig.prototype.toJSON = function toJSON() {
                return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
            };

            InodeFileConfig.MountPointMappingEntry = (function() {

                /**
                 * Properties of a MountPointMappingEntry.
                 * @memberof perfetto.protos.InodeFileConfig
                 * @interface IMountPointMappingEntry
                 * @property {string|null} [mountpoint] MountPointMappingEntry mountpoint
                 * @property {Array.<string>|null} [scanRoots] MountPointMappingEntry scanRoots
                 */

                /**
                 * Constructs a new MountPointMappingEntry.
                 * @memberof perfetto.protos.InodeFileConfig
                 * @classdesc Represents a MountPointMappingEntry.
                 * @implements IMountPointMappingEntry
                 * @constructor
                 * @param {perfetto.protos.InodeFileConfig.IMountPointMappingEntry=} [properties] Properties to set
                 */
                function MountPointMappingEntry(properties) {
                    this.scanRoots = [];
                    if (properties)
                        for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                            if (properties[keys[i]] != null)
                                this[keys[i]] = properties[keys[i]];
                }

                /**
                 * MountPointMappingEntry mountpoint.
                 * @member {string} mountpoint
                 * @memberof perfetto.protos.InodeFileConfig.MountPointMappingEntry
                 * @instance
                 */
                MountPointMappingEntry.prototype.mountpoint = "";

                /**
                 * MountPointMappingEntry scanRoots.
                 * @member {Array.<string>} scanRoots
                 * @memberof perfetto.protos.InodeFileConfig.MountPointMappingEntry
                 * @instance
                 */
                MountPointMappingEntry.prototype.scanRoots = $util.emptyArray;

                /**
                 * Creates a new MountPointMappingEntry instance using the specified properties.
                 * @function create
                 * @memberof perfetto.protos.InodeFileConfig.MountPointMappingEntry
                 * @static
                 * @param {perfetto.protos.InodeFileConfig.IMountPointMappingEntry=} [properties] Properties to set
                 * @returns {perfetto.protos.InodeFileConfig.MountPointMappingEntry} MountPointMappingEntry instance
                 */
                MountPointMappingEntry.create = function create(properties) {
                    return new MountPointMappingEntry(properties);
                };

                /**
                 * Encodes the specified MountPointMappingEntry message. Does not implicitly {@link perfetto.protos.InodeFileConfig.MountPointMappingEntry.verify|verify} messages.
                 * @function encode
                 * @memberof perfetto.protos.InodeFileConfig.MountPointMappingEntry
                 * @static
                 * @param {perfetto.protos.InodeFileConfig.IMountPointMappingEntry} message MountPointMappingEntry message or plain object to encode
                 * @param {$protobuf.Writer} [writer] Writer to encode to
                 * @returns {$protobuf.Writer} Writer
                 */
                MountPointMappingEntry.encode = function encode(message, writer) {
                    if (!writer)
                        writer = $Writer.create();
                    if (message.mountpoint != null && Object.hasOwnProperty.call(message, "mountpoint"))
                        writer.uint32(/* id 1, wireType 2 =*/10).string(message.mountpoint);
                    if (message.scanRoots != null && message.scanRoots.length)
                        for (var i = 0; i < message.scanRoots.length; ++i)
                            writer.uint32(/* id 2, wireType 2 =*/18).string(message.scanRoots[i]);
                    return writer;
                };

                /**
                 * Encodes the specified MountPointMappingEntry message, length delimited. Does not implicitly {@link perfetto.protos.InodeFileConfig.MountPointMappingEntry.verify|verify} messages.
                 * @function encodeDelimited
                 * @memberof perfetto.protos.InodeFileConfig.MountPointMappingEntry
                 * @static
                 * @param {perfetto.protos.InodeFileConfig.IMountPointMappingEntry} message MountPointMappingEntry message or plain object to encode
                 * @param {$protobuf.Writer} [writer] Writer to encode to
                 * @returns {$protobuf.Writer} Writer
                 */
                MountPointMappingEntry.encodeDelimited = function encodeDelimited(message, writer) {
                    return this.encode(message, writer).ldelim();
                };

                /**
                 * Decodes a MountPointMappingEntry message from the specified reader or buffer.
                 * @function decode
                 * @memberof perfetto.protos.InodeFileConfig.MountPointMappingEntry
                 * @static
                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                 * @param {number} [length] Message length if known beforehand
                 * @returns {perfetto.protos.InodeFileConfig.MountPointMappingEntry} MountPointMappingEntry
                 * @throws {Error} If the payload is not a reader or valid buffer
                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
                 */
                MountPointMappingEntry.decode = function decode(reader, length) {
                    if (!(reader instanceof $Reader))
                        reader = $Reader.create(reader);
                    var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.InodeFileConfig.MountPointMappingEntry();
                    while (reader.pos < end) {
                        var tag = reader.uint32();
                        switch (tag >>> 3) {
                        case 1:
                            message.mountpoint = reader.string();
                            break;
                        case 2:
                            if (!(message.scanRoots && message.scanRoots.length))
                                message.scanRoots = [];
                            message.scanRoots.push(reader.string());
                            break;
                        default:
                            reader.skipType(tag & 7);
                            break;
                        }
                    }
                    return message;
                };

                /**
                 * Decodes a MountPointMappingEntry message from the specified reader or buffer, length delimited.
                 * @function decodeDelimited
                 * @memberof perfetto.protos.InodeFileConfig.MountPointMappingEntry
                 * @static
                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                 * @returns {perfetto.protos.InodeFileConfig.MountPointMappingEntry} MountPointMappingEntry
                 * @throws {Error} If the payload is not a reader or valid buffer
                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
                 */
                MountPointMappingEntry.decodeDelimited = function decodeDelimited(reader) {
                    if (!(reader instanceof $Reader))
                        reader = new $Reader(reader);
                    return this.decode(reader, reader.uint32());
                };

                /**
                 * Verifies a MountPointMappingEntry message.
                 * @function verify
                 * @memberof perfetto.protos.InodeFileConfig.MountPointMappingEntry
                 * @static
                 * @param {Object.<string,*>} message Plain object to verify
                 * @returns {string|null} `null` if valid, otherwise the reason why it is not
                 */
                MountPointMappingEntry.verify = function verify(message) {
                    if (typeof message !== "object" || message === null)
                        return "object expected";
                    if (message.mountpoint != null && message.hasOwnProperty("mountpoint"))
                        if (!$util.isString(message.mountpoint))
                            return "mountpoint: string expected";
                    if (message.scanRoots != null && message.hasOwnProperty("scanRoots")) {
                        if (!Array.isArray(message.scanRoots))
                            return "scanRoots: array expected";
                        for (var i = 0; i < message.scanRoots.length; ++i)
                            if (!$util.isString(message.scanRoots[i]))
                                return "scanRoots: string[] expected";
                    }
                    return null;
                };

                /**
                 * Creates a MountPointMappingEntry message from a plain object. Also converts values to their respective internal types.
                 * @function fromObject
                 * @memberof perfetto.protos.InodeFileConfig.MountPointMappingEntry
                 * @static
                 * @param {Object.<string,*>} object Plain object
                 * @returns {perfetto.protos.InodeFileConfig.MountPointMappingEntry} MountPointMappingEntry
                 */
                MountPointMappingEntry.fromObject = function fromObject(object) {
                    if (object instanceof $root.perfetto.protos.InodeFileConfig.MountPointMappingEntry)
                        return object;
                    var message = new $root.perfetto.protos.InodeFileConfig.MountPointMappingEntry();
                    if (object.mountpoint != null)
                        message.mountpoint = String(object.mountpoint);
                    if (object.scanRoots) {
                        if (!Array.isArray(object.scanRoots))
                            throw TypeError(".perfetto.protos.InodeFileConfig.MountPointMappingEntry.scanRoots: array expected");
                        message.scanRoots = [];
                        for (var i = 0; i < object.scanRoots.length; ++i)
                            message.scanRoots[i] = String(object.scanRoots[i]);
                    }
                    return message;
                };

                /**
                 * Creates a plain object from a MountPointMappingEntry message. Also converts values to other types if specified.
                 * @function toObject
                 * @memberof perfetto.protos.InodeFileConfig.MountPointMappingEntry
                 * @static
                 * @param {perfetto.protos.InodeFileConfig.MountPointMappingEntry} message MountPointMappingEntry
                 * @param {$protobuf.IConversionOptions} [options] Conversion options
                 * @returns {Object.<string,*>} Plain object
                 */
                MountPointMappingEntry.toObject = function toObject(message, options) {
                    if (!options)
                        options = {};
                    var object = {};
                    if (options.arrays || options.defaults)
                        object.scanRoots = [];
                    if (options.defaults)
                        object.mountpoint = "";
                    if (message.mountpoint != null && message.hasOwnProperty("mountpoint"))
                        object.mountpoint = message.mountpoint;
                    if (message.scanRoots && message.scanRoots.length) {
                        object.scanRoots = [];
                        for (var j = 0; j < message.scanRoots.length; ++j)
                            object.scanRoots[j] = message.scanRoots[j];
                    }
                    return object;
                };

                /**
                 * Converts this MountPointMappingEntry to JSON.
                 * @function toJSON
                 * @memberof perfetto.protos.InodeFileConfig.MountPointMappingEntry
                 * @instance
                 * @returns {Object.<string,*>} JSON object
                 */
                MountPointMappingEntry.prototype.toJSON = function toJSON() {
                    return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
                };

                return MountPointMappingEntry;
            })();

            return InodeFileConfig;
        })();

        protos.ConsoleConfig = (function() {

            /**
             * Properties of a ConsoleConfig.
             * @memberof perfetto.protos
             * @interface IConsoleConfig
             * @property {perfetto.protos.ConsoleConfig.Output|null} [output] ConsoleConfig output
             * @property {boolean|null} [enableColors] ConsoleConfig enableColors
             */

            /**
             * Constructs a new ConsoleConfig.
             * @memberof perfetto.protos
             * @classdesc Represents a ConsoleConfig.
             * @implements IConsoleConfig
             * @constructor
             * @param {perfetto.protos.IConsoleConfig=} [properties] Properties to set
             */
            function ConsoleConfig(properties) {
                if (properties)
                    for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                        if (properties[keys[i]] != null)
                            this[keys[i]] = properties[keys[i]];
            }

            /**
             * ConsoleConfig output.
             * @member {perfetto.protos.ConsoleConfig.Output} output
             * @memberof perfetto.protos.ConsoleConfig
             * @instance
             */
            ConsoleConfig.prototype.output = 0;

            /**
             * ConsoleConfig enableColors.
             * @member {boolean} enableColors
             * @memberof perfetto.protos.ConsoleConfig
             * @instance
             */
            ConsoleConfig.prototype.enableColors = false;

            /**
             * Creates a new ConsoleConfig instance using the specified properties.
             * @function create
             * @memberof perfetto.protos.ConsoleConfig
             * @static
             * @param {perfetto.protos.IConsoleConfig=} [properties] Properties to set
             * @returns {perfetto.protos.ConsoleConfig} ConsoleConfig instance
             */
            ConsoleConfig.create = function create(properties) {
                return new ConsoleConfig(properties);
            };

            /**
             * Encodes the specified ConsoleConfig message. Does not implicitly {@link perfetto.protos.ConsoleConfig.verify|verify} messages.
             * @function encode
             * @memberof perfetto.protos.ConsoleConfig
             * @static
             * @param {perfetto.protos.IConsoleConfig} message ConsoleConfig message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            ConsoleConfig.encode = function encode(message, writer) {
                if (!writer)
                    writer = $Writer.create();
                if (message.output != null && Object.hasOwnProperty.call(message, "output"))
                    writer.uint32(/* id 1, wireType 0 =*/8).int32(message.output);
                if (message.enableColors != null && Object.hasOwnProperty.call(message, "enableColors"))
                    writer.uint32(/* id 2, wireType 0 =*/16).bool(message.enableColors);
                return writer;
            };

            /**
             * Encodes the specified ConsoleConfig message, length delimited. Does not implicitly {@link perfetto.protos.ConsoleConfig.verify|verify} messages.
             * @function encodeDelimited
             * @memberof perfetto.protos.ConsoleConfig
             * @static
             * @param {perfetto.protos.IConsoleConfig} message ConsoleConfig message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            ConsoleConfig.encodeDelimited = function encodeDelimited(message, writer) {
                return this.encode(message, writer).ldelim();
            };

            /**
             * Decodes a ConsoleConfig message from the specified reader or buffer.
             * @function decode
             * @memberof perfetto.protos.ConsoleConfig
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @param {number} [length] Message length if known beforehand
             * @returns {perfetto.protos.ConsoleConfig} ConsoleConfig
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            ConsoleConfig.decode = function decode(reader, length) {
                if (!(reader instanceof $Reader))
                    reader = $Reader.create(reader);
                var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.ConsoleConfig();
                while (reader.pos < end) {
                    var tag = reader.uint32();
                    switch (tag >>> 3) {
                    case 1:
                        message.output = reader.int32();
                        break;
                    case 2:
                        message.enableColors = reader.bool();
                        break;
                    default:
                        reader.skipType(tag & 7);
                        break;
                    }
                }
                return message;
            };

            /**
             * Decodes a ConsoleConfig message from the specified reader or buffer, length delimited.
             * @function decodeDelimited
             * @memberof perfetto.protos.ConsoleConfig
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @returns {perfetto.protos.ConsoleConfig} ConsoleConfig
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            ConsoleConfig.decodeDelimited = function decodeDelimited(reader) {
                if (!(reader instanceof $Reader))
                    reader = new $Reader(reader);
                return this.decode(reader, reader.uint32());
            };

            /**
             * Verifies a ConsoleConfig message.
             * @function verify
             * @memberof perfetto.protos.ConsoleConfig
             * @static
             * @param {Object.<string,*>} message Plain object to verify
             * @returns {string|null} `null` if valid, otherwise the reason why it is not
             */
            ConsoleConfig.verify = function verify(message) {
                if (typeof message !== "object" || message === null)
                    return "object expected";
                if (message.output != null && message.hasOwnProperty("output"))
                    switch (message.output) {
                    default:
                        return "output: enum value expected";
                    case 0:
                    case 1:
                    case 2:
                        break;
                    }
                if (message.enableColors != null && message.hasOwnProperty("enableColors"))
                    if (typeof message.enableColors !== "boolean")
                        return "enableColors: boolean expected";
                return null;
            };

            /**
             * Creates a ConsoleConfig message from a plain object. Also converts values to their respective internal types.
             * @function fromObject
             * @memberof perfetto.protos.ConsoleConfig
             * @static
             * @param {Object.<string,*>} object Plain object
             * @returns {perfetto.protos.ConsoleConfig} ConsoleConfig
             */
            ConsoleConfig.fromObject = function fromObject(object) {
                if (object instanceof $root.perfetto.protos.ConsoleConfig)
                    return object;
                var message = new $root.perfetto.protos.ConsoleConfig();
                switch (object.output) {
                case "OUTPUT_UNSPECIFIED":
                case 0:
                    message.output = 0;
                    break;
                case "OUTPUT_STDOUT":
                case 1:
                    message.output = 1;
                    break;
                case "OUTPUT_STDERR":
                case 2:
                    message.output = 2;
                    break;
                }
                if (object.enableColors != null)
                    message.enableColors = Boolean(object.enableColors);
                return message;
            };

            /**
             * Creates a plain object from a ConsoleConfig message. Also converts values to other types if specified.
             * @function toObject
             * @memberof perfetto.protos.ConsoleConfig
             * @static
             * @param {perfetto.protos.ConsoleConfig} message ConsoleConfig
             * @param {$protobuf.IConversionOptions} [options] Conversion options
             * @returns {Object.<string,*>} Plain object
             */
            ConsoleConfig.toObject = function toObject(message, options) {
                if (!options)
                    options = {};
                var object = {};
                if (options.defaults) {
                    object.output = options.enums === String ? "OUTPUT_UNSPECIFIED" : 0;
                    object.enableColors = false;
                }
                if (message.output != null && message.hasOwnProperty("output"))
                    object.output = options.enums === String ? $root.perfetto.protos.ConsoleConfig.Output[message.output] : message.output;
                if (message.enableColors != null && message.hasOwnProperty("enableColors"))
                    object.enableColors = message.enableColors;
                return object;
            };

            /**
             * Converts this ConsoleConfig to JSON.
             * @function toJSON
             * @memberof perfetto.protos.ConsoleConfig
             * @instance
             * @returns {Object.<string,*>} JSON object
             */
            ConsoleConfig.prototype.toJSON = function toJSON() {
                return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
            };

            /**
             * Output enum.
             * @name perfetto.protos.ConsoleConfig.Output
             * @enum {number}
             * @property {number} OUTPUT_UNSPECIFIED=0 OUTPUT_UNSPECIFIED value
             * @property {number} OUTPUT_STDOUT=1 OUTPUT_STDOUT value
             * @property {number} OUTPUT_STDERR=2 OUTPUT_STDERR value
             */
            ConsoleConfig.Output = (function() {
                var valuesById = {}, values = Object.create(valuesById);
                values[valuesById[0] = "OUTPUT_UNSPECIFIED"] = 0;
                values[valuesById[1] = "OUTPUT_STDOUT"] = 1;
                values[valuesById[2] = "OUTPUT_STDERR"] = 2;
                return values;
            })();

            return ConsoleConfig;
        })();

        protos.InterceptorConfig = (function() {

            /**
             * Properties of an InterceptorConfig.
             * @memberof perfetto.protos
             * @interface IInterceptorConfig
             * @property {string|null} [name] InterceptorConfig name
             * @property {perfetto.protos.IConsoleConfig|null} [consoleConfig] InterceptorConfig consoleConfig
             */

            /**
             * Constructs a new InterceptorConfig.
             * @memberof perfetto.protos
             * @classdesc Represents an InterceptorConfig.
             * @implements IInterceptorConfig
             * @constructor
             * @param {perfetto.protos.IInterceptorConfig=} [properties] Properties to set
             */
            function InterceptorConfig(properties) {
                if (properties)
                    for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                        if (properties[keys[i]] != null)
                            this[keys[i]] = properties[keys[i]];
            }

            /**
             * InterceptorConfig name.
             * @member {string} name
             * @memberof perfetto.protos.InterceptorConfig
             * @instance
             */
            InterceptorConfig.prototype.name = "";

            /**
             * InterceptorConfig consoleConfig.
             * @member {perfetto.protos.IConsoleConfig|null|undefined} consoleConfig
             * @memberof perfetto.protos.InterceptorConfig
             * @instance
             */
            InterceptorConfig.prototype.consoleConfig = null;

            /**
             * Creates a new InterceptorConfig instance using the specified properties.
             * @function create
             * @memberof perfetto.protos.InterceptorConfig
             * @static
             * @param {perfetto.protos.IInterceptorConfig=} [properties] Properties to set
             * @returns {perfetto.protos.InterceptorConfig} InterceptorConfig instance
             */
            InterceptorConfig.create = function create(properties) {
                return new InterceptorConfig(properties);
            };

            /**
             * Encodes the specified InterceptorConfig message. Does not implicitly {@link perfetto.protos.InterceptorConfig.verify|verify} messages.
             * @function encode
             * @memberof perfetto.protos.InterceptorConfig
             * @static
             * @param {perfetto.protos.IInterceptorConfig} message InterceptorConfig message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            InterceptorConfig.encode = function encode(message, writer) {
                if (!writer)
                    writer = $Writer.create();
                if (message.name != null && Object.hasOwnProperty.call(message, "name"))
                    writer.uint32(/* id 1, wireType 2 =*/10).string(message.name);
                if (message.consoleConfig != null && Object.hasOwnProperty.call(message, "consoleConfig"))
                    $root.perfetto.protos.ConsoleConfig.encode(message.consoleConfig, writer.uint32(/* id 100, wireType 2 =*/802).fork()).ldelim();
                return writer;
            };

            /**
             * Encodes the specified InterceptorConfig message, length delimited. Does not implicitly {@link perfetto.protos.InterceptorConfig.verify|verify} messages.
             * @function encodeDelimited
             * @memberof perfetto.protos.InterceptorConfig
             * @static
             * @param {perfetto.protos.IInterceptorConfig} message InterceptorConfig message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            InterceptorConfig.encodeDelimited = function encodeDelimited(message, writer) {
                return this.encode(message, writer).ldelim();
            };

            /**
             * Decodes an InterceptorConfig message from the specified reader or buffer.
             * @function decode
             * @memberof perfetto.protos.InterceptorConfig
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @param {number} [length] Message length if known beforehand
             * @returns {perfetto.protos.InterceptorConfig} InterceptorConfig
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            InterceptorConfig.decode = function decode(reader, length) {
                if (!(reader instanceof $Reader))
                    reader = $Reader.create(reader);
                var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.InterceptorConfig();
                while (reader.pos < end) {
                    var tag = reader.uint32();
                    switch (tag >>> 3) {
                    case 1:
                        message.name = reader.string();
                        break;
                    case 100:
                        message.consoleConfig = $root.perfetto.protos.ConsoleConfig.decode(reader, reader.uint32());
                        break;
                    default:
                        reader.skipType(tag & 7);
                        break;
                    }
                }
                return message;
            };

            /**
             * Decodes an InterceptorConfig message from the specified reader or buffer, length delimited.
             * @function decodeDelimited
             * @memberof perfetto.protos.InterceptorConfig
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @returns {perfetto.protos.InterceptorConfig} InterceptorConfig
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            InterceptorConfig.decodeDelimited = function decodeDelimited(reader) {
                if (!(reader instanceof $Reader))
                    reader = new $Reader(reader);
                return this.decode(reader, reader.uint32());
            };

            /**
             * Verifies an InterceptorConfig message.
             * @function verify
             * @memberof perfetto.protos.InterceptorConfig
             * @static
             * @param {Object.<string,*>} message Plain object to verify
             * @returns {string|null} `null` if valid, otherwise the reason why it is not
             */
            InterceptorConfig.verify = function verify(message) {
                if (typeof message !== "object" || message === null)
                    return "object expected";
                if (message.name != null && message.hasOwnProperty("name"))
                    if (!$util.isString(message.name))
                        return "name: string expected";
                if (message.consoleConfig != null && message.hasOwnProperty("consoleConfig")) {
                    var error = $root.perfetto.protos.ConsoleConfig.verify(message.consoleConfig);
                    if (error)
                        return "consoleConfig." + error;
                }
                return null;
            };

            /**
             * Creates an InterceptorConfig message from a plain object. Also converts values to their respective internal types.
             * @function fromObject
             * @memberof perfetto.protos.InterceptorConfig
             * @static
             * @param {Object.<string,*>} object Plain object
             * @returns {perfetto.protos.InterceptorConfig} InterceptorConfig
             */
            InterceptorConfig.fromObject = function fromObject(object) {
                if (object instanceof $root.perfetto.protos.InterceptorConfig)
                    return object;
                var message = new $root.perfetto.protos.InterceptorConfig();
                if (object.name != null)
                    message.name = String(object.name);
                if (object.consoleConfig != null) {
                    if (typeof object.consoleConfig !== "object")
                        throw TypeError(".perfetto.protos.InterceptorConfig.consoleConfig: object expected");
                    message.consoleConfig = $root.perfetto.protos.ConsoleConfig.fromObject(object.consoleConfig);
                }
                return message;
            };

            /**
             * Creates a plain object from an InterceptorConfig message. Also converts values to other types if specified.
             * @function toObject
             * @memberof perfetto.protos.InterceptorConfig
             * @static
             * @param {perfetto.protos.InterceptorConfig} message InterceptorConfig
             * @param {$protobuf.IConversionOptions} [options] Conversion options
             * @returns {Object.<string,*>} Plain object
             */
            InterceptorConfig.toObject = function toObject(message, options) {
                if (!options)
                    options = {};
                var object = {};
                if (options.defaults) {
                    object.name = "";
                    object.consoleConfig = null;
                }
                if (message.name != null && message.hasOwnProperty("name"))
                    object.name = message.name;
                if (message.consoleConfig != null && message.hasOwnProperty("consoleConfig"))
                    object.consoleConfig = $root.perfetto.protos.ConsoleConfig.toObject(message.consoleConfig, options);
                return object;
            };

            /**
             * Converts this InterceptorConfig to JSON.
             * @function toJSON
             * @memberof perfetto.protos.InterceptorConfig
             * @instance
             * @returns {Object.<string,*>} JSON object
             */
            InterceptorConfig.prototype.toJSON = function toJSON() {
                return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
            };

            return InterceptorConfig;
        })();

        protos.AndroidPowerConfig = (function() {

            /**
             * Properties of an AndroidPowerConfig.
             * @memberof perfetto.protos
             * @interface IAndroidPowerConfig
             * @property {number|null} [batteryPollMs] AndroidPowerConfig batteryPollMs
             * @property {Array.<perfetto.protos.AndroidPowerConfig.BatteryCounters>|null} [batteryCounters] AndroidPowerConfig batteryCounters
             * @property {boolean|null} [collectPowerRails] AndroidPowerConfig collectPowerRails
             * @property {boolean|null} [collectEnergyEstimationBreakdown] AndroidPowerConfig collectEnergyEstimationBreakdown
             */

            /**
             * Constructs a new AndroidPowerConfig.
             * @memberof perfetto.protos
             * @classdesc Represents an AndroidPowerConfig.
             * @implements IAndroidPowerConfig
             * @constructor
             * @param {perfetto.protos.IAndroidPowerConfig=} [properties] Properties to set
             */
            function AndroidPowerConfig(properties) {
                this.batteryCounters = [];
                if (properties)
                    for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                        if (properties[keys[i]] != null)
                            this[keys[i]] = properties[keys[i]];
            }

            /**
             * AndroidPowerConfig batteryPollMs.
             * @member {number} batteryPollMs
             * @memberof perfetto.protos.AndroidPowerConfig
             * @instance
             */
            AndroidPowerConfig.prototype.batteryPollMs = 0;

            /**
             * AndroidPowerConfig batteryCounters.
             * @member {Array.<perfetto.protos.AndroidPowerConfig.BatteryCounters>} batteryCounters
             * @memberof perfetto.protos.AndroidPowerConfig
             * @instance
             */
            AndroidPowerConfig.prototype.batteryCounters = $util.emptyArray;

            /**
             * AndroidPowerConfig collectPowerRails.
             * @member {boolean} collectPowerRails
             * @memberof perfetto.protos.AndroidPowerConfig
             * @instance
             */
            AndroidPowerConfig.prototype.collectPowerRails = false;

            /**
             * AndroidPowerConfig collectEnergyEstimationBreakdown.
             * @member {boolean} collectEnergyEstimationBreakdown
             * @memberof perfetto.protos.AndroidPowerConfig
             * @instance
             */
            AndroidPowerConfig.prototype.collectEnergyEstimationBreakdown = false;

            /**
             * Creates a new AndroidPowerConfig instance using the specified properties.
             * @function create
             * @memberof perfetto.protos.AndroidPowerConfig
             * @static
             * @param {perfetto.protos.IAndroidPowerConfig=} [properties] Properties to set
             * @returns {perfetto.protos.AndroidPowerConfig} AndroidPowerConfig instance
             */
            AndroidPowerConfig.create = function create(properties) {
                return new AndroidPowerConfig(properties);
            };

            /**
             * Encodes the specified AndroidPowerConfig message. Does not implicitly {@link perfetto.protos.AndroidPowerConfig.verify|verify} messages.
             * @function encode
             * @memberof perfetto.protos.AndroidPowerConfig
             * @static
             * @param {perfetto.protos.IAndroidPowerConfig} message AndroidPowerConfig message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            AndroidPowerConfig.encode = function encode(message, writer) {
                if (!writer)
                    writer = $Writer.create();
                if (message.batteryPollMs != null && Object.hasOwnProperty.call(message, "batteryPollMs"))
                    writer.uint32(/* id 1, wireType 0 =*/8).uint32(message.batteryPollMs);
                if (message.batteryCounters != null && message.batteryCounters.length)
                    for (var i = 0; i < message.batteryCounters.length; ++i)
                        writer.uint32(/* id 2, wireType 0 =*/16).int32(message.batteryCounters[i]);
                if (message.collectPowerRails != null && Object.hasOwnProperty.call(message, "collectPowerRails"))
                    writer.uint32(/* id 3, wireType 0 =*/24).bool(message.collectPowerRails);
                if (message.collectEnergyEstimationBreakdown != null && Object.hasOwnProperty.call(message, "collectEnergyEstimationBreakdown"))
                    writer.uint32(/* id 4, wireType 0 =*/32).bool(message.collectEnergyEstimationBreakdown);
                return writer;
            };

            /**
             * Encodes the specified AndroidPowerConfig message, length delimited. Does not implicitly {@link perfetto.protos.AndroidPowerConfig.verify|verify} messages.
             * @function encodeDelimited
             * @memberof perfetto.protos.AndroidPowerConfig
             * @static
             * @param {perfetto.protos.IAndroidPowerConfig} message AndroidPowerConfig message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            AndroidPowerConfig.encodeDelimited = function encodeDelimited(message, writer) {
                return this.encode(message, writer).ldelim();
            };

            /**
             * Decodes an AndroidPowerConfig message from the specified reader or buffer.
             * @function decode
             * @memberof perfetto.protos.AndroidPowerConfig
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @param {number} [length] Message length if known beforehand
             * @returns {perfetto.protos.AndroidPowerConfig} AndroidPowerConfig
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            AndroidPowerConfig.decode = function decode(reader, length) {
                if (!(reader instanceof $Reader))
                    reader = $Reader.create(reader);
                var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.AndroidPowerConfig();
                while (reader.pos < end) {
                    var tag = reader.uint32();
                    switch (tag >>> 3) {
                    case 1:
                        message.batteryPollMs = reader.uint32();
                        break;
                    case 2:
                        if (!(message.batteryCounters && message.batteryCounters.length))
                            message.batteryCounters = [];
                        if ((tag & 7) === 2) {
                            var end2 = reader.uint32() + reader.pos;
                            while (reader.pos < end2)
                                message.batteryCounters.push(reader.int32());
                        } else
                            message.batteryCounters.push(reader.int32());
                        break;
                    case 3:
                        message.collectPowerRails = reader.bool();
                        break;
                    case 4:
                        message.collectEnergyEstimationBreakdown = reader.bool();
                        break;
                    default:
                        reader.skipType(tag & 7);
                        break;
                    }
                }
                return message;
            };

            /**
             * Decodes an AndroidPowerConfig message from the specified reader or buffer, length delimited.
             * @function decodeDelimited
             * @memberof perfetto.protos.AndroidPowerConfig
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @returns {perfetto.protos.AndroidPowerConfig} AndroidPowerConfig
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            AndroidPowerConfig.decodeDelimited = function decodeDelimited(reader) {
                if (!(reader instanceof $Reader))
                    reader = new $Reader(reader);
                return this.decode(reader, reader.uint32());
            };

            /**
             * Verifies an AndroidPowerConfig message.
             * @function verify
             * @memberof perfetto.protos.AndroidPowerConfig
             * @static
             * @param {Object.<string,*>} message Plain object to verify
             * @returns {string|null} `null` if valid, otherwise the reason why it is not
             */
            AndroidPowerConfig.verify = function verify(message) {
                if (typeof message !== "object" || message === null)
                    return "object expected";
                if (message.batteryPollMs != null && message.hasOwnProperty("batteryPollMs"))
                    if (!$util.isInteger(message.batteryPollMs))
                        return "batteryPollMs: integer expected";
                if (message.batteryCounters != null && message.hasOwnProperty("batteryCounters")) {
                    if (!Array.isArray(message.batteryCounters))
                        return "batteryCounters: array expected";
                    for (var i = 0; i < message.batteryCounters.length; ++i)
                        switch (message.batteryCounters[i]) {
                        default:
                            return "batteryCounters: enum value[] expected";
                        case 0:
                        case 1:
                        case 2:
                        case 3:
                        case 4:
                            break;
                        }
                }
                if (message.collectPowerRails != null && message.hasOwnProperty("collectPowerRails"))
                    if (typeof message.collectPowerRails !== "boolean")
                        return "collectPowerRails: boolean expected";
                if (message.collectEnergyEstimationBreakdown != null && message.hasOwnProperty("collectEnergyEstimationBreakdown"))
                    if (typeof message.collectEnergyEstimationBreakdown !== "boolean")
                        return "collectEnergyEstimationBreakdown: boolean expected";
                return null;
            };

            /**
             * Creates an AndroidPowerConfig message from a plain object. Also converts values to their respective internal types.
             * @function fromObject
             * @memberof perfetto.protos.AndroidPowerConfig
             * @static
             * @param {Object.<string,*>} object Plain object
             * @returns {perfetto.protos.AndroidPowerConfig} AndroidPowerConfig
             */
            AndroidPowerConfig.fromObject = function fromObject(object) {
                if (object instanceof $root.perfetto.protos.AndroidPowerConfig)
                    return object;
                var message = new $root.perfetto.protos.AndroidPowerConfig();
                if (object.batteryPollMs != null)
                    message.batteryPollMs = object.batteryPollMs >>> 0;
                if (object.batteryCounters) {
                    if (!Array.isArray(object.batteryCounters))
                        throw TypeError(".perfetto.protos.AndroidPowerConfig.batteryCounters: array expected");
                    message.batteryCounters = [];
                    for (var i = 0; i < object.batteryCounters.length; ++i)
                        switch (object.batteryCounters[i]) {
                        default:
                        case "BATTERY_COUNTER_UNSPECIFIED":
                        case 0:
                            message.batteryCounters[i] = 0;
                            break;
                        case "BATTERY_COUNTER_CHARGE":
                        case 1:
                            message.batteryCounters[i] = 1;
                            break;
                        case "BATTERY_COUNTER_CAPACITY_PERCENT":
                        case 2:
                            message.batteryCounters[i] = 2;
                            break;
                        case "BATTERY_COUNTER_CURRENT":
                        case 3:
                            message.batteryCounters[i] = 3;
                            break;
                        case "BATTERY_COUNTER_CURRENT_AVG":
                        case 4:
                            message.batteryCounters[i] = 4;
                            break;
                        }
                }
                if (object.collectPowerRails != null)
                    message.collectPowerRails = Boolean(object.collectPowerRails);
                if (object.collectEnergyEstimationBreakdown != null)
                    message.collectEnergyEstimationBreakdown = Boolean(object.collectEnergyEstimationBreakdown);
                return message;
            };

            /**
             * Creates a plain object from an AndroidPowerConfig message. Also converts values to other types if specified.
             * @function toObject
             * @memberof perfetto.protos.AndroidPowerConfig
             * @static
             * @param {perfetto.protos.AndroidPowerConfig} message AndroidPowerConfig
             * @param {$protobuf.IConversionOptions} [options] Conversion options
             * @returns {Object.<string,*>} Plain object
             */
            AndroidPowerConfig.toObject = function toObject(message, options) {
                if (!options)
                    options = {};
                var object = {};
                if (options.arrays || options.defaults)
                    object.batteryCounters = [];
                if (options.defaults) {
                    object.batteryPollMs = 0;
                    object.collectPowerRails = false;
                    object.collectEnergyEstimationBreakdown = false;
                }
                if (message.batteryPollMs != null && message.hasOwnProperty("batteryPollMs"))
                    object.batteryPollMs = message.batteryPollMs;
                if (message.batteryCounters && message.batteryCounters.length) {
                    object.batteryCounters = [];
                    for (var j = 0; j < message.batteryCounters.length; ++j)
                        object.batteryCounters[j] = options.enums === String ? $root.perfetto.protos.AndroidPowerConfig.BatteryCounters[message.batteryCounters[j]] : message.batteryCounters[j];
                }
                if (message.collectPowerRails != null && message.hasOwnProperty("collectPowerRails"))
                    object.collectPowerRails = message.collectPowerRails;
                if (message.collectEnergyEstimationBreakdown != null && message.hasOwnProperty("collectEnergyEstimationBreakdown"))
                    object.collectEnergyEstimationBreakdown = message.collectEnergyEstimationBreakdown;
                return object;
            };

            /**
             * Converts this AndroidPowerConfig to JSON.
             * @function toJSON
             * @memberof perfetto.protos.AndroidPowerConfig
             * @instance
             * @returns {Object.<string,*>} JSON object
             */
            AndroidPowerConfig.prototype.toJSON = function toJSON() {
                return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
            };

            /**
             * BatteryCounters enum.
             * @name perfetto.protos.AndroidPowerConfig.BatteryCounters
             * @enum {number}
             * @property {number} BATTERY_COUNTER_UNSPECIFIED=0 BATTERY_COUNTER_UNSPECIFIED value
             * @property {number} BATTERY_COUNTER_CHARGE=1 BATTERY_COUNTER_CHARGE value
             * @property {number} BATTERY_COUNTER_CAPACITY_PERCENT=2 BATTERY_COUNTER_CAPACITY_PERCENT value
             * @property {number} BATTERY_COUNTER_CURRENT=3 BATTERY_COUNTER_CURRENT value
             * @property {number} BATTERY_COUNTER_CURRENT_AVG=4 BATTERY_COUNTER_CURRENT_AVG value
             */
            AndroidPowerConfig.BatteryCounters = (function() {
                var valuesById = {}, values = Object.create(valuesById);
                values[valuesById[0] = "BATTERY_COUNTER_UNSPECIFIED"] = 0;
                values[valuesById[1] = "BATTERY_COUNTER_CHARGE"] = 1;
                values[valuesById[2] = "BATTERY_COUNTER_CAPACITY_PERCENT"] = 2;
                values[valuesById[3] = "BATTERY_COUNTER_CURRENT"] = 3;
                values[valuesById[4] = "BATTERY_COUNTER_CURRENT_AVG"] = 4;
                return values;
            })();

            return AndroidPowerConfig;
        })();

        protos.ProcessStatsConfig = (function() {

            /**
             * Properties of a ProcessStatsConfig.
             * @memberof perfetto.protos
             * @interface IProcessStatsConfig
             * @property {Array.<perfetto.protos.ProcessStatsConfig.Quirks>|null} [quirks] ProcessStatsConfig quirks
             * @property {boolean|null} [scanAllProcessesOnStart] ProcessStatsConfig scanAllProcessesOnStart
             * @property {boolean|null} [recordThreadNames] ProcessStatsConfig recordThreadNames
             * @property {number|null} [procStatsPollMs] ProcessStatsConfig procStatsPollMs
             * @property {number|null} [procStatsCacheTtlMs] ProcessStatsConfig procStatsCacheTtlMs
             * @property {boolean|null} [recordThreadTimeInState] ProcessStatsConfig recordThreadTimeInState
             * @property {number|null} [threadTimeInStateCacheSize] ProcessStatsConfig threadTimeInStateCacheSize
             */

            /**
             * Constructs a new ProcessStatsConfig.
             * @memberof perfetto.protos
             * @classdesc Represents a ProcessStatsConfig.
             * @implements IProcessStatsConfig
             * @constructor
             * @param {perfetto.protos.IProcessStatsConfig=} [properties] Properties to set
             */
            function ProcessStatsConfig(properties) {
                this.quirks = [];
                if (properties)
                    for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                        if (properties[keys[i]] != null)
                            this[keys[i]] = properties[keys[i]];
            }

            /**
             * ProcessStatsConfig quirks.
             * @member {Array.<perfetto.protos.ProcessStatsConfig.Quirks>} quirks
             * @memberof perfetto.protos.ProcessStatsConfig
             * @instance
             */
            ProcessStatsConfig.prototype.quirks = $util.emptyArray;

            /**
             * ProcessStatsConfig scanAllProcessesOnStart.
             * @member {boolean} scanAllProcessesOnStart
             * @memberof perfetto.protos.ProcessStatsConfig
             * @instance
             */
            ProcessStatsConfig.prototype.scanAllProcessesOnStart = false;

            /**
             * ProcessStatsConfig recordThreadNames.
             * @member {boolean} recordThreadNames
             * @memberof perfetto.protos.ProcessStatsConfig
             * @instance
             */
            ProcessStatsConfig.prototype.recordThreadNames = false;

            /**
             * ProcessStatsConfig procStatsPollMs.
             * @member {number} procStatsPollMs
             * @memberof perfetto.protos.ProcessStatsConfig
             * @instance
             */
            ProcessStatsConfig.prototype.procStatsPollMs = 0;

            /**
             * ProcessStatsConfig procStatsCacheTtlMs.
             * @member {number} procStatsCacheTtlMs
             * @memberof perfetto.protos.ProcessStatsConfig
             * @instance
             */
            ProcessStatsConfig.prototype.procStatsCacheTtlMs = 0;

            /**
             * ProcessStatsConfig recordThreadTimeInState.
             * @member {boolean} recordThreadTimeInState
             * @memberof perfetto.protos.ProcessStatsConfig
             * @instance
             */
            ProcessStatsConfig.prototype.recordThreadTimeInState = false;

            /**
             * ProcessStatsConfig threadTimeInStateCacheSize.
             * @member {number} threadTimeInStateCacheSize
             * @memberof perfetto.protos.ProcessStatsConfig
             * @instance
             */
            ProcessStatsConfig.prototype.threadTimeInStateCacheSize = 0;

            /**
             * Creates a new ProcessStatsConfig instance using the specified properties.
             * @function create
             * @memberof perfetto.protos.ProcessStatsConfig
             * @static
             * @param {perfetto.protos.IProcessStatsConfig=} [properties] Properties to set
             * @returns {perfetto.protos.ProcessStatsConfig} ProcessStatsConfig instance
             */
            ProcessStatsConfig.create = function create(properties) {
                return new ProcessStatsConfig(properties);
            };

            /**
             * Encodes the specified ProcessStatsConfig message. Does not implicitly {@link perfetto.protos.ProcessStatsConfig.verify|verify} messages.
             * @function encode
             * @memberof perfetto.protos.ProcessStatsConfig
             * @static
             * @param {perfetto.protos.IProcessStatsConfig} message ProcessStatsConfig message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            ProcessStatsConfig.encode = function encode(message, writer) {
                if (!writer)
                    writer = $Writer.create();
                if (message.quirks != null && message.quirks.length)
                    for (var i = 0; i < message.quirks.length; ++i)
                        writer.uint32(/* id 1, wireType 0 =*/8).int32(message.quirks[i]);
                if (message.scanAllProcessesOnStart != null && Object.hasOwnProperty.call(message, "scanAllProcessesOnStart"))
                    writer.uint32(/* id 2, wireType 0 =*/16).bool(message.scanAllProcessesOnStart);
                if (message.recordThreadNames != null && Object.hasOwnProperty.call(message, "recordThreadNames"))
                    writer.uint32(/* id 3, wireType 0 =*/24).bool(message.recordThreadNames);
                if (message.procStatsPollMs != null && Object.hasOwnProperty.call(message, "procStatsPollMs"))
                    writer.uint32(/* id 4, wireType 0 =*/32).uint32(message.procStatsPollMs);
                if (message.procStatsCacheTtlMs != null && Object.hasOwnProperty.call(message, "procStatsCacheTtlMs"))
                    writer.uint32(/* id 6, wireType 0 =*/48).uint32(message.procStatsCacheTtlMs);
                if (message.recordThreadTimeInState != null && Object.hasOwnProperty.call(message, "recordThreadTimeInState"))
                    writer.uint32(/* id 7, wireType 0 =*/56).bool(message.recordThreadTimeInState);
                if (message.threadTimeInStateCacheSize != null && Object.hasOwnProperty.call(message, "threadTimeInStateCacheSize"))
                    writer.uint32(/* id 8, wireType 0 =*/64).uint32(message.threadTimeInStateCacheSize);
                return writer;
            };

            /**
             * Encodes the specified ProcessStatsConfig message, length delimited. Does not implicitly {@link perfetto.protos.ProcessStatsConfig.verify|verify} messages.
             * @function encodeDelimited
             * @memberof perfetto.protos.ProcessStatsConfig
             * @static
             * @param {perfetto.protos.IProcessStatsConfig} message ProcessStatsConfig message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            ProcessStatsConfig.encodeDelimited = function encodeDelimited(message, writer) {
                return this.encode(message, writer).ldelim();
            };

            /**
             * Decodes a ProcessStatsConfig message from the specified reader or buffer.
             * @function decode
             * @memberof perfetto.protos.ProcessStatsConfig
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @param {number} [length] Message length if known beforehand
             * @returns {perfetto.protos.ProcessStatsConfig} ProcessStatsConfig
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            ProcessStatsConfig.decode = function decode(reader, length) {
                if (!(reader instanceof $Reader))
                    reader = $Reader.create(reader);
                var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.ProcessStatsConfig();
                while (reader.pos < end) {
                    var tag = reader.uint32();
                    switch (tag >>> 3) {
                    case 1:
                        if (!(message.quirks && message.quirks.length))
                            message.quirks = [];
                        if ((tag & 7) === 2) {
                            var end2 = reader.uint32() + reader.pos;
                            while (reader.pos < end2)
                                message.quirks.push(reader.int32());
                        } else
                            message.quirks.push(reader.int32());
                        break;
                    case 2:
                        message.scanAllProcessesOnStart = reader.bool();
                        break;
                    case 3:
                        message.recordThreadNames = reader.bool();
                        break;
                    case 4:
                        message.procStatsPollMs = reader.uint32();
                        break;
                    case 6:
                        message.procStatsCacheTtlMs = reader.uint32();
                        break;
                    case 7:
                        message.recordThreadTimeInState = reader.bool();
                        break;
                    case 8:
                        message.threadTimeInStateCacheSize = reader.uint32();
                        break;
                    default:
                        reader.skipType(tag & 7);
                        break;
                    }
                }
                return message;
            };

            /**
             * Decodes a ProcessStatsConfig message from the specified reader or buffer, length delimited.
             * @function decodeDelimited
             * @memberof perfetto.protos.ProcessStatsConfig
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @returns {perfetto.protos.ProcessStatsConfig} ProcessStatsConfig
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            ProcessStatsConfig.decodeDelimited = function decodeDelimited(reader) {
                if (!(reader instanceof $Reader))
                    reader = new $Reader(reader);
                return this.decode(reader, reader.uint32());
            };

            /**
             * Verifies a ProcessStatsConfig message.
             * @function verify
             * @memberof perfetto.protos.ProcessStatsConfig
             * @static
             * @param {Object.<string,*>} message Plain object to verify
             * @returns {string|null} `null` if valid, otherwise the reason why it is not
             */
            ProcessStatsConfig.verify = function verify(message) {
                if (typeof message !== "object" || message === null)
                    return "object expected";
                if (message.quirks != null && message.hasOwnProperty("quirks")) {
                    if (!Array.isArray(message.quirks))
                        return "quirks: array expected";
                    for (var i = 0; i < message.quirks.length; ++i)
                        switch (message.quirks[i]) {
                        default:
                            return "quirks: enum value[] expected";
                        case 0:
                        case 1:
                        case 2:
                            break;
                        }
                }
                if (message.scanAllProcessesOnStart != null && message.hasOwnProperty("scanAllProcessesOnStart"))
                    if (typeof message.scanAllProcessesOnStart !== "boolean")
                        return "scanAllProcessesOnStart: boolean expected";
                if (message.recordThreadNames != null && message.hasOwnProperty("recordThreadNames"))
                    if (typeof message.recordThreadNames !== "boolean")
                        return "recordThreadNames: boolean expected";
                if (message.procStatsPollMs != null && message.hasOwnProperty("procStatsPollMs"))
                    if (!$util.isInteger(message.procStatsPollMs))
                        return "procStatsPollMs: integer expected";
                if (message.procStatsCacheTtlMs != null && message.hasOwnProperty("procStatsCacheTtlMs"))
                    if (!$util.isInteger(message.procStatsCacheTtlMs))
                        return "procStatsCacheTtlMs: integer expected";
                if (message.recordThreadTimeInState != null && message.hasOwnProperty("recordThreadTimeInState"))
                    if (typeof message.recordThreadTimeInState !== "boolean")
                        return "recordThreadTimeInState: boolean expected";
                if (message.threadTimeInStateCacheSize != null && message.hasOwnProperty("threadTimeInStateCacheSize"))
                    if (!$util.isInteger(message.threadTimeInStateCacheSize))
                        return "threadTimeInStateCacheSize: integer expected";
                return null;
            };

            /**
             * Creates a ProcessStatsConfig message from a plain object. Also converts values to their respective internal types.
             * @function fromObject
             * @memberof perfetto.protos.ProcessStatsConfig
             * @static
             * @param {Object.<string,*>} object Plain object
             * @returns {perfetto.protos.ProcessStatsConfig} ProcessStatsConfig
             */
            ProcessStatsConfig.fromObject = function fromObject(object) {
                if (object instanceof $root.perfetto.protos.ProcessStatsConfig)
                    return object;
                var message = new $root.perfetto.protos.ProcessStatsConfig();
                if (object.quirks) {
                    if (!Array.isArray(object.quirks))
                        throw TypeError(".perfetto.protos.ProcessStatsConfig.quirks: array expected");
                    message.quirks = [];
                    for (var i = 0; i < object.quirks.length; ++i)
                        switch (object.quirks[i]) {
                        default:
                        case "QUIRKS_UNSPECIFIED":
                        case 0:
                            message.quirks[i] = 0;
                            break;
                        case "DISABLE_INITIAL_DUMP":
                        case 1:
                            message.quirks[i] = 1;
                            break;
                        case "DISABLE_ON_DEMAND":
                        case 2:
                            message.quirks[i] = 2;
                            break;
                        }
                }
                if (object.scanAllProcessesOnStart != null)
                    message.scanAllProcessesOnStart = Boolean(object.scanAllProcessesOnStart);
                if (object.recordThreadNames != null)
                    message.recordThreadNames = Boolean(object.recordThreadNames);
                if (object.procStatsPollMs != null)
                    message.procStatsPollMs = object.procStatsPollMs >>> 0;
                if (object.procStatsCacheTtlMs != null)
                    message.procStatsCacheTtlMs = object.procStatsCacheTtlMs >>> 0;
                if (object.recordThreadTimeInState != null)
                    message.recordThreadTimeInState = Boolean(object.recordThreadTimeInState);
                if (object.threadTimeInStateCacheSize != null)
                    message.threadTimeInStateCacheSize = object.threadTimeInStateCacheSize >>> 0;
                return message;
            };

            /**
             * Creates a plain object from a ProcessStatsConfig message. Also converts values to other types if specified.
             * @function toObject
             * @memberof perfetto.protos.ProcessStatsConfig
             * @static
             * @param {perfetto.protos.ProcessStatsConfig} message ProcessStatsConfig
             * @param {$protobuf.IConversionOptions} [options] Conversion options
             * @returns {Object.<string,*>} Plain object
             */
            ProcessStatsConfig.toObject = function toObject(message, options) {
                if (!options)
                    options = {};
                var object = {};
                if (options.arrays || options.defaults)
                    object.quirks = [];
                if (options.defaults) {
                    object.scanAllProcessesOnStart = false;
                    object.recordThreadNames = false;
                    object.procStatsPollMs = 0;
                    object.procStatsCacheTtlMs = 0;
                    object.recordThreadTimeInState = false;
                    object.threadTimeInStateCacheSize = 0;
                }
                if (message.quirks && message.quirks.length) {
                    object.quirks = [];
                    for (var j = 0; j < message.quirks.length; ++j)
                        object.quirks[j] = options.enums === String ? $root.perfetto.protos.ProcessStatsConfig.Quirks[message.quirks[j]] : message.quirks[j];
                }
                if (message.scanAllProcessesOnStart != null && message.hasOwnProperty("scanAllProcessesOnStart"))
                    object.scanAllProcessesOnStart = message.scanAllProcessesOnStart;
                if (message.recordThreadNames != null && message.hasOwnProperty("recordThreadNames"))
                    object.recordThreadNames = message.recordThreadNames;
                if (message.procStatsPollMs != null && message.hasOwnProperty("procStatsPollMs"))
                    object.procStatsPollMs = message.procStatsPollMs;
                if (message.procStatsCacheTtlMs != null && message.hasOwnProperty("procStatsCacheTtlMs"))
                    object.procStatsCacheTtlMs = message.procStatsCacheTtlMs;
                if (message.recordThreadTimeInState != null && message.hasOwnProperty("recordThreadTimeInState"))
                    object.recordThreadTimeInState = message.recordThreadTimeInState;
                if (message.threadTimeInStateCacheSize != null && message.hasOwnProperty("threadTimeInStateCacheSize"))
                    object.threadTimeInStateCacheSize = message.threadTimeInStateCacheSize;
                return object;
            };

            /**
             * Converts this ProcessStatsConfig to JSON.
             * @function toJSON
             * @memberof perfetto.protos.ProcessStatsConfig
             * @instance
             * @returns {Object.<string,*>} JSON object
             */
            ProcessStatsConfig.prototype.toJSON = function toJSON() {
                return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
            };

            /**
             * Quirks enum.
             * @name perfetto.protos.ProcessStatsConfig.Quirks
             * @enum {number}
             * @property {number} QUIRKS_UNSPECIFIED=0 QUIRKS_UNSPECIFIED value
             * @property {number} DISABLE_INITIAL_DUMP=1 DISABLE_INITIAL_DUMP value
             * @property {number} DISABLE_ON_DEMAND=2 DISABLE_ON_DEMAND value
             */
            ProcessStatsConfig.Quirks = (function() {
                var valuesById = {}, values = Object.create(valuesById);
                values[valuesById[0] = "QUIRKS_UNSPECIFIED"] = 0;
                values[valuesById[1] = "DISABLE_INITIAL_DUMP"] = 1;
                values[valuesById[2] = "DISABLE_ON_DEMAND"] = 2;
                return values;
            })();

            return ProcessStatsConfig;
        })();

        protos.HeapprofdConfig = (function() {

            /**
             * Properties of a HeapprofdConfig.
             * @memberof perfetto.protos
             * @interface IHeapprofdConfig
             * @property {number|null} [samplingIntervalBytes] HeapprofdConfig samplingIntervalBytes
             * @property {number|null} [adaptiveSamplingShmemThreshold] HeapprofdConfig adaptiveSamplingShmemThreshold
             * @property {number|null} [adaptiveSamplingMaxSamplingIntervalBytes] HeapprofdConfig adaptiveSamplingMaxSamplingIntervalBytes
             * @property {Array.<string>|null} [processCmdline] HeapprofdConfig processCmdline
             * @property {Array.<number>|null} [pid] HeapprofdConfig pid
             * @property {Array.<string>|null} [targetInstalledBy] HeapprofdConfig targetInstalledBy
             * @property {Array.<string>|null} [heaps] HeapprofdConfig heaps
             * @property {Array.<string>|null} [excludeHeaps] HeapprofdConfig excludeHeaps
             * @property {boolean|null} [streamAllocations] HeapprofdConfig streamAllocations
             * @property {Array.<number>|null} [heapSamplingIntervals] HeapprofdConfig heapSamplingIntervals
             * @property {boolean|null} [allHeaps] HeapprofdConfig allHeaps
             * @property {boolean|null} [all] HeapprofdConfig all
             * @property {number|null} [minAnonymousMemoryKb] HeapprofdConfig minAnonymousMemoryKb
             * @property {number|null} [maxHeapprofdMemoryKb] HeapprofdConfig maxHeapprofdMemoryKb
             * @property {number|null} [maxHeapprofdCpuSecs] HeapprofdConfig maxHeapprofdCpuSecs
             * @property {Array.<string>|null} [skipSymbolPrefix] HeapprofdConfig skipSymbolPrefix
             * @property {perfetto.protos.HeapprofdConfig.IContinuousDumpConfig|null} [continuousDumpConfig] HeapprofdConfig continuousDumpConfig
             * @property {number|null} [shmemSizeBytes] HeapprofdConfig shmemSizeBytes
             * @property {boolean|null} [blockClient] HeapprofdConfig blockClient
             * @property {number|null} [blockClientTimeoutUs] HeapprofdConfig blockClientTimeoutUs
             * @property {boolean|null} [noStartup] HeapprofdConfig noStartup
             * @property {boolean|null} [noRunning] HeapprofdConfig noRunning
             * @property {boolean|null} [dumpAtMax] HeapprofdConfig dumpAtMax
             * @property {boolean|null} [disableForkTeardown] HeapprofdConfig disableForkTeardown
             * @property {boolean|null} [disableVforkDetection] HeapprofdConfig disableVforkDetection
             */

            /**
             * Constructs a new HeapprofdConfig.
             * @memberof perfetto.protos
             * @classdesc Represents a HeapprofdConfig.
             * @implements IHeapprofdConfig
             * @constructor
             * @param {perfetto.protos.IHeapprofdConfig=} [properties] Properties to set
             */
            function HeapprofdConfig(properties) {
                this.processCmdline = [];
                this.pid = [];
                this.targetInstalledBy = [];
                this.heaps = [];
                this.excludeHeaps = [];
                this.heapSamplingIntervals = [];
                this.skipSymbolPrefix = [];
                if (properties)
                    for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                        if (properties[keys[i]] != null)
                            this[keys[i]] = properties[keys[i]];
            }

            /**
             * HeapprofdConfig samplingIntervalBytes.
             * @member {number} samplingIntervalBytes
             * @memberof perfetto.protos.HeapprofdConfig
             * @instance
             */
            HeapprofdConfig.prototype.samplingIntervalBytes = $util.Long ? $util.Long.fromBits(0,0,true) : 0;

            /**
             * HeapprofdConfig adaptiveSamplingShmemThreshold.
             * @member {number} adaptiveSamplingShmemThreshold
             * @memberof perfetto.protos.HeapprofdConfig
             * @instance
             */
            HeapprofdConfig.prototype.adaptiveSamplingShmemThreshold = $util.Long ? $util.Long.fromBits(0,0,true) : 0;

            /**
             * HeapprofdConfig adaptiveSamplingMaxSamplingIntervalBytes.
             * @member {number} adaptiveSamplingMaxSamplingIntervalBytes
             * @memberof perfetto.protos.HeapprofdConfig
             * @instance
             */
            HeapprofdConfig.prototype.adaptiveSamplingMaxSamplingIntervalBytes = $util.Long ? $util.Long.fromBits(0,0,true) : 0;

            /**
             * HeapprofdConfig processCmdline.
             * @member {Array.<string>} processCmdline
             * @memberof perfetto.protos.HeapprofdConfig
             * @instance
             */
            HeapprofdConfig.prototype.processCmdline = $util.emptyArray;

            /**
             * HeapprofdConfig pid.
             * @member {Array.<number>} pid
             * @memberof perfetto.protos.HeapprofdConfig
             * @instance
             */
            HeapprofdConfig.prototype.pid = $util.emptyArray;

            /**
             * HeapprofdConfig targetInstalledBy.
             * @member {Array.<string>} targetInstalledBy
             * @memberof perfetto.protos.HeapprofdConfig
             * @instance
             */
            HeapprofdConfig.prototype.targetInstalledBy = $util.emptyArray;

            /**
             * HeapprofdConfig heaps.
             * @member {Array.<string>} heaps
             * @memberof perfetto.protos.HeapprofdConfig
             * @instance
             */
            HeapprofdConfig.prototype.heaps = $util.emptyArray;

            /**
             * HeapprofdConfig excludeHeaps.
             * @member {Array.<string>} excludeHeaps
             * @memberof perfetto.protos.HeapprofdConfig
             * @instance
             */
            HeapprofdConfig.prototype.excludeHeaps = $util.emptyArray;

            /**
             * HeapprofdConfig streamAllocations.
             * @member {boolean} streamAllocations
             * @memberof perfetto.protos.HeapprofdConfig
             * @instance
             */
            HeapprofdConfig.prototype.streamAllocations = false;

            /**
             * HeapprofdConfig heapSamplingIntervals.
             * @member {Array.<number>} heapSamplingIntervals
             * @memberof perfetto.protos.HeapprofdConfig
             * @instance
             */
            HeapprofdConfig.prototype.heapSamplingIntervals = $util.emptyArray;

            /**
             * HeapprofdConfig allHeaps.
             * @member {boolean} allHeaps
             * @memberof perfetto.protos.HeapprofdConfig
             * @instance
             */
            HeapprofdConfig.prototype.allHeaps = false;

            /**
             * HeapprofdConfig all.
             * @member {boolean} all
             * @memberof perfetto.protos.HeapprofdConfig
             * @instance
             */
            HeapprofdConfig.prototype.all = false;

            /**
             * HeapprofdConfig minAnonymousMemoryKb.
             * @member {number} minAnonymousMemoryKb
             * @memberof perfetto.protos.HeapprofdConfig
             * @instance
             */
            HeapprofdConfig.prototype.minAnonymousMemoryKb = 0;

            /**
             * HeapprofdConfig maxHeapprofdMemoryKb.
             * @member {number} maxHeapprofdMemoryKb
             * @memberof perfetto.protos.HeapprofdConfig
             * @instance
             */
            HeapprofdConfig.prototype.maxHeapprofdMemoryKb = 0;

            /**
             * HeapprofdConfig maxHeapprofdCpuSecs.
             * @member {number} maxHeapprofdCpuSecs
             * @memberof perfetto.protos.HeapprofdConfig
             * @instance
             */
            HeapprofdConfig.prototype.maxHeapprofdCpuSecs = $util.Long ? $util.Long.fromBits(0,0,true) : 0;

            /**
             * HeapprofdConfig skipSymbolPrefix.
             * @member {Array.<string>} skipSymbolPrefix
             * @memberof perfetto.protos.HeapprofdConfig
             * @instance
             */
            HeapprofdConfig.prototype.skipSymbolPrefix = $util.emptyArray;

            /**
             * HeapprofdConfig continuousDumpConfig.
             * @member {perfetto.protos.HeapprofdConfig.IContinuousDumpConfig|null|undefined} continuousDumpConfig
             * @memberof perfetto.protos.HeapprofdConfig
             * @instance
             */
            HeapprofdConfig.prototype.continuousDumpConfig = null;

            /**
             * HeapprofdConfig shmemSizeBytes.
             * @member {number} shmemSizeBytes
             * @memberof perfetto.protos.HeapprofdConfig
             * @instance
             */
            HeapprofdConfig.prototype.shmemSizeBytes = $util.Long ? $util.Long.fromBits(0,0,true) : 0;

            /**
             * HeapprofdConfig blockClient.
             * @member {boolean} blockClient
             * @memberof perfetto.protos.HeapprofdConfig
             * @instance
             */
            HeapprofdConfig.prototype.blockClient = false;

            /**
             * HeapprofdConfig blockClientTimeoutUs.
             * @member {number} blockClientTimeoutUs
             * @memberof perfetto.protos.HeapprofdConfig
             * @instance
             */
            HeapprofdConfig.prototype.blockClientTimeoutUs = 0;

            /**
             * HeapprofdConfig noStartup.
             * @member {boolean} noStartup
             * @memberof perfetto.protos.HeapprofdConfig
             * @instance
             */
            HeapprofdConfig.prototype.noStartup = false;

            /**
             * HeapprofdConfig noRunning.
             * @member {boolean} noRunning
             * @memberof perfetto.protos.HeapprofdConfig
             * @instance
             */
            HeapprofdConfig.prototype.noRunning = false;

            /**
             * HeapprofdConfig dumpAtMax.
             * @member {boolean} dumpAtMax
             * @memberof perfetto.protos.HeapprofdConfig
             * @instance
             */
            HeapprofdConfig.prototype.dumpAtMax = false;

            /**
             * HeapprofdConfig disableForkTeardown.
             * @member {boolean} disableForkTeardown
             * @memberof perfetto.protos.HeapprofdConfig
             * @instance
             */
            HeapprofdConfig.prototype.disableForkTeardown = false;

            /**
             * HeapprofdConfig disableVforkDetection.
             * @member {boolean} disableVforkDetection
             * @memberof perfetto.protos.HeapprofdConfig
             * @instance
             */
            HeapprofdConfig.prototype.disableVforkDetection = false;

            /**
             * Creates a new HeapprofdConfig instance using the specified properties.
             * @function create
             * @memberof perfetto.protos.HeapprofdConfig
             * @static
             * @param {perfetto.protos.IHeapprofdConfig=} [properties] Properties to set
             * @returns {perfetto.protos.HeapprofdConfig} HeapprofdConfig instance
             */
            HeapprofdConfig.create = function create(properties) {
                return new HeapprofdConfig(properties);
            };

            /**
             * Encodes the specified HeapprofdConfig message. Does not implicitly {@link perfetto.protos.HeapprofdConfig.verify|verify} messages.
             * @function encode
             * @memberof perfetto.protos.HeapprofdConfig
             * @static
             * @param {perfetto.protos.IHeapprofdConfig} message HeapprofdConfig message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            HeapprofdConfig.encode = function encode(message, writer) {
                if (!writer)
                    writer = $Writer.create();
                if (message.samplingIntervalBytes != null && Object.hasOwnProperty.call(message, "samplingIntervalBytes"))
                    writer.uint32(/* id 1, wireType 0 =*/8).uint64(message.samplingIntervalBytes);
                if (message.processCmdline != null && message.processCmdline.length)
                    for (var i = 0; i < message.processCmdline.length; ++i)
                        writer.uint32(/* id 2, wireType 2 =*/18).string(message.processCmdline[i]);
                if (message.pid != null && message.pid.length)
                    for (var i = 0; i < message.pid.length; ++i)
                        writer.uint32(/* id 4, wireType 0 =*/32).uint64(message.pid[i]);
                if (message.all != null && Object.hasOwnProperty.call(message, "all"))
                    writer.uint32(/* id 5, wireType 0 =*/40).bool(message.all);
                if (message.continuousDumpConfig != null && Object.hasOwnProperty.call(message, "continuousDumpConfig"))
                    $root.perfetto.protos.HeapprofdConfig.ContinuousDumpConfig.encode(message.continuousDumpConfig, writer.uint32(/* id 6, wireType 2 =*/50).fork()).ldelim();
                if (message.skipSymbolPrefix != null && message.skipSymbolPrefix.length)
                    for (var i = 0; i < message.skipSymbolPrefix.length; ++i)
                        writer.uint32(/* id 7, wireType 2 =*/58).string(message.skipSymbolPrefix[i]);
                if (message.shmemSizeBytes != null && Object.hasOwnProperty.call(message, "shmemSizeBytes"))
                    writer.uint32(/* id 8, wireType 0 =*/64).uint64(message.shmemSizeBytes);
                if (message.blockClient != null && Object.hasOwnProperty.call(message, "blockClient"))
                    writer.uint32(/* id 9, wireType 0 =*/72).bool(message.blockClient);
                if (message.noStartup != null && Object.hasOwnProperty.call(message, "noStartup"))
                    writer.uint32(/* id 10, wireType 0 =*/80).bool(message.noStartup);
                if (message.noRunning != null && Object.hasOwnProperty.call(message, "noRunning"))
                    writer.uint32(/* id 11, wireType 0 =*/88).bool(message.noRunning);
                if (message.dumpAtMax != null && Object.hasOwnProperty.call(message, "dumpAtMax"))
                    writer.uint32(/* id 13, wireType 0 =*/104).bool(message.dumpAtMax);
                if (message.blockClientTimeoutUs != null && Object.hasOwnProperty.call(message, "blockClientTimeoutUs"))
                    writer.uint32(/* id 14, wireType 0 =*/112).uint32(message.blockClientTimeoutUs);
                if (message.minAnonymousMemoryKb != null && Object.hasOwnProperty.call(message, "minAnonymousMemoryKb"))
                    writer.uint32(/* id 15, wireType 0 =*/120).uint32(message.minAnonymousMemoryKb);
                if (message.maxHeapprofdMemoryKb != null && Object.hasOwnProperty.call(message, "maxHeapprofdMemoryKb"))
                    writer.uint32(/* id 16, wireType 0 =*/128).uint32(message.maxHeapprofdMemoryKb);
                if (message.maxHeapprofdCpuSecs != null && Object.hasOwnProperty.call(message, "maxHeapprofdCpuSecs"))
                    writer.uint32(/* id 17, wireType 0 =*/136).uint64(message.maxHeapprofdCpuSecs);
                if (message.disableForkTeardown != null && Object.hasOwnProperty.call(message, "disableForkTeardown"))
                    writer.uint32(/* id 18, wireType 0 =*/144).bool(message.disableForkTeardown);
                if (message.disableVforkDetection != null && Object.hasOwnProperty.call(message, "disableVforkDetection"))
                    writer.uint32(/* id 19, wireType 0 =*/152).bool(message.disableVforkDetection);
                if (message.heaps != null && message.heaps.length)
                    for (var i = 0; i < message.heaps.length; ++i)
                        writer.uint32(/* id 20, wireType 2 =*/162).string(message.heaps[i]);
                if (message.allHeaps != null && Object.hasOwnProperty.call(message, "allHeaps"))
                    writer.uint32(/* id 21, wireType 0 =*/168).bool(message.allHeaps);
                if (message.heapSamplingIntervals != null && message.heapSamplingIntervals.length)
                    for (var i = 0; i < message.heapSamplingIntervals.length; ++i)
                        writer.uint32(/* id 22, wireType 0 =*/176).uint64(message.heapSamplingIntervals[i]);
                if (message.streamAllocations != null && Object.hasOwnProperty.call(message, "streamAllocations"))
                    writer.uint32(/* id 23, wireType 0 =*/184).bool(message.streamAllocations);
                if (message.adaptiveSamplingShmemThreshold != null && Object.hasOwnProperty.call(message, "adaptiveSamplingShmemThreshold"))
                    writer.uint32(/* id 24, wireType 0 =*/192).uint64(message.adaptiveSamplingShmemThreshold);
                if (message.adaptiveSamplingMaxSamplingIntervalBytes != null && Object.hasOwnProperty.call(message, "adaptiveSamplingMaxSamplingIntervalBytes"))
                    writer.uint32(/* id 25, wireType 0 =*/200).uint64(message.adaptiveSamplingMaxSamplingIntervalBytes);
                if (message.targetInstalledBy != null && message.targetInstalledBy.length)
                    for (var i = 0; i < message.targetInstalledBy.length; ++i)
                        writer.uint32(/* id 26, wireType 2 =*/210).string(message.targetInstalledBy[i]);
                if (message.excludeHeaps != null && message.excludeHeaps.length)
                    for (var i = 0; i < message.excludeHeaps.length; ++i)
                        writer.uint32(/* id 27, wireType 2 =*/218).string(message.excludeHeaps[i]);
                return writer;
            };

            /**
             * Encodes the specified HeapprofdConfig message, length delimited. Does not implicitly {@link perfetto.protos.HeapprofdConfig.verify|verify} messages.
             * @function encodeDelimited
             * @memberof perfetto.protos.HeapprofdConfig
             * @static
             * @param {perfetto.protos.IHeapprofdConfig} message HeapprofdConfig message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            HeapprofdConfig.encodeDelimited = function encodeDelimited(message, writer) {
                return this.encode(message, writer).ldelim();
            };

            /**
             * Decodes a HeapprofdConfig message from the specified reader or buffer.
             * @function decode
             * @memberof perfetto.protos.HeapprofdConfig
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @param {number} [length] Message length if known beforehand
             * @returns {perfetto.protos.HeapprofdConfig} HeapprofdConfig
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            HeapprofdConfig.decode = function decode(reader, length) {
                if (!(reader instanceof $Reader))
                    reader = $Reader.create(reader);
                var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.HeapprofdConfig();
                while (reader.pos < end) {
                    var tag = reader.uint32();
                    switch (tag >>> 3) {
                    case 1:
                        message.samplingIntervalBytes = reader.uint64();
                        break;
                    case 24:
                        message.adaptiveSamplingShmemThreshold = reader.uint64();
                        break;
                    case 25:
                        message.adaptiveSamplingMaxSamplingIntervalBytes = reader.uint64();
                        break;
                    case 2:
                        if (!(message.processCmdline && message.processCmdline.length))
                            message.processCmdline = [];
                        message.processCmdline.push(reader.string());
                        break;
                    case 4:
                        if (!(message.pid && message.pid.length))
                            message.pid = [];
                        if ((tag & 7) === 2) {
                            var end2 = reader.uint32() + reader.pos;
                            while (reader.pos < end2)
                                message.pid.push(reader.uint64());
                        } else
                            message.pid.push(reader.uint64());
                        break;
                    case 26:
                        if (!(message.targetInstalledBy && message.targetInstalledBy.length))
                            message.targetInstalledBy = [];
                        message.targetInstalledBy.push(reader.string());
                        break;
                    case 20:
                        if (!(message.heaps && message.heaps.length))
                            message.heaps = [];
                        message.heaps.push(reader.string());
                        break;
                    case 27:
                        if (!(message.excludeHeaps && message.excludeHeaps.length))
                            message.excludeHeaps = [];
                        message.excludeHeaps.push(reader.string());
                        break;
                    case 23:
                        message.streamAllocations = reader.bool();
                        break;
                    case 22:
                        if (!(message.heapSamplingIntervals && message.heapSamplingIntervals.length))
                            message.heapSamplingIntervals = [];
                        if ((tag & 7) === 2) {
                            var end2 = reader.uint32() + reader.pos;
                            while (reader.pos < end2)
                                message.heapSamplingIntervals.push(reader.uint64());
                        } else
                            message.heapSamplingIntervals.push(reader.uint64());
                        break;
                    case 21:
                        message.allHeaps = reader.bool();
                        break;
                    case 5:
                        message.all = reader.bool();
                        break;
                    case 15:
                        message.minAnonymousMemoryKb = reader.uint32();
                        break;
                    case 16:
                        message.maxHeapprofdMemoryKb = reader.uint32();
                        break;
                    case 17:
                        message.maxHeapprofdCpuSecs = reader.uint64();
                        break;
                    case 7:
                        if (!(message.skipSymbolPrefix && message.skipSymbolPrefix.length))
                            message.skipSymbolPrefix = [];
                        message.skipSymbolPrefix.push(reader.string());
                        break;
                    case 6:
                        message.continuousDumpConfig = $root.perfetto.protos.HeapprofdConfig.ContinuousDumpConfig.decode(reader, reader.uint32());
                        break;
                    case 8:
                        message.shmemSizeBytes = reader.uint64();
                        break;
                    case 9:
                        message.blockClient = reader.bool();
                        break;
                    case 14:
                        message.blockClientTimeoutUs = reader.uint32();
                        break;
                    case 10:
                        message.noStartup = reader.bool();
                        break;
                    case 11:
                        message.noRunning = reader.bool();
                        break;
                    case 13:
                        message.dumpAtMax = reader.bool();
                        break;
                    case 18:
                        message.disableForkTeardown = reader.bool();
                        break;
                    case 19:
                        message.disableVforkDetection = reader.bool();
                        break;
                    default:
                        reader.skipType(tag & 7);
                        break;
                    }
                }
                return message;
            };

            /**
             * Decodes a HeapprofdConfig message from the specified reader or buffer, length delimited.
             * @function decodeDelimited
             * @memberof perfetto.protos.HeapprofdConfig
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @returns {perfetto.protos.HeapprofdConfig} HeapprofdConfig
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            HeapprofdConfig.decodeDelimited = function decodeDelimited(reader) {
                if (!(reader instanceof $Reader))
                    reader = new $Reader(reader);
                return this.decode(reader, reader.uint32());
            };

            /**
             * Verifies a HeapprofdConfig message.
             * @function verify
             * @memberof perfetto.protos.HeapprofdConfig
             * @static
             * @param {Object.<string,*>} message Plain object to verify
             * @returns {string|null} `null` if valid, otherwise the reason why it is not
             */
            HeapprofdConfig.verify = function verify(message) {
                if (typeof message !== "object" || message === null)
                    return "object expected";
                if (message.samplingIntervalBytes != null && message.hasOwnProperty("samplingIntervalBytes"))
                    if (!$util.isInteger(message.samplingIntervalBytes) && !(message.samplingIntervalBytes && $util.isInteger(message.samplingIntervalBytes.low) && $util.isInteger(message.samplingIntervalBytes.high)))
                        return "samplingIntervalBytes: integer|Long expected";
                if (message.adaptiveSamplingShmemThreshold != null && message.hasOwnProperty("adaptiveSamplingShmemThreshold"))
                    if (!$util.isInteger(message.adaptiveSamplingShmemThreshold) && !(message.adaptiveSamplingShmemThreshold && $util.isInteger(message.adaptiveSamplingShmemThreshold.low) && $util.isInteger(message.adaptiveSamplingShmemThreshold.high)))
                        return "adaptiveSamplingShmemThreshold: integer|Long expected";
                if (message.adaptiveSamplingMaxSamplingIntervalBytes != null && message.hasOwnProperty("adaptiveSamplingMaxSamplingIntervalBytes"))
                    if (!$util.isInteger(message.adaptiveSamplingMaxSamplingIntervalBytes) && !(message.adaptiveSamplingMaxSamplingIntervalBytes && $util.isInteger(message.adaptiveSamplingMaxSamplingIntervalBytes.low) && $util.isInteger(message.adaptiveSamplingMaxSamplingIntervalBytes.high)))
                        return "adaptiveSamplingMaxSamplingIntervalBytes: integer|Long expected";
                if (message.processCmdline != null && message.hasOwnProperty("processCmdline")) {
                    if (!Array.isArray(message.processCmdline))
                        return "processCmdline: array expected";
                    for (var i = 0; i < message.processCmdline.length; ++i)
                        if (!$util.isString(message.processCmdline[i]))
                            return "processCmdline: string[] expected";
                }
                if (message.pid != null && message.hasOwnProperty("pid")) {
                    if (!Array.isArray(message.pid))
                        return "pid: array expected";
                    for (var i = 0; i < message.pid.length; ++i)
                        if (!$util.isInteger(message.pid[i]) && !(message.pid[i] && $util.isInteger(message.pid[i].low) && $util.isInteger(message.pid[i].high)))
                            return "pid: integer|Long[] expected";
                }
                if (message.targetInstalledBy != null && message.hasOwnProperty("targetInstalledBy")) {
                    if (!Array.isArray(message.targetInstalledBy))
                        return "targetInstalledBy: array expected";
                    for (var i = 0; i < message.targetInstalledBy.length; ++i)
                        if (!$util.isString(message.targetInstalledBy[i]))
                            return "targetInstalledBy: string[] expected";
                }
                if (message.heaps != null && message.hasOwnProperty("heaps")) {
                    if (!Array.isArray(message.heaps))
                        return "heaps: array expected";
                    for (var i = 0; i < message.heaps.length; ++i)
                        if (!$util.isString(message.heaps[i]))
                            return "heaps: string[] expected";
                }
                if (message.excludeHeaps != null && message.hasOwnProperty("excludeHeaps")) {
                    if (!Array.isArray(message.excludeHeaps))
                        return "excludeHeaps: array expected";
                    for (var i = 0; i < message.excludeHeaps.length; ++i)
                        if (!$util.isString(message.excludeHeaps[i]))
                            return "excludeHeaps: string[] expected";
                }
                if (message.streamAllocations != null && message.hasOwnProperty("streamAllocations"))
                    if (typeof message.streamAllocations !== "boolean")
                        return "streamAllocations: boolean expected";
                if (message.heapSamplingIntervals != null && message.hasOwnProperty("heapSamplingIntervals")) {
                    if (!Array.isArray(message.heapSamplingIntervals))
                        return "heapSamplingIntervals: array expected";
                    for (var i = 0; i < message.heapSamplingIntervals.length; ++i)
                        if (!$util.isInteger(message.heapSamplingIntervals[i]) && !(message.heapSamplingIntervals[i] && $util.isInteger(message.heapSamplingIntervals[i].low) && $util.isInteger(message.heapSamplingIntervals[i].high)))
                            return "heapSamplingIntervals: integer|Long[] expected";
                }
                if (message.allHeaps != null && message.hasOwnProperty("allHeaps"))
                    if (typeof message.allHeaps !== "boolean")
                        return "allHeaps: boolean expected";
                if (message.all != null && message.hasOwnProperty("all"))
                    if (typeof message.all !== "boolean")
                        return "all: boolean expected";
                if (message.minAnonymousMemoryKb != null && message.hasOwnProperty("minAnonymousMemoryKb"))
                    if (!$util.isInteger(message.minAnonymousMemoryKb))
                        return "minAnonymousMemoryKb: integer expected";
                if (message.maxHeapprofdMemoryKb != null && message.hasOwnProperty("maxHeapprofdMemoryKb"))
                    if (!$util.isInteger(message.maxHeapprofdMemoryKb))
                        return "maxHeapprofdMemoryKb: integer expected";
                if (message.maxHeapprofdCpuSecs != null && message.hasOwnProperty("maxHeapprofdCpuSecs"))
                    if (!$util.isInteger(message.maxHeapprofdCpuSecs) && !(message.maxHeapprofdCpuSecs && $util.isInteger(message.maxHeapprofdCpuSecs.low) && $util.isInteger(message.maxHeapprofdCpuSecs.high)))
                        return "maxHeapprofdCpuSecs: integer|Long expected";
                if (message.skipSymbolPrefix != null && message.hasOwnProperty("skipSymbolPrefix")) {
                    if (!Array.isArray(message.skipSymbolPrefix))
                        return "skipSymbolPrefix: array expected";
                    for (var i = 0; i < message.skipSymbolPrefix.length; ++i)
                        if (!$util.isString(message.skipSymbolPrefix[i]))
                            return "skipSymbolPrefix: string[] expected";
                }
                if (message.continuousDumpConfig != null && message.hasOwnProperty("continuousDumpConfig")) {
                    var error = $root.perfetto.protos.HeapprofdConfig.ContinuousDumpConfig.verify(message.continuousDumpConfig);
                    if (error)
                        return "continuousDumpConfig." + error;
                }
                if (message.shmemSizeBytes != null && message.hasOwnProperty("shmemSizeBytes"))
                    if (!$util.isInteger(message.shmemSizeBytes) && !(message.shmemSizeBytes && $util.isInteger(message.shmemSizeBytes.low) && $util.isInteger(message.shmemSizeBytes.high)))
                        return "shmemSizeBytes: integer|Long expected";
                if (message.blockClient != null && message.hasOwnProperty("blockClient"))
                    if (typeof message.blockClient !== "boolean")
                        return "blockClient: boolean expected";
                if (message.blockClientTimeoutUs != null && message.hasOwnProperty("blockClientTimeoutUs"))
                    if (!$util.isInteger(message.blockClientTimeoutUs))
                        return "blockClientTimeoutUs: integer expected";
                if (message.noStartup != null && message.hasOwnProperty("noStartup"))
                    if (typeof message.noStartup !== "boolean")
                        return "noStartup: boolean expected";
                if (message.noRunning != null && message.hasOwnProperty("noRunning"))
                    if (typeof message.noRunning !== "boolean")
                        return "noRunning: boolean expected";
                if (message.dumpAtMax != null && message.hasOwnProperty("dumpAtMax"))
                    if (typeof message.dumpAtMax !== "boolean")
                        return "dumpAtMax: boolean expected";
                if (message.disableForkTeardown != null && message.hasOwnProperty("disableForkTeardown"))
                    if (typeof message.disableForkTeardown !== "boolean")
                        return "disableForkTeardown: boolean expected";
                if (message.disableVforkDetection != null && message.hasOwnProperty("disableVforkDetection"))
                    if (typeof message.disableVforkDetection !== "boolean")
                        return "disableVforkDetection: boolean expected";
                return null;
            };

            /**
             * Creates a HeapprofdConfig message from a plain object. Also converts values to their respective internal types.
             * @function fromObject
             * @memberof perfetto.protos.HeapprofdConfig
             * @static
             * @param {Object.<string,*>} object Plain object
             * @returns {perfetto.protos.HeapprofdConfig} HeapprofdConfig
             */
            HeapprofdConfig.fromObject = function fromObject(object) {
                if (object instanceof $root.perfetto.protos.HeapprofdConfig)
                    return object;
                var message = new $root.perfetto.protos.HeapprofdConfig();
                if (object.samplingIntervalBytes != null)
                    if ($util.Long)
                        (message.samplingIntervalBytes = $util.Long.fromValue(object.samplingIntervalBytes)).unsigned = true;
                    else if (typeof object.samplingIntervalBytes === "string")
                        message.samplingIntervalBytes = parseInt(object.samplingIntervalBytes, 10);
                    else if (typeof object.samplingIntervalBytes === "number")
                        message.samplingIntervalBytes = object.samplingIntervalBytes;
                    else if (typeof object.samplingIntervalBytes === "object")
                        message.samplingIntervalBytes = new $util.LongBits(object.samplingIntervalBytes.low >>> 0, object.samplingIntervalBytes.high >>> 0).toNumber(true);
                if (object.adaptiveSamplingShmemThreshold != null)
                    if ($util.Long)
                        (message.adaptiveSamplingShmemThreshold = $util.Long.fromValue(object.adaptiveSamplingShmemThreshold)).unsigned = true;
                    else if (typeof object.adaptiveSamplingShmemThreshold === "string")
                        message.adaptiveSamplingShmemThreshold = parseInt(object.adaptiveSamplingShmemThreshold, 10);
                    else if (typeof object.adaptiveSamplingShmemThreshold === "number")
                        message.adaptiveSamplingShmemThreshold = object.adaptiveSamplingShmemThreshold;
                    else if (typeof object.adaptiveSamplingShmemThreshold === "object")
                        message.adaptiveSamplingShmemThreshold = new $util.LongBits(object.adaptiveSamplingShmemThreshold.low >>> 0, object.adaptiveSamplingShmemThreshold.high >>> 0).toNumber(true);
                if (object.adaptiveSamplingMaxSamplingIntervalBytes != null)
                    if ($util.Long)
                        (message.adaptiveSamplingMaxSamplingIntervalBytes = $util.Long.fromValue(object.adaptiveSamplingMaxSamplingIntervalBytes)).unsigned = true;
                    else if (typeof object.adaptiveSamplingMaxSamplingIntervalBytes === "string")
                        message.adaptiveSamplingMaxSamplingIntervalBytes = parseInt(object.adaptiveSamplingMaxSamplingIntervalBytes, 10);
                    else if (typeof object.adaptiveSamplingMaxSamplingIntervalBytes === "number")
                        message.adaptiveSamplingMaxSamplingIntervalBytes = object.adaptiveSamplingMaxSamplingIntervalBytes;
                    else if (typeof object.adaptiveSamplingMaxSamplingIntervalBytes === "object")
                        message.adaptiveSamplingMaxSamplingIntervalBytes = new $util.LongBits(object.adaptiveSamplingMaxSamplingIntervalBytes.low >>> 0, object.adaptiveSamplingMaxSamplingIntervalBytes.high >>> 0).toNumber(true);
                if (object.processCmdline) {
                    if (!Array.isArray(object.processCmdline))
                        throw TypeError(".perfetto.protos.HeapprofdConfig.processCmdline: array expected");
                    message.processCmdline = [];
                    for (var i = 0; i < object.processCmdline.length; ++i)
                        message.processCmdline[i] = String(object.processCmdline[i]);
                }
                if (object.pid) {
                    if (!Array.isArray(object.pid))
                        throw TypeError(".perfetto.protos.HeapprofdConfig.pid: array expected");
                    message.pid = [];
                    for (var i = 0; i < object.pid.length; ++i)
                        if ($util.Long)
                            (message.pid[i] = $util.Long.fromValue(object.pid[i])).unsigned = true;
                        else if (typeof object.pid[i] === "string")
                            message.pid[i] = parseInt(object.pid[i], 10);
                        else if (typeof object.pid[i] === "number")
                            message.pid[i] = object.pid[i];
                        else if (typeof object.pid[i] === "object")
                            message.pid[i] = new $util.LongBits(object.pid[i].low >>> 0, object.pid[i].high >>> 0).toNumber(true);
                }
                if (object.targetInstalledBy) {
                    if (!Array.isArray(object.targetInstalledBy))
                        throw TypeError(".perfetto.protos.HeapprofdConfig.targetInstalledBy: array expected");
                    message.targetInstalledBy = [];
                    for (var i = 0; i < object.targetInstalledBy.length; ++i)
                        message.targetInstalledBy[i] = String(object.targetInstalledBy[i]);
                }
                if (object.heaps) {
                    if (!Array.isArray(object.heaps))
                        throw TypeError(".perfetto.protos.HeapprofdConfig.heaps: array expected");
                    message.heaps = [];
                    for (var i = 0; i < object.heaps.length; ++i)
                        message.heaps[i] = String(object.heaps[i]);
                }
                if (object.excludeHeaps) {
                    if (!Array.isArray(object.excludeHeaps))
                        throw TypeError(".perfetto.protos.HeapprofdConfig.excludeHeaps: array expected");
                    message.excludeHeaps = [];
                    for (var i = 0; i < object.excludeHeaps.length; ++i)
                        message.excludeHeaps[i] = String(object.excludeHeaps[i]);
                }
                if (object.streamAllocations != null)
                    message.streamAllocations = Boolean(object.streamAllocations);
                if (object.heapSamplingIntervals) {
                    if (!Array.isArray(object.heapSamplingIntervals))
                        throw TypeError(".perfetto.protos.HeapprofdConfig.heapSamplingIntervals: array expected");
                    message.heapSamplingIntervals = [];
                    for (var i = 0; i < object.heapSamplingIntervals.length; ++i)
                        if ($util.Long)
                            (message.heapSamplingIntervals[i] = $util.Long.fromValue(object.heapSamplingIntervals[i])).unsigned = true;
                        else if (typeof object.heapSamplingIntervals[i] === "string")
                            message.heapSamplingIntervals[i] = parseInt(object.heapSamplingIntervals[i], 10);
                        else if (typeof object.heapSamplingIntervals[i] === "number")
                            message.heapSamplingIntervals[i] = object.heapSamplingIntervals[i];
                        else if (typeof object.heapSamplingIntervals[i] === "object")
                            message.heapSamplingIntervals[i] = new $util.LongBits(object.heapSamplingIntervals[i].low >>> 0, object.heapSamplingIntervals[i].high >>> 0).toNumber(true);
                }
                if (object.allHeaps != null)
                    message.allHeaps = Boolean(object.allHeaps);
                if (object.all != null)
                    message.all = Boolean(object.all);
                if (object.minAnonymousMemoryKb != null)
                    message.minAnonymousMemoryKb = object.minAnonymousMemoryKb >>> 0;
                if (object.maxHeapprofdMemoryKb != null)
                    message.maxHeapprofdMemoryKb = object.maxHeapprofdMemoryKb >>> 0;
                if (object.maxHeapprofdCpuSecs != null)
                    if ($util.Long)
                        (message.maxHeapprofdCpuSecs = $util.Long.fromValue(object.maxHeapprofdCpuSecs)).unsigned = true;
                    else if (typeof object.maxHeapprofdCpuSecs === "string")
                        message.maxHeapprofdCpuSecs = parseInt(object.maxHeapprofdCpuSecs, 10);
                    else if (typeof object.maxHeapprofdCpuSecs === "number")
                        message.maxHeapprofdCpuSecs = object.maxHeapprofdCpuSecs;
                    else if (typeof object.maxHeapprofdCpuSecs === "object")
                        message.maxHeapprofdCpuSecs = new $util.LongBits(object.maxHeapprofdCpuSecs.low >>> 0, object.maxHeapprofdCpuSecs.high >>> 0).toNumber(true);
                if (object.skipSymbolPrefix) {
                    if (!Array.isArray(object.skipSymbolPrefix))
                        throw TypeError(".perfetto.protos.HeapprofdConfig.skipSymbolPrefix: array expected");
                    message.skipSymbolPrefix = [];
                    for (var i = 0; i < object.skipSymbolPrefix.length; ++i)
                        message.skipSymbolPrefix[i] = String(object.skipSymbolPrefix[i]);
                }
                if (object.continuousDumpConfig != null) {
                    if (typeof object.continuousDumpConfig !== "object")
                        throw TypeError(".perfetto.protos.HeapprofdConfig.continuousDumpConfig: object expected");
                    message.continuousDumpConfig = $root.perfetto.protos.HeapprofdConfig.ContinuousDumpConfig.fromObject(object.continuousDumpConfig);
                }
                if (object.shmemSizeBytes != null)
                    if ($util.Long)
                        (message.shmemSizeBytes = $util.Long.fromValue(object.shmemSizeBytes)).unsigned = true;
                    else if (typeof object.shmemSizeBytes === "string")
                        message.shmemSizeBytes = parseInt(object.shmemSizeBytes, 10);
                    else if (typeof object.shmemSizeBytes === "number")
                        message.shmemSizeBytes = object.shmemSizeBytes;
                    else if (typeof object.shmemSizeBytes === "object")
                        message.shmemSizeBytes = new $util.LongBits(object.shmemSizeBytes.low >>> 0, object.shmemSizeBytes.high >>> 0).toNumber(true);
                if (object.blockClient != null)
                    message.blockClient = Boolean(object.blockClient);
                if (object.blockClientTimeoutUs != null)
                    message.blockClientTimeoutUs = object.blockClientTimeoutUs >>> 0;
                if (object.noStartup != null)
                    message.noStartup = Boolean(object.noStartup);
                if (object.noRunning != null)
                    message.noRunning = Boolean(object.noRunning);
                if (object.dumpAtMax != null)
                    message.dumpAtMax = Boolean(object.dumpAtMax);
                if (object.disableForkTeardown != null)
                    message.disableForkTeardown = Boolean(object.disableForkTeardown);
                if (object.disableVforkDetection != null)
                    message.disableVforkDetection = Boolean(object.disableVforkDetection);
                return message;
            };

            /**
             * Creates a plain object from a HeapprofdConfig message. Also converts values to other types if specified.
             * @function toObject
             * @memberof perfetto.protos.HeapprofdConfig
             * @static
             * @param {perfetto.protos.HeapprofdConfig} message HeapprofdConfig
             * @param {$protobuf.IConversionOptions} [options] Conversion options
             * @returns {Object.<string,*>} Plain object
             */
            HeapprofdConfig.toObject = function toObject(message, options) {
                if (!options)
                    options = {};
                var object = {};
                if (options.arrays || options.defaults) {
                    object.processCmdline = [];
                    object.pid = [];
                    object.skipSymbolPrefix = [];
                    object.heaps = [];
                    object.heapSamplingIntervals = [];
                    object.targetInstalledBy = [];
                    object.excludeHeaps = [];
                }
                if (options.defaults) {
                    if ($util.Long) {
                        var long = new $util.Long(0, 0, true);
                        object.samplingIntervalBytes = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
                    } else
                        object.samplingIntervalBytes = options.longs === String ? "0" : 0;
                    object.all = false;
                    object.continuousDumpConfig = null;
                    if ($util.Long) {
                        var long = new $util.Long(0, 0, true);
                        object.shmemSizeBytes = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
                    } else
                        object.shmemSizeBytes = options.longs === String ? "0" : 0;
                    object.blockClient = false;
                    object.noStartup = false;
                    object.noRunning = false;
                    object.dumpAtMax = false;
                    object.blockClientTimeoutUs = 0;
                    object.minAnonymousMemoryKb = 0;
                    object.maxHeapprofdMemoryKb = 0;
                    if ($util.Long) {
                        var long = new $util.Long(0, 0, true);
                        object.maxHeapprofdCpuSecs = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
                    } else
                        object.maxHeapprofdCpuSecs = options.longs === String ? "0" : 0;
                    object.disableForkTeardown = false;
                    object.disableVforkDetection = false;
                    object.allHeaps = false;
                    object.streamAllocations = false;
                    if ($util.Long) {
                        var long = new $util.Long(0, 0, true);
                        object.adaptiveSamplingShmemThreshold = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
                    } else
                        object.adaptiveSamplingShmemThreshold = options.longs === String ? "0" : 0;
                    if ($util.Long) {
                        var long = new $util.Long(0, 0, true);
                        object.adaptiveSamplingMaxSamplingIntervalBytes = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
                    } else
                        object.adaptiveSamplingMaxSamplingIntervalBytes = options.longs === String ? "0" : 0;
                }
                if (message.samplingIntervalBytes != null && message.hasOwnProperty("samplingIntervalBytes"))
                    if (typeof message.samplingIntervalBytes === "number")
                        object.samplingIntervalBytes = options.longs === String ? String(message.samplingIntervalBytes) : message.samplingIntervalBytes;
                    else
                        object.samplingIntervalBytes = options.longs === String ? $util.Long.prototype.toString.call(message.samplingIntervalBytes) : options.longs === Number ? new $util.LongBits(message.samplingIntervalBytes.low >>> 0, message.samplingIntervalBytes.high >>> 0).toNumber(true) : message.samplingIntervalBytes;
                if (message.processCmdline && message.processCmdline.length) {
                    object.processCmdline = [];
                    for (var j = 0; j < message.processCmdline.length; ++j)
                        object.processCmdline[j] = message.processCmdline[j];
                }
                if (message.pid && message.pid.length) {
                    object.pid = [];
                    for (var j = 0; j < message.pid.length; ++j)
                        if (typeof message.pid[j] === "number")
                            object.pid[j] = options.longs === String ? String(message.pid[j]) : message.pid[j];
                        else
                            object.pid[j] = options.longs === String ? $util.Long.prototype.toString.call(message.pid[j]) : options.longs === Number ? new $util.LongBits(message.pid[j].low >>> 0, message.pid[j].high >>> 0).toNumber(true) : message.pid[j];
                }
                if (message.all != null && message.hasOwnProperty("all"))
                    object.all = message.all;
                if (message.continuousDumpConfig != null && message.hasOwnProperty("continuousDumpConfig"))
                    object.continuousDumpConfig = $root.perfetto.protos.HeapprofdConfig.ContinuousDumpConfig.toObject(message.continuousDumpConfig, options);
                if (message.skipSymbolPrefix && message.skipSymbolPrefix.length) {
                    object.skipSymbolPrefix = [];
                    for (var j = 0; j < message.skipSymbolPrefix.length; ++j)
                        object.skipSymbolPrefix[j] = message.skipSymbolPrefix[j];
                }
                if (message.shmemSizeBytes != null && message.hasOwnProperty("shmemSizeBytes"))
                    if (typeof message.shmemSizeBytes === "number")
                        object.shmemSizeBytes = options.longs === String ? String(message.shmemSizeBytes) : message.shmemSizeBytes;
                    else
                        object.shmemSizeBytes = options.longs === String ? $util.Long.prototype.toString.call(message.shmemSizeBytes) : options.longs === Number ? new $util.LongBits(message.shmemSizeBytes.low >>> 0, message.shmemSizeBytes.high >>> 0).toNumber(true) : message.shmemSizeBytes;
                if (message.blockClient != null && message.hasOwnProperty("blockClient"))
                    object.blockClient = message.blockClient;
                if (message.noStartup != null && message.hasOwnProperty("noStartup"))
                    object.noStartup = message.noStartup;
                if (message.noRunning != null && message.hasOwnProperty("noRunning"))
                    object.noRunning = message.noRunning;
                if (message.dumpAtMax != null && message.hasOwnProperty("dumpAtMax"))
                    object.dumpAtMax = message.dumpAtMax;
                if (message.blockClientTimeoutUs != null && message.hasOwnProperty("blockClientTimeoutUs"))
                    object.blockClientTimeoutUs = message.blockClientTimeoutUs;
                if (message.minAnonymousMemoryKb != null && message.hasOwnProperty("minAnonymousMemoryKb"))
                    object.minAnonymousMemoryKb = message.minAnonymousMemoryKb;
                if (message.maxHeapprofdMemoryKb != null && message.hasOwnProperty("maxHeapprofdMemoryKb"))
                    object.maxHeapprofdMemoryKb = message.maxHeapprofdMemoryKb;
                if (message.maxHeapprofdCpuSecs != null && message.hasOwnProperty("maxHeapprofdCpuSecs"))
                    if (typeof message.maxHeapprofdCpuSecs === "number")
                        object.maxHeapprofdCpuSecs = options.longs === String ? String(message.maxHeapprofdCpuSecs) : message.maxHeapprofdCpuSecs;
                    else
                        object.maxHeapprofdCpuSecs = options.longs === String ? $util.Long.prototype.toString.call(message.maxHeapprofdCpuSecs) : options.longs === Number ? new $util.LongBits(message.maxHeapprofdCpuSecs.low >>> 0, message.maxHeapprofdCpuSecs.high >>> 0).toNumber(true) : message.maxHeapprofdCpuSecs;
                if (message.disableForkTeardown != null && message.hasOwnProperty("disableForkTeardown"))
                    object.disableForkTeardown = message.disableForkTeardown;
                if (message.disableVforkDetection != null && message.hasOwnProperty("disableVforkDetection"))
                    object.disableVforkDetection = message.disableVforkDetection;
                if (message.heaps && message.heaps.length) {
                    object.heaps = [];
                    for (var j = 0; j < message.heaps.length; ++j)
                        object.heaps[j] = message.heaps[j];
                }
                if (message.allHeaps != null && message.hasOwnProperty("allHeaps"))
                    object.allHeaps = message.allHeaps;
                if (message.heapSamplingIntervals && message.heapSamplingIntervals.length) {
                    object.heapSamplingIntervals = [];
                    for (var j = 0; j < message.heapSamplingIntervals.length; ++j)
                        if (typeof message.heapSamplingIntervals[j] === "number")
                            object.heapSamplingIntervals[j] = options.longs === String ? String(message.heapSamplingIntervals[j]) : message.heapSamplingIntervals[j];
                        else
                            object.heapSamplingIntervals[j] = options.longs === String ? $util.Long.prototype.toString.call(message.heapSamplingIntervals[j]) : options.longs === Number ? new $util.LongBits(message.heapSamplingIntervals[j].low >>> 0, message.heapSamplingIntervals[j].high >>> 0).toNumber(true) : message.heapSamplingIntervals[j];
                }
                if (message.streamAllocations != null && message.hasOwnProperty("streamAllocations"))
                    object.streamAllocations = message.streamAllocations;
                if (message.adaptiveSamplingShmemThreshold != null && message.hasOwnProperty("adaptiveSamplingShmemThreshold"))
                    if (typeof message.adaptiveSamplingShmemThreshold === "number")
                        object.adaptiveSamplingShmemThreshold = options.longs === String ? String(message.adaptiveSamplingShmemThreshold) : message.adaptiveSamplingShmemThreshold;
                    else
                        object.adaptiveSamplingShmemThreshold = options.longs === String ? $util.Long.prototype.toString.call(message.adaptiveSamplingShmemThreshold) : options.longs === Number ? new $util.LongBits(message.adaptiveSamplingShmemThreshold.low >>> 0, message.adaptiveSamplingShmemThreshold.high >>> 0).toNumber(true) : message.adaptiveSamplingShmemThreshold;
                if (message.adaptiveSamplingMaxSamplingIntervalBytes != null && message.hasOwnProperty("adaptiveSamplingMaxSamplingIntervalBytes"))
                    if (typeof message.adaptiveSamplingMaxSamplingIntervalBytes === "number")
                        object.adaptiveSamplingMaxSamplingIntervalBytes = options.longs === String ? String(message.adaptiveSamplingMaxSamplingIntervalBytes) : message.adaptiveSamplingMaxSamplingIntervalBytes;
                    else
                        object.adaptiveSamplingMaxSamplingIntervalBytes = options.longs === String ? $util.Long.prototype.toString.call(message.adaptiveSamplingMaxSamplingIntervalBytes) : options.longs === Number ? new $util.LongBits(message.adaptiveSamplingMaxSamplingIntervalBytes.low >>> 0, message.adaptiveSamplingMaxSamplingIntervalBytes.high >>> 0).toNumber(true) : message.adaptiveSamplingMaxSamplingIntervalBytes;
                if (message.targetInstalledBy && message.targetInstalledBy.length) {
                    object.targetInstalledBy = [];
                    for (var j = 0; j < message.targetInstalledBy.length; ++j)
                        object.targetInstalledBy[j] = message.targetInstalledBy[j];
                }
                if (message.excludeHeaps && message.excludeHeaps.length) {
                    object.excludeHeaps = [];
                    for (var j = 0; j < message.excludeHeaps.length; ++j)
                        object.excludeHeaps[j] = message.excludeHeaps[j];
                }
                return object;
            };

            /**
             * Converts this HeapprofdConfig to JSON.
             * @function toJSON
             * @memberof perfetto.protos.HeapprofdConfig
             * @instance
             * @returns {Object.<string,*>} JSON object
             */
            HeapprofdConfig.prototype.toJSON = function toJSON() {
                return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
            };

            HeapprofdConfig.ContinuousDumpConfig = (function() {

                /**
                 * Properties of a ContinuousDumpConfig.
                 * @memberof perfetto.protos.HeapprofdConfig
                 * @interface IContinuousDumpConfig
                 * @property {number|null} [dumpPhaseMs] ContinuousDumpConfig dumpPhaseMs
                 * @property {number|null} [dumpIntervalMs] ContinuousDumpConfig dumpIntervalMs
                 */

                /**
                 * Constructs a new ContinuousDumpConfig.
                 * @memberof perfetto.protos.HeapprofdConfig
                 * @classdesc Represents a ContinuousDumpConfig.
                 * @implements IContinuousDumpConfig
                 * @constructor
                 * @param {perfetto.protos.HeapprofdConfig.IContinuousDumpConfig=} [properties] Properties to set
                 */
                function ContinuousDumpConfig(properties) {
                    if (properties)
                        for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                            if (properties[keys[i]] != null)
                                this[keys[i]] = properties[keys[i]];
                }

                /**
                 * ContinuousDumpConfig dumpPhaseMs.
                 * @member {number} dumpPhaseMs
                 * @memberof perfetto.protos.HeapprofdConfig.ContinuousDumpConfig
                 * @instance
                 */
                ContinuousDumpConfig.prototype.dumpPhaseMs = 0;

                /**
                 * ContinuousDumpConfig dumpIntervalMs.
                 * @member {number} dumpIntervalMs
                 * @memberof perfetto.protos.HeapprofdConfig.ContinuousDumpConfig
                 * @instance
                 */
                ContinuousDumpConfig.prototype.dumpIntervalMs = 0;

                /**
                 * Creates a new ContinuousDumpConfig instance using the specified properties.
                 * @function create
                 * @memberof perfetto.protos.HeapprofdConfig.ContinuousDumpConfig
                 * @static
                 * @param {perfetto.protos.HeapprofdConfig.IContinuousDumpConfig=} [properties] Properties to set
                 * @returns {perfetto.protos.HeapprofdConfig.ContinuousDumpConfig} ContinuousDumpConfig instance
                 */
                ContinuousDumpConfig.create = function create(properties) {
                    return new ContinuousDumpConfig(properties);
                };

                /**
                 * Encodes the specified ContinuousDumpConfig message. Does not implicitly {@link perfetto.protos.HeapprofdConfig.ContinuousDumpConfig.verify|verify} messages.
                 * @function encode
                 * @memberof perfetto.protos.HeapprofdConfig.ContinuousDumpConfig
                 * @static
                 * @param {perfetto.protos.HeapprofdConfig.IContinuousDumpConfig} message ContinuousDumpConfig message or plain object to encode
                 * @param {$protobuf.Writer} [writer] Writer to encode to
                 * @returns {$protobuf.Writer} Writer
                 */
                ContinuousDumpConfig.encode = function encode(message, writer) {
                    if (!writer)
                        writer = $Writer.create();
                    if (message.dumpPhaseMs != null && Object.hasOwnProperty.call(message, "dumpPhaseMs"))
                        writer.uint32(/* id 5, wireType 0 =*/40).uint32(message.dumpPhaseMs);
                    if (message.dumpIntervalMs != null && Object.hasOwnProperty.call(message, "dumpIntervalMs"))
                        writer.uint32(/* id 6, wireType 0 =*/48).uint32(message.dumpIntervalMs);
                    return writer;
                };

                /**
                 * Encodes the specified ContinuousDumpConfig message, length delimited. Does not implicitly {@link perfetto.protos.HeapprofdConfig.ContinuousDumpConfig.verify|verify} messages.
                 * @function encodeDelimited
                 * @memberof perfetto.protos.HeapprofdConfig.ContinuousDumpConfig
                 * @static
                 * @param {perfetto.protos.HeapprofdConfig.IContinuousDumpConfig} message ContinuousDumpConfig message or plain object to encode
                 * @param {$protobuf.Writer} [writer] Writer to encode to
                 * @returns {$protobuf.Writer} Writer
                 */
                ContinuousDumpConfig.encodeDelimited = function encodeDelimited(message, writer) {
                    return this.encode(message, writer).ldelim();
                };

                /**
                 * Decodes a ContinuousDumpConfig message from the specified reader or buffer.
                 * @function decode
                 * @memberof perfetto.protos.HeapprofdConfig.ContinuousDumpConfig
                 * @static
                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                 * @param {number} [length] Message length if known beforehand
                 * @returns {perfetto.protos.HeapprofdConfig.ContinuousDumpConfig} ContinuousDumpConfig
                 * @throws {Error} If the payload is not a reader or valid buffer
                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
                 */
                ContinuousDumpConfig.decode = function decode(reader, length) {
                    if (!(reader instanceof $Reader))
                        reader = $Reader.create(reader);
                    var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.HeapprofdConfig.ContinuousDumpConfig();
                    while (reader.pos < end) {
                        var tag = reader.uint32();
                        switch (tag >>> 3) {
                        case 5:
                            message.dumpPhaseMs = reader.uint32();
                            break;
                        case 6:
                            message.dumpIntervalMs = reader.uint32();
                            break;
                        default:
                            reader.skipType(tag & 7);
                            break;
                        }
                    }
                    return message;
                };

                /**
                 * Decodes a ContinuousDumpConfig message from the specified reader or buffer, length delimited.
                 * @function decodeDelimited
                 * @memberof perfetto.protos.HeapprofdConfig.ContinuousDumpConfig
                 * @static
                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                 * @returns {perfetto.protos.HeapprofdConfig.ContinuousDumpConfig} ContinuousDumpConfig
                 * @throws {Error} If the payload is not a reader or valid buffer
                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
                 */
                ContinuousDumpConfig.decodeDelimited = function decodeDelimited(reader) {
                    if (!(reader instanceof $Reader))
                        reader = new $Reader(reader);
                    return this.decode(reader, reader.uint32());
                };

                /**
                 * Verifies a ContinuousDumpConfig message.
                 * @function verify
                 * @memberof perfetto.protos.HeapprofdConfig.ContinuousDumpConfig
                 * @static
                 * @param {Object.<string,*>} message Plain object to verify
                 * @returns {string|null} `null` if valid, otherwise the reason why it is not
                 */
                ContinuousDumpConfig.verify = function verify(message) {
                    if (typeof message !== "object" || message === null)
                        return "object expected";
                    if (message.dumpPhaseMs != null && message.hasOwnProperty("dumpPhaseMs"))
                        if (!$util.isInteger(message.dumpPhaseMs))
                            return "dumpPhaseMs: integer expected";
                    if (message.dumpIntervalMs != null && message.hasOwnProperty("dumpIntervalMs"))
                        if (!$util.isInteger(message.dumpIntervalMs))
                            return "dumpIntervalMs: integer expected";
                    return null;
                };

                /**
                 * Creates a ContinuousDumpConfig message from a plain object. Also converts values to their respective internal types.
                 * @function fromObject
                 * @memberof perfetto.protos.HeapprofdConfig.ContinuousDumpConfig
                 * @static
                 * @param {Object.<string,*>} object Plain object
                 * @returns {perfetto.protos.HeapprofdConfig.ContinuousDumpConfig} ContinuousDumpConfig
                 */
                ContinuousDumpConfig.fromObject = function fromObject(object) {
                    if (object instanceof $root.perfetto.protos.HeapprofdConfig.ContinuousDumpConfig)
                        return object;
                    var message = new $root.perfetto.protos.HeapprofdConfig.ContinuousDumpConfig();
                    if (object.dumpPhaseMs != null)
                        message.dumpPhaseMs = object.dumpPhaseMs >>> 0;
                    if (object.dumpIntervalMs != null)
                        message.dumpIntervalMs = object.dumpIntervalMs >>> 0;
                    return message;
                };

                /**
                 * Creates a plain object from a ContinuousDumpConfig message. Also converts values to other types if specified.
                 * @function toObject
                 * @memberof perfetto.protos.HeapprofdConfig.ContinuousDumpConfig
                 * @static
                 * @param {perfetto.protos.HeapprofdConfig.ContinuousDumpConfig} message ContinuousDumpConfig
                 * @param {$protobuf.IConversionOptions} [options] Conversion options
                 * @returns {Object.<string,*>} Plain object
                 */
                ContinuousDumpConfig.toObject = function toObject(message, options) {
                    if (!options)
                        options = {};
                    var object = {};
                    if (options.defaults) {
                        object.dumpPhaseMs = 0;
                        object.dumpIntervalMs = 0;
                    }
                    if (message.dumpPhaseMs != null && message.hasOwnProperty("dumpPhaseMs"))
                        object.dumpPhaseMs = message.dumpPhaseMs;
                    if (message.dumpIntervalMs != null && message.hasOwnProperty("dumpIntervalMs"))
                        object.dumpIntervalMs = message.dumpIntervalMs;
                    return object;
                };

                /**
                 * Converts this ContinuousDumpConfig to JSON.
                 * @function toJSON
                 * @memberof perfetto.protos.HeapprofdConfig.ContinuousDumpConfig
                 * @instance
                 * @returns {Object.<string,*>} JSON object
                 */
                ContinuousDumpConfig.prototype.toJSON = function toJSON() {
                    return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
                };

                return ContinuousDumpConfig;
            })();

            return HeapprofdConfig;
        })();

        protos.JavaHprofConfig = (function() {

            /**
             * Properties of a JavaHprofConfig.
             * @memberof perfetto.protos
             * @interface IJavaHprofConfig
             * @property {Array.<string>|null} [processCmdline] JavaHprofConfig processCmdline
             * @property {Array.<number>|null} [pid] JavaHprofConfig pid
             * @property {Array.<string>|null} [targetInstalledBy] JavaHprofConfig targetInstalledBy
             * @property {perfetto.protos.JavaHprofConfig.IContinuousDumpConfig|null} [continuousDumpConfig] JavaHprofConfig continuousDumpConfig
             * @property {number|null} [minAnonymousMemoryKb] JavaHprofConfig minAnonymousMemoryKb
             * @property {boolean|null} [dumpSmaps] JavaHprofConfig dumpSmaps
             * @property {Array.<string>|null} [ignoredTypes] JavaHprofConfig ignoredTypes
             */

            /**
             * Constructs a new JavaHprofConfig.
             * @memberof perfetto.protos
             * @classdesc Represents a JavaHprofConfig.
             * @implements IJavaHprofConfig
             * @constructor
             * @param {perfetto.protos.IJavaHprofConfig=} [properties] Properties to set
             */
            function JavaHprofConfig(properties) {
                this.processCmdline = [];
                this.pid = [];
                this.targetInstalledBy = [];
                this.ignoredTypes = [];
                if (properties)
                    for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                        if (properties[keys[i]] != null)
                            this[keys[i]] = properties[keys[i]];
            }

            /**
             * JavaHprofConfig processCmdline.
             * @member {Array.<string>} processCmdline
             * @memberof perfetto.protos.JavaHprofConfig
             * @instance
             */
            JavaHprofConfig.prototype.processCmdline = $util.emptyArray;

            /**
             * JavaHprofConfig pid.
             * @member {Array.<number>} pid
             * @memberof perfetto.protos.JavaHprofConfig
             * @instance
             */
            JavaHprofConfig.prototype.pid = $util.emptyArray;

            /**
             * JavaHprofConfig targetInstalledBy.
             * @member {Array.<string>} targetInstalledBy
             * @memberof perfetto.protos.JavaHprofConfig
             * @instance
             */
            JavaHprofConfig.prototype.targetInstalledBy = $util.emptyArray;

            /**
             * JavaHprofConfig continuousDumpConfig.
             * @member {perfetto.protos.JavaHprofConfig.IContinuousDumpConfig|null|undefined} continuousDumpConfig
             * @memberof perfetto.protos.JavaHprofConfig
             * @instance
             */
            JavaHprofConfig.prototype.continuousDumpConfig = null;

            /**
             * JavaHprofConfig minAnonymousMemoryKb.
             * @member {number} minAnonymousMemoryKb
             * @memberof perfetto.protos.JavaHprofConfig
             * @instance
             */
            JavaHprofConfig.prototype.minAnonymousMemoryKb = 0;

            /**
             * JavaHprofConfig dumpSmaps.
             * @member {boolean} dumpSmaps
             * @memberof perfetto.protos.JavaHprofConfig
             * @instance
             */
            JavaHprofConfig.prototype.dumpSmaps = false;

            /**
             * JavaHprofConfig ignoredTypes.
             * @member {Array.<string>} ignoredTypes
             * @memberof perfetto.protos.JavaHprofConfig
             * @instance
             */
            JavaHprofConfig.prototype.ignoredTypes = $util.emptyArray;

            /**
             * Creates a new JavaHprofConfig instance using the specified properties.
             * @function create
             * @memberof perfetto.protos.JavaHprofConfig
             * @static
             * @param {perfetto.protos.IJavaHprofConfig=} [properties] Properties to set
             * @returns {perfetto.protos.JavaHprofConfig} JavaHprofConfig instance
             */
            JavaHprofConfig.create = function create(properties) {
                return new JavaHprofConfig(properties);
            };

            /**
             * Encodes the specified JavaHprofConfig message. Does not implicitly {@link perfetto.protos.JavaHprofConfig.verify|verify} messages.
             * @function encode
             * @memberof perfetto.protos.JavaHprofConfig
             * @static
             * @param {perfetto.protos.IJavaHprofConfig} message JavaHprofConfig message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            JavaHprofConfig.encode = function encode(message, writer) {
                if (!writer)
                    writer = $Writer.create();
                if (message.processCmdline != null && message.processCmdline.length)
                    for (var i = 0; i < message.processCmdline.length; ++i)
                        writer.uint32(/* id 1, wireType 2 =*/10).string(message.processCmdline[i]);
                if (message.pid != null && message.pid.length)
                    for (var i = 0; i < message.pid.length; ++i)
                        writer.uint32(/* id 2, wireType 0 =*/16).uint64(message.pid[i]);
                if (message.continuousDumpConfig != null && Object.hasOwnProperty.call(message, "continuousDumpConfig"))
                    $root.perfetto.protos.JavaHprofConfig.ContinuousDumpConfig.encode(message.continuousDumpConfig, writer.uint32(/* id 3, wireType 2 =*/26).fork()).ldelim();
                if (message.minAnonymousMemoryKb != null && Object.hasOwnProperty.call(message, "minAnonymousMemoryKb"))
                    writer.uint32(/* id 4, wireType 0 =*/32).uint32(message.minAnonymousMemoryKb);
                if (message.dumpSmaps != null && Object.hasOwnProperty.call(message, "dumpSmaps"))
                    writer.uint32(/* id 5, wireType 0 =*/40).bool(message.dumpSmaps);
                if (message.ignoredTypes != null && message.ignoredTypes.length)
                    for (var i = 0; i < message.ignoredTypes.length; ++i)
                        writer.uint32(/* id 6, wireType 2 =*/50).string(message.ignoredTypes[i]);
                if (message.targetInstalledBy != null && message.targetInstalledBy.length)
                    for (var i = 0; i < message.targetInstalledBy.length; ++i)
                        writer.uint32(/* id 7, wireType 2 =*/58).string(message.targetInstalledBy[i]);
                return writer;
            };

            /**
             * Encodes the specified JavaHprofConfig message, length delimited. Does not implicitly {@link perfetto.protos.JavaHprofConfig.verify|verify} messages.
             * @function encodeDelimited
             * @memberof perfetto.protos.JavaHprofConfig
             * @static
             * @param {perfetto.protos.IJavaHprofConfig} message JavaHprofConfig message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            JavaHprofConfig.encodeDelimited = function encodeDelimited(message, writer) {
                return this.encode(message, writer).ldelim();
            };

            /**
             * Decodes a JavaHprofConfig message from the specified reader or buffer.
             * @function decode
             * @memberof perfetto.protos.JavaHprofConfig
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @param {number} [length] Message length if known beforehand
             * @returns {perfetto.protos.JavaHprofConfig} JavaHprofConfig
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            JavaHprofConfig.decode = function decode(reader, length) {
                if (!(reader instanceof $Reader))
                    reader = $Reader.create(reader);
                var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.JavaHprofConfig();
                while (reader.pos < end) {
                    var tag = reader.uint32();
                    switch (tag >>> 3) {
                    case 1:
                        if (!(message.processCmdline && message.processCmdline.length))
                            message.processCmdline = [];
                        message.processCmdline.push(reader.string());
                        break;
                    case 2:
                        if (!(message.pid && message.pid.length))
                            message.pid = [];
                        if ((tag & 7) === 2) {
                            var end2 = reader.uint32() + reader.pos;
                            while (reader.pos < end2)
                                message.pid.push(reader.uint64());
                        } else
                            message.pid.push(reader.uint64());
                        break;
                    case 7:
                        if (!(message.targetInstalledBy && message.targetInstalledBy.length))
                            message.targetInstalledBy = [];
                        message.targetInstalledBy.push(reader.string());
                        break;
                    case 3:
                        message.continuousDumpConfig = $root.perfetto.protos.JavaHprofConfig.ContinuousDumpConfig.decode(reader, reader.uint32());
                        break;
                    case 4:
                        message.minAnonymousMemoryKb = reader.uint32();
                        break;
                    case 5:
                        message.dumpSmaps = reader.bool();
                        break;
                    case 6:
                        if (!(message.ignoredTypes && message.ignoredTypes.length))
                            message.ignoredTypes = [];
                        message.ignoredTypes.push(reader.string());
                        break;
                    default:
                        reader.skipType(tag & 7);
                        break;
                    }
                }
                return message;
            };

            /**
             * Decodes a JavaHprofConfig message from the specified reader or buffer, length delimited.
             * @function decodeDelimited
             * @memberof perfetto.protos.JavaHprofConfig
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @returns {perfetto.protos.JavaHprofConfig} JavaHprofConfig
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            JavaHprofConfig.decodeDelimited = function decodeDelimited(reader) {
                if (!(reader instanceof $Reader))
                    reader = new $Reader(reader);
                return this.decode(reader, reader.uint32());
            };

            /**
             * Verifies a JavaHprofConfig message.
             * @function verify
             * @memberof perfetto.protos.JavaHprofConfig
             * @static
             * @param {Object.<string,*>} message Plain object to verify
             * @returns {string|null} `null` if valid, otherwise the reason why it is not
             */
            JavaHprofConfig.verify = function verify(message) {
                if (typeof message !== "object" || message === null)
                    return "object expected";
                if (message.processCmdline != null && message.hasOwnProperty("processCmdline")) {
                    if (!Array.isArray(message.processCmdline))
                        return "processCmdline: array expected";
                    for (var i = 0; i < message.processCmdline.length; ++i)
                        if (!$util.isString(message.processCmdline[i]))
                            return "processCmdline: string[] expected";
                }
                if (message.pid != null && message.hasOwnProperty("pid")) {
                    if (!Array.isArray(message.pid))
                        return "pid: array expected";
                    for (var i = 0; i < message.pid.length; ++i)
                        if (!$util.isInteger(message.pid[i]) && !(message.pid[i] && $util.isInteger(message.pid[i].low) && $util.isInteger(message.pid[i].high)))
                            return "pid: integer|Long[] expected";
                }
                if (message.targetInstalledBy != null && message.hasOwnProperty("targetInstalledBy")) {
                    if (!Array.isArray(message.targetInstalledBy))
                        return "targetInstalledBy: array expected";
                    for (var i = 0; i < message.targetInstalledBy.length; ++i)
                        if (!$util.isString(message.targetInstalledBy[i]))
                            return "targetInstalledBy: string[] expected";
                }
                if (message.continuousDumpConfig != null && message.hasOwnProperty("continuousDumpConfig")) {
                    var error = $root.perfetto.protos.JavaHprofConfig.ContinuousDumpConfig.verify(message.continuousDumpConfig);
                    if (error)
                        return "continuousDumpConfig." + error;
                }
                if (message.minAnonymousMemoryKb != null && message.hasOwnProperty("minAnonymousMemoryKb"))
                    if (!$util.isInteger(message.minAnonymousMemoryKb))
                        return "minAnonymousMemoryKb: integer expected";
                if (message.dumpSmaps != null && message.hasOwnProperty("dumpSmaps"))
                    if (typeof message.dumpSmaps !== "boolean")
                        return "dumpSmaps: boolean expected";
                if (message.ignoredTypes != null && message.hasOwnProperty("ignoredTypes")) {
                    if (!Array.isArray(message.ignoredTypes))
                        return "ignoredTypes: array expected";
                    for (var i = 0; i < message.ignoredTypes.length; ++i)
                        if (!$util.isString(message.ignoredTypes[i]))
                            return "ignoredTypes: string[] expected";
                }
                return null;
            };

            /**
             * Creates a JavaHprofConfig message from a plain object. Also converts values to their respective internal types.
             * @function fromObject
             * @memberof perfetto.protos.JavaHprofConfig
             * @static
             * @param {Object.<string,*>} object Plain object
             * @returns {perfetto.protos.JavaHprofConfig} JavaHprofConfig
             */
            JavaHprofConfig.fromObject = function fromObject(object) {
                if (object instanceof $root.perfetto.protos.JavaHprofConfig)
                    return object;
                var message = new $root.perfetto.protos.JavaHprofConfig();
                if (object.processCmdline) {
                    if (!Array.isArray(object.processCmdline))
                        throw TypeError(".perfetto.protos.JavaHprofConfig.processCmdline: array expected");
                    message.processCmdline = [];
                    for (var i = 0; i < object.processCmdline.length; ++i)
                        message.processCmdline[i] = String(object.processCmdline[i]);
                }
                if (object.pid) {
                    if (!Array.isArray(object.pid))
                        throw TypeError(".perfetto.protos.JavaHprofConfig.pid: array expected");
                    message.pid = [];
                    for (var i = 0; i < object.pid.length; ++i)
                        if ($util.Long)
                            (message.pid[i] = $util.Long.fromValue(object.pid[i])).unsigned = true;
                        else if (typeof object.pid[i] === "string")
                            message.pid[i] = parseInt(object.pid[i], 10);
                        else if (typeof object.pid[i] === "number")
                            message.pid[i] = object.pid[i];
                        else if (typeof object.pid[i] === "object")
                            message.pid[i] = new $util.LongBits(object.pid[i].low >>> 0, object.pid[i].high >>> 0).toNumber(true);
                }
                if (object.targetInstalledBy) {
                    if (!Array.isArray(object.targetInstalledBy))
                        throw TypeError(".perfetto.protos.JavaHprofConfig.targetInstalledBy: array expected");
                    message.targetInstalledBy = [];
                    for (var i = 0; i < object.targetInstalledBy.length; ++i)
                        message.targetInstalledBy[i] = String(object.targetInstalledBy[i]);
                }
                if (object.continuousDumpConfig != null) {
                    if (typeof object.continuousDumpConfig !== "object")
                        throw TypeError(".perfetto.protos.JavaHprofConfig.continuousDumpConfig: object expected");
                    message.continuousDumpConfig = $root.perfetto.protos.JavaHprofConfig.ContinuousDumpConfig.fromObject(object.continuousDumpConfig);
                }
                if (object.minAnonymousMemoryKb != null)
                    message.minAnonymousMemoryKb = object.minAnonymousMemoryKb >>> 0;
                if (object.dumpSmaps != null)
                    message.dumpSmaps = Boolean(object.dumpSmaps);
                if (object.ignoredTypes) {
                    if (!Array.isArray(object.ignoredTypes))
                        throw TypeError(".perfetto.protos.JavaHprofConfig.ignoredTypes: array expected");
                    message.ignoredTypes = [];
                    for (var i = 0; i < object.ignoredTypes.length; ++i)
                        message.ignoredTypes[i] = String(object.ignoredTypes[i]);
                }
                return message;
            };

            /**
             * Creates a plain object from a JavaHprofConfig message. Also converts values to other types if specified.
             * @function toObject
             * @memberof perfetto.protos.JavaHprofConfig
             * @static
             * @param {perfetto.protos.JavaHprofConfig} message JavaHprofConfig
             * @param {$protobuf.IConversionOptions} [options] Conversion options
             * @returns {Object.<string,*>} Plain object
             */
            JavaHprofConfig.toObject = function toObject(message, options) {
                if (!options)
                    options = {};
                var object = {};
                if (options.arrays || options.defaults) {
                    object.processCmdline = [];
                    object.pid = [];
                    object.ignoredTypes = [];
                    object.targetInstalledBy = [];
                }
                if (options.defaults) {
                    object.continuousDumpConfig = null;
                    object.minAnonymousMemoryKb = 0;
                    object.dumpSmaps = false;
                }
                if (message.processCmdline && message.processCmdline.length) {
                    object.processCmdline = [];
                    for (var j = 0; j < message.processCmdline.length; ++j)
                        object.processCmdline[j] = message.processCmdline[j];
                }
                if (message.pid && message.pid.length) {
                    object.pid = [];
                    for (var j = 0; j < message.pid.length; ++j)
                        if (typeof message.pid[j] === "number")
                            object.pid[j] = options.longs === String ? String(message.pid[j]) : message.pid[j];
                        else
                            object.pid[j] = options.longs === String ? $util.Long.prototype.toString.call(message.pid[j]) : options.longs === Number ? new $util.LongBits(message.pid[j].low >>> 0, message.pid[j].high >>> 0).toNumber(true) : message.pid[j];
                }
                if (message.continuousDumpConfig != null && message.hasOwnProperty("continuousDumpConfig"))
                    object.continuousDumpConfig = $root.perfetto.protos.JavaHprofConfig.ContinuousDumpConfig.toObject(message.continuousDumpConfig, options);
                if (message.minAnonymousMemoryKb != null && message.hasOwnProperty("minAnonymousMemoryKb"))
                    object.minAnonymousMemoryKb = message.minAnonymousMemoryKb;
                if (message.dumpSmaps != null && message.hasOwnProperty("dumpSmaps"))
                    object.dumpSmaps = message.dumpSmaps;
                if (message.ignoredTypes && message.ignoredTypes.length) {
                    object.ignoredTypes = [];
                    for (var j = 0; j < message.ignoredTypes.length; ++j)
                        object.ignoredTypes[j] = message.ignoredTypes[j];
                }
                if (message.targetInstalledBy && message.targetInstalledBy.length) {
                    object.targetInstalledBy = [];
                    for (var j = 0; j < message.targetInstalledBy.length; ++j)
                        object.targetInstalledBy[j] = message.targetInstalledBy[j];
                }
                return object;
            };

            /**
             * Converts this JavaHprofConfig to JSON.
             * @function toJSON
             * @memberof perfetto.protos.JavaHprofConfig
             * @instance
             * @returns {Object.<string,*>} JSON object
             */
            JavaHprofConfig.prototype.toJSON = function toJSON() {
                return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
            };

            JavaHprofConfig.ContinuousDumpConfig = (function() {

                /**
                 * Properties of a ContinuousDumpConfig.
                 * @memberof perfetto.protos.JavaHprofConfig
                 * @interface IContinuousDumpConfig
                 * @property {number|null} [dumpPhaseMs] ContinuousDumpConfig dumpPhaseMs
                 * @property {number|null} [dumpIntervalMs] ContinuousDumpConfig dumpIntervalMs
                 */

                /**
                 * Constructs a new ContinuousDumpConfig.
                 * @memberof perfetto.protos.JavaHprofConfig
                 * @classdesc Represents a ContinuousDumpConfig.
                 * @implements IContinuousDumpConfig
                 * @constructor
                 * @param {perfetto.protos.JavaHprofConfig.IContinuousDumpConfig=} [properties] Properties to set
                 */
                function ContinuousDumpConfig(properties) {
                    if (properties)
                        for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                            if (properties[keys[i]] != null)
                                this[keys[i]] = properties[keys[i]];
                }

                /**
                 * ContinuousDumpConfig dumpPhaseMs.
                 * @member {number} dumpPhaseMs
                 * @memberof perfetto.protos.JavaHprofConfig.ContinuousDumpConfig
                 * @instance
                 */
                ContinuousDumpConfig.prototype.dumpPhaseMs = 0;

                /**
                 * ContinuousDumpConfig dumpIntervalMs.
                 * @member {number} dumpIntervalMs
                 * @memberof perfetto.protos.JavaHprofConfig.ContinuousDumpConfig
                 * @instance
                 */
                ContinuousDumpConfig.prototype.dumpIntervalMs = 0;

                /**
                 * Creates a new ContinuousDumpConfig instance using the specified properties.
                 * @function create
                 * @memberof perfetto.protos.JavaHprofConfig.ContinuousDumpConfig
                 * @static
                 * @param {perfetto.protos.JavaHprofConfig.IContinuousDumpConfig=} [properties] Properties to set
                 * @returns {perfetto.protos.JavaHprofConfig.ContinuousDumpConfig} ContinuousDumpConfig instance
                 */
                ContinuousDumpConfig.create = function create(properties) {
                    return new ContinuousDumpConfig(properties);
                };

                /**
                 * Encodes the specified ContinuousDumpConfig message. Does not implicitly {@link perfetto.protos.JavaHprofConfig.ContinuousDumpConfig.verify|verify} messages.
                 * @function encode
                 * @memberof perfetto.protos.JavaHprofConfig.ContinuousDumpConfig
                 * @static
                 * @param {perfetto.protos.JavaHprofConfig.IContinuousDumpConfig} message ContinuousDumpConfig message or plain object to encode
                 * @param {$protobuf.Writer} [writer] Writer to encode to
                 * @returns {$protobuf.Writer} Writer
                 */
                ContinuousDumpConfig.encode = function encode(message, writer) {
                    if (!writer)
                        writer = $Writer.create();
                    if (message.dumpPhaseMs != null && Object.hasOwnProperty.call(message, "dumpPhaseMs"))
                        writer.uint32(/* id 1, wireType 0 =*/8).uint32(message.dumpPhaseMs);
                    if (message.dumpIntervalMs != null && Object.hasOwnProperty.call(message, "dumpIntervalMs"))
                        writer.uint32(/* id 2, wireType 0 =*/16).uint32(message.dumpIntervalMs);
                    return writer;
                };

                /**
                 * Encodes the specified ContinuousDumpConfig message, length delimited. Does not implicitly {@link perfetto.protos.JavaHprofConfig.ContinuousDumpConfig.verify|verify} messages.
                 * @function encodeDelimited
                 * @memberof perfetto.protos.JavaHprofConfig.ContinuousDumpConfig
                 * @static
                 * @param {perfetto.protos.JavaHprofConfig.IContinuousDumpConfig} message ContinuousDumpConfig message or plain object to encode
                 * @param {$protobuf.Writer} [writer] Writer to encode to
                 * @returns {$protobuf.Writer} Writer
                 */
                ContinuousDumpConfig.encodeDelimited = function encodeDelimited(message, writer) {
                    return this.encode(message, writer).ldelim();
                };

                /**
                 * Decodes a ContinuousDumpConfig message from the specified reader or buffer.
                 * @function decode
                 * @memberof perfetto.protos.JavaHprofConfig.ContinuousDumpConfig
                 * @static
                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                 * @param {number} [length] Message length if known beforehand
                 * @returns {perfetto.protos.JavaHprofConfig.ContinuousDumpConfig} ContinuousDumpConfig
                 * @throws {Error} If the payload is not a reader or valid buffer
                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
                 */
                ContinuousDumpConfig.decode = function decode(reader, length) {
                    if (!(reader instanceof $Reader))
                        reader = $Reader.create(reader);
                    var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.JavaHprofConfig.ContinuousDumpConfig();
                    while (reader.pos < end) {
                        var tag = reader.uint32();
                        switch (tag >>> 3) {
                        case 1:
                            message.dumpPhaseMs = reader.uint32();
                            break;
                        case 2:
                            message.dumpIntervalMs = reader.uint32();
                            break;
                        default:
                            reader.skipType(tag & 7);
                            break;
                        }
                    }
                    return message;
                };

                /**
                 * Decodes a ContinuousDumpConfig message from the specified reader or buffer, length delimited.
                 * @function decodeDelimited
                 * @memberof perfetto.protos.JavaHprofConfig.ContinuousDumpConfig
                 * @static
                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                 * @returns {perfetto.protos.JavaHprofConfig.ContinuousDumpConfig} ContinuousDumpConfig
                 * @throws {Error} If the payload is not a reader or valid buffer
                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
                 */
                ContinuousDumpConfig.decodeDelimited = function decodeDelimited(reader) {
                    if (!(reader instanceof $Reader))
                        reader = new $Reader(reader);
                    return this.decode(reader, reader.uint32());
                };

                /**
                 * Verifies a ContinuousDumpConfig message.
                 * @function verify
                 * @memberof perfetto.protos.JavaHprofConfig.ContinuousDumpConfig
                 * @static
                 * @param {Object.<string,*>} message Plain object to verify
                 * @returns {string|null} `null` if valid, otherwise the reason why it is not
                 */
                ContinuousDumpConfig.verify = function verify(message) {
                    if (typeof message !== "object" || message === null)
                        return "object expected";
                    if (message.dumpPhaseMs != null && message.hasOwnProperty("dumpPhaseMs"))
                        if (!$util.isInteger(message.dumpPhaseMs))
                            return "dumpPhaseMs: integer expected";
                    if (message.dumpIntervalMs != null && message.hasOwnProperty("dumpIntervalMs"))
                        if (!$util.isInteger(message.dumpIntervalMs))
                            return "dumpIntervalMs: integer expected";
                    return null;
                };

                /**
                 * Creates a ContinuousDumpConfig message from a plain object. Also converts values to their respective internal types.
                 * @function fromObject
                 * @memberof perfetto.protos.JavaHprofConfig.ContinuousDumpConfig
                 * @static
                 * @param {Object.<string,*>} object Plain object
                 * @returns {perfetto.protos.JavaHprofConfig.ContinuousDumpConfig} ContinuousDumpConfig
                 */
                ContinuousDumpConfig.fromObject = function fromObject(object) {
                    if (object instanceof $root.perfetto.protos.JavaHprofConfig.ContinuousDumpConfig)
                        return object;
                    var message = new $root.perfetto.protos.JavaHprofConfig.ContinuousDumpConfig();
                    if (object.dumpPhaseMs != null)
                        message.dumpPhaseMs = object.dumpPhaseMs >>> 0;
                    if (object.dumpIntervalMs != null)
                        message.dumpIntervalMs = object.dumpIntervalMs >>> 0;
                    return message;
                };

                /**
                 * Creates a plain object from a ContinuousDumpConfig message. Also converts values to other types if specified.
                 * @function toObject
                 * @memberof perfetto.protos.JavaHprofConfig.ContinuousDumpConfig
                 * @static
                 * @param {perfetto.protos.JavaHprofConfig.ContinuousDumpConfig} message ContinuousDumpConfig
                 * @param {$protobuf.IConversionOptions} [options] Conversion options
                 * @returns {Object.<string,*>} Plain object
                 */
                ContinuousDumpConfig.toObject = function toObject(message, options) {
                    if (!options)
                        options = {};
                    var object = {};
                    if (options.defaults) {
                        object.dumpPhaseMs = 0;
                        object.dumpIntervalMs = 0;
                    }
                    if (message.dumpPhaseMs != null && message.hasOwnProperty("dumpPhaseMs"))
                        object.dumpPhaseMs = message.dumpPhaseMs;
                    if (message.dumpIntervalMs != null && message.hasOwnProperty("dumpIntervalMs"))
                        object.dumpIntervalMs = message.dumpIntervalMs;
                    return object;
                };

                /**
                 * Converts this ContinuousDumpConfig to JSON.
                 * @function toJSON
                 * @memberof perfetto.protos.JavaHprofConfig.ContinuousDumpConfig
                 * @instance
                 * @returns {Object.<string,*>} JSON object
                 */
                ContinuousDumpConfig.prototype.toJSON = function toJSON() {
                    return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
                };

                return ContinuousDumpConfig;
            })();

            return JavaHprofConfig;
        })();

        protos.PerfEvents = (function() {

            /**
             * Properties of a PerfEvents.
             * @memberof perfetto.protos
             * @interface IPerfEvents
             */

            /**
             * Constructs a new PerfEvents.
             * @memberof perfetto.protos
             * @classdesc Represents a PerfEvents.
             * @implements IPerfEvents
             * @constructor
             * @param {perfetto.protos.IPerfEvents=} [properties] Properties to set
             */
            function PerfEvents(properties) {
                if (properties)
                    for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                        if (properties[keys[i]] != null)
                            this[keys[i]] = properties[keys[i]];
            }

            /**
             * Creates a new PerfEvents instance using the specified properties.
             * @function create
             * @memberof perfetto.protos.PerfEvents
             * @static
             * @param {perfetto.protos.IPerfEvents=} [properties] Properties to set
             * @returns {perfetto.protos.PerfEvents} PerfEvents instance
             */
            PerfEvents.create = function create(properties) {
                return new PerfEvents(properties);
            };

            /**
             * Encodes the specified PerfEvents message. Does not implicitly {@link perfetto.protos.PerfEvents.verify|verify} messages.
             * @function encode
             * @memberof perfetto.protos.PerfEvents
             * @static
             * @param {perfetto.protos.IPerfEvents} message PerfEvents message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            PerfEvents.encode = function encode(message, writer) {
                if (!writer)
                    writer = $Writer.create();
                return writer;
            };

            /**
             * Encodes the specified PerfEvents message, length delimited. Does not implicitly {@link perfetto.protos.PerfEvents.verify|verify} messages.
             * @function encodeDelimited
             * @memberof perfetto.protos.PerfEvents
             * @static
             * @param {perfetto.protos.IPerfEvents} message PerfEvents message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            PerfEvents.encodeDelimited = function encodeDelimited(message, writer) {
                return this.encode(message, writer).ldelim();
            };

            /**
             * Decodes a PerfEvents message from the specified reader or buffer.
             * @function decode
             * @memberof perfetto.protos.PerfEvents
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @param {number} [length] Message length if known beforehand
             * @returns {perfetto.protos.PerfEvents} PerfEvents
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            PerfEvents.decode = function decode(reader, length) {
                if (!(reader instanceof $Reader))
                    reader = $Reader.create(reader);
                var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.PerfEvents();
                while (reader.pos < end) {
                    var tag = reader.uint32();
                    switch (tag >>> 3) {
                    default:
                        reader.skipType(tag & 7);
                        break;
                    }
                }
                return message;
            };

            /**
             * Decodes a PerfEvents message from the specified reader or buffer, length delimited.
             * @function decodeDelimited
             * @memberof perfetto.protos.PerfEvents
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @returns {perfetto.protos.PerfEvents} PerfEvents
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            PerfEvents.decodeDelimited = function decodeDelimited(reader) {
                if (!(reader instanceof $Reader))
                    reader = new $Reader(reader);
                return this.decode(reader, reader.uint32());
            };

            /**
             * Verifies a PerfEvents message.
             * @function verify
             * @memberof perfetto.protos.PerfEvents
             * @static
             * @param {Object.<string,*>} message Plain object to verify
             * @returns {string|null} `null` if valid, otherwise the reason why it is not
             */
            PerfEvents.verify = function verify(message) {
                if (typeof message !== "object" || message === null)
                    return "object expected";
                return null;
            };

            /**
             * Creates a PerfEvents message from a plain object. Also converts values to their respective internal types.
             * @function fromObject
             * @memberof perfetto.protos.PerfEvents
             * @static
             * @param {Object.<string,*>} object Plain object
             * @returns {perfetto.protos.PerfEvents} PerfEvents
             */
            PerfEvents.fromObject = function fromObject(object) {
                if (object instanceof $root.perfetto.protos.PerfEvents)
                    return object;
                return new $root.perfetto.protos.PerfEvents();
            };

            /**
             * Creates a plain object from a PerfEvents message. Also converts values to other types if specified.
             * @function toObject
             * @memberof perfetto.protos.PerfEvents
             * @static
             * @param {perfetto.protos.PerfEvents} message PerfEvents
             * @param {$protobuf.IConversionOptions} [options] Conversion options
             * @returns {Object.<string,*>} Plain object
             */
            PerfEvents.toObject = function toObject() {
                return {};
            };

            /**
             * Converts this PerfEvents to JSON.
             * @function toJSON
             * @memberof perfetto.protos.PerfEvents
             * @instance
             * @returns {Object.<string,*>} JSON object
             */
            PerfEvents.prototype.toJSON = function toJSON() {
                return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
            };

            PerfEvents.Timebase = (function() {

                /**
                 * Properties of a Timebase.
                 * @memberof perfetto.protos.PerfEvents
                 * @interface ITimebase
                 * @property {number|null} [frequency] Timebase frequency
                 * @property {number|null} [period] Timebase period
                 * @property {perfetto.protos.PerfEvents.Counter|null} [counter] Timebase counter
                 * @property {perfetto.protos.PerfEvents.ITracepoint|null} [tracepoint] Timebase tracepoint
                 */

                /**
                 * Constructs a new Timebase.
                 * @memberof perfetto.protos.PerfEvents
                 * @classdesc Represents a Timebase.
                 * @implements ITimebase
                 * @constructor
                 * @param {perfetto.protos.PerfEvents.ITimebase=} [properties] Properties to set
                 */
                function Timebase(properties) {
                    if (properties)
                        for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                            if (properties[keys[i]] != null)
                                this[keys[i]] = properties[keys[i]];
                }

                /**
                 * Timebase frequency.
                 * @member {number} frequency
                 * @memberof perfetto.protos.PerfEvents.Timebase
                 * @instance
                 */
                Timebase.prototype.frequency = $util.Long ? $util.Long.fromBits(0,0,true) : 0;

                /**
                 * Timebase period.
                 * @member {number} period
                 * @memberof perfetto.protos.PerfEvents.Timebase
                 * @instance
                 */
                Timebase.prototype.period = $util.Long ? $util.Long.fromBits(0,0,true) : 0;

                /**
                 * Timebase counter.
                 * @member {perfetto.protos.PerfEvents.Counter} counter
                 * @memberof perfetto.protos.PerfEvents.Timebase
                 * @instance
                 */
                Timebase.prototype.counter = 0;

                /**
                 * Timebase tracepoint.
                 * @member {perfetto.protos.PerfEvents.ITracepoint|null|undefined} tracepoint
                 * @memberof perfetto.protos.PerfEvents.Timebase
                 * @instance
                 */
                Timebase.prototype.tracepoint = null;

                // OneOf field names bound to virtual getters and setters
                var $oneOfFields;

                /**
                 * Timebase interval.
                 * @member {"frequency"|"period"|undefined} interval
                 * @memberof perfetto.protos.PerfEvents.Timebase
                 * @instance
                 */
                Object.defineProperty(Timebase.prototype, "interval", {
                    get: $util.oneOfGetter($oneOfFields = ["frequency", "period"]),
                    set: $util.oneOfSetter($oneOfFields)
                });

                /**
                 * Timebase event.
                 * @member {"counter"|"tracepoint"|undefined} event
                 * @memberof perfetto.protos.PerfEvents.Timebase
                 * @instance
                 */
                Object.defineProperty(Timebase.prototype, "event", {
                    get: $util.oneOfGetter($oneOfFields = ["counter", "tracepoint"]),
                    set: $util.oneOfSetter($oneOfFields)
                });

                /**
                 * Creates a new Timebase instance using the specified properties.
                 * @function create
                 * @memberof perfetto.protos.PerfEvents.Timebase
                 * @static
                 * @param {perfetto.protos.PerfEvents.ITimebase=} [properties] Properties to set
                 * @returns {perfetto.protos.PerfEvents.Timebase} Timebase instance
                 */
                Timebase.create = function create(properties) {
                    return new Timebase(properties);
                };

                /**
                 * Encodes the specified Timebase message. Does not implicitly {@link perfetto.protos.PerfEvents.Timebase.verify|verify} messages.
                 * @function encode
                 * @memberof perfetto.protos.PerfEvents.Timebase
                 * @static
                 * @param {perfetto.protos.PerfEvents.ITimebase} message Timebase message or plain object to encode
                 * @param {$protobuf.Writer} [writer] Writer to encode to
                 * @returns {$protobuf.Writer} Writer
                 */
                Timebase.encode = function encode(message, writer) {
                    if (!writer)
                        writer = $Writer.create();
                    if (message.period != null && Object.hasOwnProperty.call(message, "period"))
                        writer.uint32(/* id 1, wireType 0 =*/8).uint64(message.period);
                    if (message.frequency != null && Object.hasOwnProperty.call(message, "frequency"))
                        writer.uint32(/* id 2, wireType 0 =*/16).uint64(message.frequency);
                    if (message.tracepoint != null && Object.hasOwnProperty.call(message, "tracepoint"))
                        $root.perfetto.protos.PerfEvents.Tracepoint.encode(message.tracepoint, writer.uint32(/* id 3, wireType 2 =*/26).fork()).ldelim();
                    if (message.counter != null && Object.hasOwnProperty.call(message, "counter"))
                        writer.uint32(/* id 4, wireType 0 =*/32).int32(message.counter);
                    return writer;
                };

                /**
                 * Encodes the specified Timebase message, length delimited. Does not implicitly {@link perfetto.protos.PerfEvents.Timebase.verify|verify} messages.
                 * @function encodeDelimited
                 * @memberof perfetto.protos.PerfEvents.Timebase
                 * @static
                 * @param {perfetto.protos.PerfEvents.ITimebase} message Timebase message or plain object to encode
                 * @param {$protobuf.Writer} [writer] Writer to encode to
                 * @returns {$protobuf.Writer} Writer
                 */
                Timebase.encodeDelimited = function encodeDelimited(message, writer) {
                    return this.encode(message, writer).ldelim();
                };

                /**
                 * Decodes a Timebase message from the specified reader or buffer.
                 * @function decode
                 * @memberof perfetto.protos.PerfEvents.Timebase
                 * @static
                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                 * @param {number} [length] Message length if known beforehand
                 * @returns {perfetto.protos.PerfEvents.Timebase} Timebase
                 * @throws {Error} If the payload is not a reader or valid buffer
                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
                 */
                Timebase.decode = function decode(reader, length) {
                    if (!(reader instanceof $Reader))
                        reader = $Reader.create(reader);
                    var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.PerfEvents.Timebase();
                    while (reader.pos < end) {
                        var tag = reader.uint32();
                        switch (tag >>> 3) {
                        case 2:
                            message.frequency = reader.uint64();
                            break;
                        case 1:
                            message.period = reader.uint64();
                            break;
                        case 4:
                            message.counter = reader.int32();
                            break;
                        case 3:
                            message.tracepoint = $root.perfetto.protos.PerfEvents.Tracepoint.decode(reader, reader.uint32());
                            break;
                        default:
                            reader.skipType(tag & 7);
                            break;
                        }
                    }
                    return message;
                };

                /**
                 * Decodes a Timebase message from the specified reader or buffer, length delimited.
                 * @function decodeDelimited
                 * @memberof perfetto.protos.PerfEvents.Timebase
                 * @static
                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                 * @returns {perfetto.protos.PerfEvents.Timebase} Timebase
                 * @throws {Error} If the payload is not a reader or valid buffer
                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
                 */
                Timebase.decodeDelimited = function decodeDelimited(reader) {
                    if (!(reader instanceof $Reader))
                        reader = new $Reader(reader);
                    return this.decode(reader, reader.uint32());
                };

                /**
                 * Verifies a Timebase message.
                 * @function verify
                 * @memberof perfetto.protos.PerfEvents.Timebase
                 * @static
                 * @param {Object.<string,*>} message Plain object to verify
                 * @returns {string|null} `null` if valid, otherwise the reason why it is not
                 */
                Timebase.verify = function verify(message) {
                    if (typeof message !== "object" || message === null)
                        return "object expected";
                    var properties = {};
                    if (message.frequency != null && message.hasOwnProperty("frequency")) {
                        properties.interval = 1;
                        if (!$util.isInteger(message.frequency) && !(message.frequency && $util.isInteger(message.frequency.low) && $util.isInteger(message.frequency.high)))
                            return "frequency: integer|Long expected";
                    }
                    if (message.period != null && message.hasOwnProperty("period")) {
                        if (properties.interval === 1)
                            return "interval: multiple values";
                        properties.interval = 1;
                        if (!$util.isInteger(message.period) && !(message.period && $util.isInteger(message.period.low) && $util.isInteger(message.period.high)))
                            return "period: integer|Long expected";
                    }
                    if (message.counter != null && message.hasOwnProperty("counter")) {
                        properties.event = 1;
                        switch (message.counter) {
                        default:
                            return "counter: enum value expected";
                        case 0:
                        case 1:
                        case 2:
                        case 10:
                        case 11:
                            break;
                        }
                    }
                    if (message.tracepoint != null && message.hasOwnProperty("tracepoint")) {
                        if (properties.event === 1)
                            return "event: multiple values";
                        properties.event = 1;
                        {
                            var error = $root.perfetto.protos.PerfEvents.Tracepoint.verify(message.tracepoint);
                            if (error)
                                return "tracepoint." + error;
                        }
                    }
                    return null;
                };

                /**
                 * Creates a Timebase message from a plain object. Also converts values to their respective internal types.
                 * @function fromObject
                 * @memberof perfetto.protos.PerfEvents.Timebase
                 * @static
                 * @param {Object.<string,*>} object Plain object
                 * @returns {perfetto.protos.PerfEvents.Timebase} Timebase
                 */
                Timebase.fromObject = function fromObject(object) {
                    if (object instanceof $root.perfetto.protos.PerfEvents.Timebase)
                        return object;
                    var message = new $root.perfetto.protos.PerfEvents.Timebase();
                    if (object.frequency != null)
                        if ($util.Long)
                            (message.frequency = $util.Long.fromValue(object.frequency)).unsigned = true;
                        else if (typeof object.frequency === "string")
                            message.frequency = parseInt(object.frequency, 10);
                        else if (typeof object.frequency === "number")
                            message.frequency = object.frequency;
                        else if (typeof object.frequency === "object")
                            message.frequency = new $util.LongBits(object.frequency.low >>> 0, object.frequency.high >>> 0).toNumber(true);
                    if (object.period != null)
                        if ($util.Long)
                            (message.period = $util.Long.fromValue(object.period)).unsigned = true;
                        else if (typeof object.period === "string")
                            message.period = parseInt(object.period, 10);
                        else if (typeof object.period === "number")
                            message.period = object.period;
                        else if (typeof object.period === "object")
                            message.period = new $util.LongBits(object.period.low >>> 0, object.period.high >>> 0).toNumber(true);
                    switch (object.counter) {
                    case "UNKNOWN_COUNTER":
                    case 0:
                        message.counter = 0;
                        break;
                    case "SW_CPU_CLOCK":
                    case 1:
                        message.counter = 1;
                        break;
                    case "SW_PAGE_FAULTS":
                    case 2:
                        message.counter = 2;
                        break;
                    case "HW_CPU_CYCLES":
                    case 10:
                        message.counter = 10;
                        break;
                    case "HW_INSTRUCTIONS":
                    case 11:
                        message.counter = 11;
                        break;
                    }
                    if (object.tracepoint != null) {
                        if (typeof object.tracepoint !== "object")
                            throw TypeError(".perfetto.protos.PerfEvents.Timebase.tracepoint: object expected");
                        message.tracepoint = $root.perfetto.protos.PerfEvents.Tracepoint.fromObject(object.tracepoint);
                    }
                    return message;
                };

                /**
                 * Creates a plain object from a Timebase message. Also converts values to other types if specified.
                 * @function toObject
                 * @memberof perfetto.protos.PerfEvents.Timebase
                 * @static
                 * @param {perfetto.protos.PerfEvents.Timebase} message Timebase
                 * @param {$protobuf.IConversionOptions} [options] Conversion options
                 * @returns {Object.<string,*>} Plain object
                 */
                Timebase.toObject = function toObject(message, options) {
                    if (!options)
                        options = {};
                    var object = {};
                    if (message.period != null && message.hasOwnProperty("period")) {
                        if (typeof message.period === "number")
                            object.period = options.longs === String ? String(message.period) : message.period;
                        else
                            object.period = options.longs === String ? $util.Long.prototype.toString.call(message.period) : options.longs === Number ? new $util.LongBits(message.period.low >>> 0, message.period.high >>> 0).toNumber(true) : message.period;
                        if (options.oneofs)
                            object.interval = "period";
                    }
                    if (message.frequency != null && message.hasOwnProperty("frequency")) {
                        if (typeof message.frequency === "number")
                            object.frequency = options.longs === String ? String(message.frequency) : message.frequency;
                        else
                            object.frequency = options.longs === String ? $util.Long.prototype.toString.call(message.frequency) : options.longs === Number ? new $util.LongBits(message.frequency.low >>> 0, message.frequency.high >>> 0).toNumber(true) : message.frequency;
                        if (options.oneofs)
                            object.interval = "frequency";
                    }
                    if (message.tracepoint != null && message.hasOwnProperty("tracepoint")) {
                        object.tracepoint = $root.perfetto.protos.PerfEvents.Tracepoint.toObject(message.tracepoint, options);
                        if (options.oneofs)
                            object.event = "tracepoint";
                    }
                    if (message.counter != null && message.hasOwnProperty("counter")) {
                        object.counter = options.enums === String ? $root.perfetto.protos.PerfEvents.Counter[message.counter] : message.counter;
                        if (options.oneofs)
                            object.event = "counter";
                    }
                    return object;
                };

                /**
                 * Converts this Timebase to JSON.
                 * @function toJSON
                 * @memberof perfetto.protos.PerfEvents.Timebase
                 * @instance
                 * @returns {Object.<string,*>} JSON object
                 */
                Timebase.prototype.toJSON = function toJSON() {
                    return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
                };

                return Timebase;
            })();

            /**
             * Counter enum.
             * @name perfetto.protos.PerfEvents.Counter
             * @enum {number}
             * @property {number} UNKNOWN_COUNTER=0 UNKNOWN_COUNTER value
             * @property {number} SW_CPU_CLOCK=1 SW_CPU_CLOCK value
             * @property {number} SW_PAGE_FAULTS=2 SW_PAGE_FAULTS value
             * @property {number} HW_CPU_CYCLES=10 HW_CPU_CYCLES value
             * @property {number} HW_INSTRUCTIONS=11 HW_INSTRUCTIONS value
             */
            PerfEvents.Counter = (function() {
                var valuesById = {}, values = Object.create(valuesById);
                values[valuesById[0] = "UNKNOWN_COUNTER"] = 0;
                values[valuesById[1] = "SW_CPU_CLOCK"] = 1;
                values[valuesById[2] = "SW_PAGE_FAULTS"] = 2;
                values[valuesById[10] = "HW_CPU_CYCLES"] = 10;
                values[valuesById[11] = "HW_INSTRUCTIONS"] = 11;
                return values;
            })();

            PerfEvents.Tracepoint = (function() {

                /**
                 * Properties of a Tracepoint.
                 * @memberof perfetto.protos.PerfEvents
                 * @interface ITracepoint
                 * @property {string|null} [name] Tracepoint name
                 * @property {string|null} [filter] Tracepoint filter
                 */

                /**
                 * Constructs a new Tracepoint.
                 * @memberof perfetto.protos.PerfEvents
                 * @classdesc Represents a Tracepoint.
                 * @implements ITracepoint
                 * @constructor
                 * @param {perfetto.protos.PerfEvents.ITracepoint=} [properties] Properties to set
                 */
                function Tracepoint(properties) {
                    if (properties)
                        for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                            if (properties[keys[i]] != null)
                                this[keys[i]] = properties[keys[i]];
                }

                /**
                 * Tracepoint name.
                 * @member {string} name
                 * @memberof perfetto.protos.PerfEvents.Tracepoint
                 * @instance
                 */
                Tracepoint.prototype.name = "";

                /**
                 * Tracepoint filter.
                 * @member {string} filter
                 * @memberof perfetto.protos.PerfEvents.Tracepoint
                 * @instance
                 */
                Tracepoint.prototype.filter = "";

                /**
                 * Creates a new Tracepoint instance using the specified properties.
                 * @function create
                 * @memberof perfetto.protos.PerfEvents.Tracepoint
                 * @static
                 * @param {perfetto.protos.PerfEvents.ITracepoint=} [properties] Properties to set
                 * @returns {perfetto.protos.PerfEvents.Tracepoint} Tracepoint instance
                 */
                Tracepoint.create = function create(properties) {
                    return new Tracepoint(properties);
                };

                /**
                 * Encodes the specified Tracepoint message. Does not implicitly {@link perfetto.protos.PerfEvents.Tracepoint.verify|verify} messages.
                 * @function encode
                 * @memberof perfetto.protos.PerfEvents.Tracepoint
                 * @static
                 * @param {perfetto.protos.PerfEvents.ITracepoint} message Tracepoint message or plain object to encode
                 * @param {$protobuf.Writer} [writer] Writer to encode to
                 * @returns {$protobuf.Writer} Writer
                 */
                Tracepoint.encode = function encode(message, writer) {
                    if (!writer)
                        writer = $Writer.create();
                    if (message.name != null && Object.hasOwnProperty.call(message, "name"))
                        writer.uint32(/* id 1, wireType 2 =*/10).string(message.name);
                    if (message.filter != null && Object.hasOwnProperty.call(message, "filter"))
                        writer.uint32(/* id 2, wireType 2 =*/18).string(message.filter);
                    return writer;
                };

                /**
                 * Encodes the specified Tracepoint message, length delimited. Does not implicitly {@link perfetto.protos.PerfEvents.Tracepoint.verify|verify} messages.
                 * @function encodeDelimited
                 * @memberof perfetto.protos.PerfEvents.Tracepoint
                 * @static
                 * @param {perfetto.protos.PerfEvents.ITracepoint} message Tracepoint message or plain object to encode
                 * @param {$protobuf.Writer} [writer] Writer to encode to
                 * @returns {$protobuf.Writer} Writer
                 */
                Tracepoint.encodeDelimited = function encodeDelimited(message, writer) {
                    return this.encode(message, writer).ldelim();
                };

                /**
                 * Decodes a Tracepoint message from the specified reader or buffer.
                 * @function decode
                 * @memberof perfetto.protos.PerfEvents.Tracepoint
                 * @static
                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                 * @param {number} [length] Message length if known beforehand
                 * @returns {perfetto.protos.PerfEvents.Tracepoint} Tracepoint
                 * @throws {Error} If the payload is not a reader or valid buffer
                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
                 */
                Tracepoint.decode = function decode(reader, length) {
                    if (!(reader instanceof $Reader))
                        reader = $Reader.create(reader);
                    var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.PerfEvents.Tracepoint();
                    while (reader.pos < end) {
                        var tag = reader.uint32();
                        switch (tag >>> 3) {
                        case 1:
                            message.name = reader.string();
                            break;
                        case 2:
                            message.filter = reader.string();
                            break;
                        default:
                            reader.skipType(tag & 7);
                            break;
                        }
                    }
                    return message;
                };

                /**
                 * Decodes a Tracepoint message from the specified reader or buffer, length delimited.
                 * @function decodeDelimited
                 * @memberof perfetto.protos.PerfEvents.Tracepoint
                 * @static
                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                 * @returns {perfetto.protos.PerfEvents.Tracepoint} Tracepoint
                 * @throws {Error} If the payload is not a reader or valid buffer
                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
                 */
                Tracepoint.decodeDelimited = function decodeDelimited(reader) {
                    if (!(reader instanceof $Reader))
                        reader = new $Reader(reader);
                    return this.decode(reader, reader.uint32());
                };

                /**
                 * Verifies a Tracepoint message.
                 * @function verify
                 * @memberof perfetto.protos.PerfEvents.Tracepoint
                 * @static
                 * @param {Object.<string,*>} message Plain object to verify
                 * @returns {string|null} `null` if valid, otherwise the reason why it is not
                 */
                Tracepoint.verify = function verify(message) {
                    if (typeof message !== "object" || message === null)
                        return "object expected";
                    if (message.name != null && message.hasOwnProperty("name"))
                        if (!$util.isString(message.name))
                            return "name: string expected";
                    if (message.filter != null && message.hasOwnProperty("filter"))
                        if (!$util.isString(message.filter))
                            return "filter: string expected";
                    return null;
                };

                /**
                 * Creates a Tracepoint message from a plain object. Also converts values to their respective internal types.
                 * @function fromObject
                 * @memberof perfetto.protos.PerfEvents.Tracepoint
                 * @static
                 * @param {Object.<string,*>} object Plain object
                 * @returns {perfetto.protos.PerfEvents.Tracepoint} Tracepoint
                 */
                Tracepoint.fromObject = function fromObject(object) {
                    if (object instanceof $root.perfetto.protos.PerfEvents.Tracepoint)
                        return object;
                    var message = new $root.perfetto.protos.PerfEvents.Tracepoint();
                    if (object.name != null)
                        message.name = String(object.name);
                    if (object.filter != null)
                        message.filter = String(object.filter);
                    return message;
                };

                /**
                 * Creates a plain object from a Tracepoint message. Also converts values to other types if specified.
                 * @function toObject
                 * @memberof perfetto.protos.PerfEvents.Tracepoint
                 * @static
                 * @param {perfetto.protos.PerfEvents.Tracepoint} message Tracepoint
                 * @param {$protobuf.IConversionOptions} [options] Conversion options
                 * @returns {Object.<string,*>} Plain object
                 */
                Tracepoint.toObject = function toObject(message, options) {
                    if (!options)
                        options = {};
                    var object = {};
                    if (options.defaults) {
                        object.name = "";
                        object.filter = "";
                    }
                    if (message.name != null && message.hasOwnProperty("name"))
                        object.name = message.name;
                    if (message.filter != null && message.hasOwnProperty("filter"))
                        object.filter = message.filter;
                    return object;
                };

                /**
                 * Converts this Tracepoint to JSON.
                 * @function toJSON
                 * @memberof perfetto.protos.PerfEvents.Tracepoint
                 * @instance
                 * @returns {Object.<string,*>} JSON object
                 */
                Tracepoint.prototype.toJSON = function toJSON() {
                    return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
                };

                return Tracepoint;
            })();

            return PerfEvents;
        })();

        protos.PerfEventConfig = (function() {

            /**
             * Properties of a PerfEventConfig.
             * @memberof perfetto.protos
             * @interface IPerfEventConfig
             * @property {perfetto.protos.PerfEvents.ITimebase|null} [timebase] PerfEventConfig timebase
             * @property {perfetto.protos.PerfEventConfig.ICallstackSampling|null} [callstackSampling] PerfEventConfig callstackSampling
             * @property {number|null} [ringBufferReadPeriodMs] PerfEventConfig ringBufferReadPeriodMs
             * @property {number|null} [ringBufferPages] PerfEventConfig ringBufferPages
             * @property {number|null} [maxEnqueuedFootprintKb] PerfEventConfig maxEnqueuedFootprintKb
             * @property {number|null} [maxDaemonMemoryKb] PerfEventConfig maxDaemonMemoryKb
             * @property {number|null} [remoteDescriptorTimeoutMs] PerfEventConfig remoteDescriptorTimeoutMs
             * @property {number|null} [unwindStateClearPeriodMs] PerfEventConfig unwindStateClearPeriodMs
             * @property {boolean|null} [allCpus] PerfEventConfig allCpus
             * @property {number|null} [samplingFrequency] PerfEventConfig samplingFrequency
             * @property {boolean|null} [kernelFrames] PerfEventConfig kernelFrames
             * @property {Array.<number>|null} [targetPid] PerfEventConfig targetPid
             * @property {Array.<string>|null} [targetCmdline] PerfEventConfig targetCmdline
             * @property {Array.<string>|null} [targetInstalledBy] PerfEventConfig targetInstalledBy
             * @property {Array.<number>|null} [excludePid] PerfEventConfig excludePid
             * @property {Array.<string>|null} [excludeCmdline] PerfEventConfig excludeCmdline
             * @property {number|null} [additionalCmdlineCount] PerfEventConfig additionalCmdlineCount
             */

            /**
             * Constructs a new PerfEventConfig.
             * @memberof perfetto.protos
             * @classdesc Represents a PerfEventConfig.
             * @implements IPerfEventConfig
             * @constructor
             * @param {perfetto.protos.IPerfEventConfig=} [properties] Properties to set
             */
            function PerfEventConfig(properties) {
                this.targetPid = [];
                this.targetCmdline = [];
                this.targetInstalledBy = [];
                this.excludePid = [];
                this.excludeCmdline = [];
                if (properties)
                    for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                        if (properties[keys[i]] != null)
                            this[keys[i]] = properties[keys[i]];
            }

            /**
             * PerfEventConfig timebase.
             * @member {perfetto.protos.PerfEvents.ITimebase|null|undefined} timebase
             * @memberof perfetto.protos.PerfEventConfig
             * @instance
             */
            PerfEventConfig.prototype.timebase = null;

            /**
             * PerfEventConfig callstackSampling.
             * @member {perfetto.protos.PerfEventConfig.ICallstackSampling|null|undefined} callstackSampling
             * @memberof perfetto.protos.PerfEventConfig
             * @instance
             */
            PerfEventConfig.prototype.callstackSampling = null;

            /**
             * PerfEventConfig ringBufferReadPeriodMs.
             * @member {number} ringBufferReadPeriodMs
             * @memberof perfetto.protos.PerfEventConfig
             * @instance
             */
            PerfEventConfig.prototype.ringBufferReadPeriodMs = 0;

            /**
             * PerfEventConfig ringBufferPages.
             * @member {number} ringBufferPages
             * @memberof perfetto.protos.PerfEventConfig
             * @instance
             */
            PerfEventConfig.prototype.ringBufferPages = 0;

            /**
             * PerfEventConfig maxEnqueuedFootprintKb.
             * @member {number} maxEnqueuedFootprintKb
             * @memberof perfetto.protos.PerfEventConfig
             * @instance
             */
            PerfEventConfig.prototype.maxEnqueuedFootprintKb = $util.Long ? $util.Long.fromBits(0,0,true) : 0;

            /**
             * PerfEventConfig maxDaemonMemoryKb.
             * @member {number} maxDaemonMemoryKb
             * @memberof perfetto.protos.PerfEventConfig
             * @instance
             */
            PerfEventConfig.prototype.maxDaemonMemoryKb = 0;

            /**
             * PerfEventConfig remoteDescriptorTimeoutMs.
             * @member {number} remoteDescriptorTimeoutMs
             * @memberof perfetto.protos.PerfEventConfig
             * @instance
             */
            PerfEventConfig.prototype.remoteDescriptorTimeoutMs = 0;

            /**
             * PerfEventConfig unwindStateClearPeriodMs.
             * @member {number} unwindStateClearPeriodMs
             * @memberof perfetto.protos.PerfEventConfig
             * @instance
             */
            PerfEventConfig.prototype.unwindStateClearPeriodMs = 0;

            /**
             * PerfEventConfig allCpus.
             * @member {boolean} allCpus
             * @memberof perfetto.protos.PerfEventConfig
             * @instance
             */
            PerfEventConfig.prototype.allCpus = false;

            /**
             * PerfEventConfig samplingFrequency.
             * @member {number} samplingFrequency
             * @memberof perfetto.protos.PerfEventConfig
             * @instance
             */
            PerfEventConfig.prototype.samplingFrequency = 0;

            /**
             * PerfEventConfig kernelFrames.
             * @member {boolean} kernelFrames
             * @memberof perfetto.protos.PerfEventConfig
             * @instance
             */
            PerfEventConfig.prototype.kernelFrames = false;

            /**
             * PerfEventConfig targetPid.
             * @member {Array.<number>} targetPid
             * @memberof perfetto.protos.PerfEventConfig
             * @instance
             */
            PerfEventConfig.prototype.targetPid = $util.emptyArray;

            /**
             * PerfEventConfig targetCmdline.
             * @member {Array.<string>} targetCmdline
             * @memberof perfetto.protos.PerfEventConfig
             * @instance
             */
            PerfEventConfig.prototype.targetCmdline = $util.emptyArray;

            /**
             * PerfEventConfig targetInstalledBy.
             * @member {Array.<string>} targetInstalledBy
             * @memberof perfetto.protos.PerfEventConfig
             * @instance
             */
            PerfEventConfig.prototype.targetInstalledBy = $util.emptyArray;

            /**
             * PerfEventConfig excludePid.
             * @member {Array.<number>} excludePid
             * @memberof perfetto.protos.PerfEventConfig
             * @instance
             */
            PerfEventConfig.prototype.excludePid = $util.emptyArray;

            /**
             * PerfEventConfig excludeCmdline.
             * @member {Array.<string>} excludeCmdline
             * @memberof perfetto.protos.PerfEventConfig
             * @instance
             */
            PerfEventConfig.prototype.excludeCmdline = $util.emptyArray;

            /**
             * PerfEventConfig additionalCmdlineCount.
             * @member {number} additionalCmdlineCount
             * @memberof perfetto.protos.PerfEventConfig
             * @instance
             */
            PerfEventConfig.prototype.additionalCmdlineCount = 0;

            /**
             * Creates a new PerfEventConfig instance using the specified properties.
             * @function create
             * @memberof perfetto.protos.PerfEventConfig
             * @static
             * @param {perfetto.protos.IPerfEventConfig=} [properties] Properties to set
             * @returns {perfetto.protos.PerfEventConfig} PerfEventConfig instance
             */
            PerfEventConfig.create = function create(properties) {
                return new PerfEventConfig(properties);
            };

            /**
             * Encodes the specified PerfEventConfig message. Does not implicitly {@link perfetto.protos.PerfEventConfig.verify|verify} messages.
             * @function encode
             * @memberof perfetto.protos.PerfEventConfig
             * @static
             * @param {perfetto.protos.IPerfEventConfig} message PerfEventConfig message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            PerfEventConfig.encode = function encode(message, writer) {
                if (!writer)
                    writer = $Writer.create();
                if (message.allCpus != null && Object.hasOwnProperty.call(message, "allCpus"))
                    writer.uint32(/* id 1, wireType 0 =*/8).bool(message.allCpus);
                if (message.samplingFrequency != null && Object.hasOwnProperty.call(message, "samplingFrequency"))
                    writer.uint32(/* id 2, wireType 0 =*/16).uint32(message.samplingFrequency);
                if (message.ringBufferPages != null && Object.hasOwnProperty.call(message, "ringBufferPages"))
                    writer.uint32(/* id 3, wireType 0 =*/24).uint32(message.ringBufferPages);
                if (message.targetPid != null && message.targetPid.length)
                    for (var i = 0; i < message.targetPid.length; ++i)
                        writer.uint32(/* id 4, wireType 0 =*/32).int32(message.targetPid[i]);
                if (message.targetCmdline != null && message.targetCmdline.length)
                    for (var i = 0; i < message.targetCmdline.length; ++i)
                        writer.uint32(/* id 5, wireType 2 =*/42).string(message.targetCmdline[i]);
                if (message.excludePid != null && message.excludePid.length)
                    for (var i = 0; i < message.excludePid.length; ++i)
                        writer.uint32(/* id 6, wireType 0 =*/48).int32(message.excludePid[i]);
                if (message.excludeCmdline != null && message.excludeCmdline.length)
                    for (var i = 0; i < message.excludeCmdline.length; ++i)
                        writer.uint32(/* id 7, wireType 2 =*/58).string(message.excludeCmdline[i]);
                if (message.ringBufferReadPeriodMs != null && Object.hasOwnProperty.call(message, "ringBufferReadPeriodMs"))
                    writer.uint32(/* id 8, wireType 0 =*/64).uint32(message.ringBufferReadPeriodMs);
                if (message.remoteDescriptorTimeoutMs != null && Object.hasOwnProperty.call(message, "remoteDescriptorTimeoutMs"))
                    writer.uint32(/* id 9, wireType 0 =*/72).uint32(message.remoteDescriptorTimeoutMs);
                if (message.unwindStateClearPeriodMs != null && Object.hasOwnProperty.call(message, "unwindStateClearPeriodMs"))
                    writer.uint32(/* id 10, wireType 0 =*/80).uint32(message.unwindStateClearPeriodMs);
                if (message.additionalCmdlineCount != null && Object.hasOwnProperty.call(message, "additionalCmdlineCount"))
                    writer.uint32(/* id 11, wireType 0 =*/88).uint32(message.additionalCmdlineCount);
                if (message.kernelFrames != null && Object.hasOwnProperty.call(message, "kernelFrames"))
                    writer.uint32(/* id 12, wireType 0 =*/96).bool(message.kernelFrames);
                if (message.maxDaemonMemoryKb != null && Object.hasOwnProperty.call(message, "maxDaemonMemoryKb"))
                    writer.uint32(/* id 13, wireType 0 =*/104).uint32(message.maxDaemonMemoryKb);
                if (message.timebase != null && Object.hasOwnProperty.call(message, "timebase"))
                    $root.perfetto.protos.PerfEvents.Timebase.encode(message.timebase, writer.uint32(/* id 15, wireType 2 =*/122).fork()).ldelim();
                if (message.callstackSampling != null && Object.hasOwnProperty.call(message, "callstackSampling"))
                    $root.perfetto.protos.PerfEventConfig.CallstackSampling.encode(message.callstackSampling, writer.uint32(/* id 16, wireType 2 =*/130).fork()).ldelim();
                if (message.maxEnqueuedFootprintKb != null && Object.hasOwnProperty.call(message, "maxEnqueuedFootprintKb"))
                    writer.uint32(/* id 17, wireType 0 =*/136).uint64(message.maxEnqueuedFootprintKb);
                if (message.targetInstalledBy != null && message.targetInstalledBy.length)
                    for (var i = 0; i < message.targetInstalledBy.length; ++i)
                        writer.uint32(/* id 18, wireType 2 =*/146).string(message.targetInstalledBy[i]);
                return writer;
            };

            /**
             * Encodes the specified PerfEventConfig message, length delimited. Does not implicitly {@link perfetto.protos.PerfEventConfig.verify|verify} messages.
             * @function encodeDelimited
             * @memberof perfetto.protos.PerfEventConfig
             * @static
             * @param {perfetto.protos.IPerfEventConfig} message PerfEventConfig message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            PerfEventConfig.encodeDelimited = function encodeDelimited(message, writer) {
                return this.encode(message, writer).ldelim();
            };

            /**
             * Decodes a PerfEventConfig message from the specified reader or buffer.
             * @function decode
             * @memberof perfetto.protos.PerfEventConfig
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @param {number} [length] Message length if known beforehand
             * @returns {perfetto.protos.PerfEventConfig} PerfEventConfig
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            PerfEventConfig.decode = function decode(reader, length) {
                if (!(reader instanceof $Reader))
                    reader = $Reader.create(reader);
                var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.PerfEventConfig();
                while (reader.pos < end) {
                    var tag = reader.uint32();
                    switch (tag >>> 3) {
                    case 15:
                        message.timebase = $root.perfetto.protos.PerfEvents.Timebase.decode(reader, reader.uint32());
                        break;
                    case 16:
                        message.callstackSampling = $root.perfetto.protos.PerfEventConfig.CallstackSampling.decode(reader, reader.uint32());
                        break;
                    case 8:
                        message.ringBufferReadPeriodMs = reader.uint32();
                        break;
                    case 3:
                        message.ringBufferPages = reader.uint32();
                        break;
                    case 17:
                        message.maxEnqueuedFootprintKb = reader.uint64();
                        break;
                    case 13:
                        message.maxDaemonMemoryKb = reader.uint32();
                        break;
                    case 9:
                        message.remoteDescriptorTimeoutMs = reader.uint32();
                        break;
                    case 10:
                        message.unwindStateClearPeriodMs = reader.uint32();
                        break;
                    case 1:
                        message.allCpus = reader.bool();
                        break;
                    case 2:
                        message.samplingFrequency = reader.uint32();
                        break;
                    case 12:
                        message.kernelFrames = reader.bool();
                        break;
                    case 4:
                        if (!(message.targetPid && message.targetPid.length))
                            message.targetPid = [];
                        if ((tag & 7) === 2) {
                            var end2 = reader.uint32() + reader.pos;
                            while (reader.pos < end2)
                                message.targetPid.push(reader.int32());
                        } else
                            message.targetPid.push(reader.int32());
                        break;
                    case 5:
                        if (!(message.targetCmdline && message.targetCmdline.length))
                            message.targetCmdline = [];
                        message.targetCmdline.push(reader.string());
                        break;
                    case 18:
                        if (!(message.targetInstalledBy && message.targetInstalledBy.length))
                            message.targetInstalledBy = [];
                        message.targetInstalledBy.push(reader.string());
                        break;
                    case 6:
                        if (!(message.excludePid && message.excludePid.length))
                            message.excludePid = [];
                        if ((tag & 7) === 2) {
                            var end2 = reader.uint32() + reader.pos;
                            while (reader.pos < end2)
                                message.excludePid.push(reader.int32());
                        } else
                            message.excludePid.push(reader.int32());
                        break;
                    case 7:
                        if (!(message.excludeCmdline && message.excludeCmdline.length))
                            message.excludeCmdline = [];
                        message.excludeCmdline.push(reader.string());
                        break;
                    case 11:
                        message.additionalCmdlineCount = reader.uint32();
                        break;
                    default:
                        reader.skipType(tag & 7);
                        break;
                    }
                }
                return message;
            };

            /**
             * Decodes a PerfEventConfig message from the specified reader or buffer, length delimited.
             * @function decodeDelimited
             * @memberof perfetto.protos.PerfEventConfig
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @returns {perfetto.protos.PerfEventConfig} PerfEventConfig
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            PerfEventConfig.decodeDelimited = function decodeDelimited(reader) {
                if (!(reader instanceof $Reader))
                    reader = new $Reader(reader);
                return this.decode(reader, reader.uint32());
            };

            /**
             * Verifies a PerfEventConfig message.
             * @function verify
             * @memberof perfetto.protos.PerfEventConfig
             * @static
             * @param {Object.<string,*>} message Plain object to verify
             * @returns {string|null} `null` if valid, otherwise the reason why it is not
             */
            PerfEventConfig.verify = function verify(message) {
                if (typeof message !== "object" || message === null)
                    return "object expected";
                if (message.timebase != null && message.hasOwnProperty("timebase")) {
                    var error = $root.perfetto.protos.PerfEvents.Timebase.verify(message.timebase);
                    if (error)
                        return "timebase." + error;
                }
                if (message.callstackSampling != null && message.hasOwnProperty("callstackSampling")) {
                    var error = $root.perfetto.protos.PerfEventConfig.CallstackSampling.verify(message.callstackSampling);
                    if (error)
                        return "callstackSampling." + error;
                }
                if (message.ringBufferReadPeriodMs != null && message.hasOwnProperty("ringBufferReadPeriodMs"))
                    if (!$util.isInteger(message.ringBufferReadPeriodMs))
                        return "ringBufferReadPeriodMs: integer expected";
                if (message.ringBufferPages != null && message.hasOwnProperty("ringBufferPages"))
                    if (!$util.isInteger(message.ringBufferPages))
                        return "ringBufferPages: integer expected";
                if (message.maxEnqueuedFootprintKb != null && message.hasOwnProperty("maxEnqueuedFootprintKb"))
                    if (!$util.isInteger(message.maxEnqueuedFootprintKb) && !(message.maxEnqueuedFootprintKb && $util.isInteger(message.maxEnqueuedFootprintKb.low) && $util.isInteger(message.maxEnqueuedFootprintKb.high)))
                        return "maxEnqueuedFootprintKb: integer|Long expected";
                if (message.maxDaemonMemoryKb != null && message.hasOwnProperty("maxDaemonMemoryKb"))
                    if (!$util.isInteger(message.maxDaemonMemoryKb))
                        return "maxDaemonMemoryKb: integer expected";
                if (message.remoteDescriptorTimeoutMs != null && message.hasOwnProperty("remoteDescriptorTimeoutMs"))
                    if (!$util.isInteger(message.remoteDescriptorTimeoutMs))
                        return "remoteDescriptorTimeoutMs: integer expected";
                if (message.unwindStateClearPeriodMs != null && message.hasOwnProperty("unwindStateClearPeriodMs"))
                    if (!$util.isInteger(message.unwindStateClearPeriodMs))
                        return "unwindStateClearPeriodMs: integer expected";
                if (message.allCpus != null && message.hasOwnProperty("allCpus"))
                    if (typeof message.allCpus !== "boolean")
                        return "allCpus: boolean expected";
                if (message.samplingFrequency != null && message.hasOwnProperty("samplingFrequency"))
                    if (!$util.isInteger(message.samplingFrequency))
                        return "samplingFrequency: integer expected";
                if (message.kernelFrames != null && message.hasOwnProperty("kernelFrames"))
                    if (typeof message.kernelFrames !== "boolean")
                        return "kernelFrames: boolean expected";
                if (message.targetPid != null && message.hasOwnProperty("targetPid")) {
                    if (!Array.isArray(message.targetPid))
                        return "targetPid: array expected";
                    for (var i = 0; i < message.targetPid.length; ++i)
                        if (!$util.isInteger(message.targetPid[i]))
                            return "targetPid: integer[] expected";
                }
                if (message.targetCmdline != null && message.hasOwnProperty("targetCmdline")) {
                    if (!Array.isArray(message.targetCmdline))
                        return "targetCmdline: array expected";
                    for (var i = 0; i < message.targetCmdline.length; ++i)
                        if (!$util.isString(message.targetCmdline[i]))
                            return "targetCmdline: string[] expected";
                }
                if (message.targetInstalledBy != null && message.hasOwnProperty("targetInstalledBy")) {
                    if (!Array.isArray(message.targetInstalledBy))
                        return "targetInstalledBy: array expected";
                    for (var i = 0; i < message.targetInstalledBy.length; ++i)
                        if (!$util.isString(message.targetInstalledBy[i]))
                            return "targetInstalledBy: string[] expected";
                }
                if (message.excludePid != null && message.hasOwnProperty("excludePid")) {
                    if (!Array.isArray(message.excludePid))
                        return "excludePid: array expected";
                    for (var i = 0; i < message.excludePid.length; ++i)
                        if (!$util.isInteger(message.excludePid[i]))
                            return "excludePid: integer[] expected";
                }
                if (message.excludeCmdline != null && message.hasOwnProperty("excludeCmdline")) {
                    if (!Array.isArray(message.excludeCmdline))
                        return "excludeCmdline: array expected";
                    for (var i = 0; i < message.excludeCmdline.length; ++i)
                        if (!$util.isString(message.excludeCmdline[i]))
                            return "excludeCmdline: string[] expected";
                }
                if (message.additionalCmdlineCount != null && message.hasOwnProperty("additionalCmdlineCount"))
                    if (!$util.isInteger(message.additionalCmdlineCount))
                        return "additionalCmdlineCount: integer expected";
                return null;
            };

            /**
             * Creates a PerfEventConfig message from a plain object. Also converts values to their respective internal types.
             * @function fromObject
             * @memberof perfetto.protos.PerfEventConfig
             * @static
             * @param {Object.<string,*>} object Plain object
             * @returns {perfetto.protos.PerfEventConfig} PerfEventConfig
             */
            PerfEventConfig.fromObject = function fromObject(object) {
                if (object instanceof $root.perfetto.protos.PerfEventConfig)
                    return object;
                var message = new $root.perfetto.protos.PerfEventConfig();
                if (object.timebase != null) {
                    if (typeof object.timebase !== "object")
                        throw TypeError(".perfetto.protos.PerfEventConfig.timebase: object expected");
                    message.timebase = $root.perfetto.protos.PerfEvents.Timebase.fromObject(object.timebase);
                }
                if (object.callstackSampling != null) {
                    if (typeof object.callstackSampling !== "object")
                        throw TypeError(".perfetto.protos.PerfEventConfig.callstackSampling: object expected");
                    message.callstackSampling = $root.perfetto.protos.PerfEventConfig.CallstackSampling.fromObject(object.callstackSampling);
                }
                if (object.ringBufferReadPeriodMs != null)
                    message.ringBufferReadPeriodMs = object.ringBufferReadPeriodMs >>> 0;
                if (object.ringBufferPages != null)
                    message.ringBufferPages = object.ringBufferPages >>> 0;
                if (object.maxEnqueuedFootprintKb != null)
                    if ($util.Long)
                        (message.maxEnqueuedFootprintKb = $util.Long.fromValue(object.maxEnqueuedFootprintKb)).unsigned = true;
                    else if (typeof object.maxEnqueuedFootprintKb === "string")
                        message.maxEnqueuedFootprintKb = parseInt(object.maxEnqueuedFootprintKb, 10);
                    else if (typeof object.maxEnqueuedFootprintKb === "number")
                        message.maxEnqueuedFootprintKb = object.maxEnqueuedFootprintKb;
                    else if (typeof object.maxEnqueuedFootprintKb === "object")
                        message.maxEnqueuedFootprintKb = new $util.LongBits(object.maxEnqueuedFootprintKb.low >>> 0, object.maxEnqueuedFootprintKb.high >>> 0).toNumber(true);
                if (object.maxDaemonMemoryKb != null)
                    message.maxDaemonMemoryKb = object.maxDaemonMemoryKb >>> 0;
                if (object.remoteDescriptorTimeoutMs != null)
                    message.remoteDescriptorTimeoutMs = object.remoteDescriptorTimeoutMs >>> 0;
                if (object.unwindStateClearPeriodMs != null)
                    message.unwindStateClearPeriodMs = object.unwindStateClearPeriodMs >>> 0;
                if (object.allCpus != null)
                    message.allCpus = Boolean(object.allCpus);
                if (object.samplingFrequency != null)
                    message.samplingFrequency = object.samplingFrequency >>> 0;
                if (object.kernelFrames != null)
                    message.kernelFrames = Boolean(object.kernelFrames);
                if (object.targetPid) {
                    if (!Array.isArray(object.targetPid))
                        throw TypeError(".perfetto.protos.PerfEventConfig.targetPid: array expected");
                    message.targetPid = [];
                    for (var i = 0; i < object.targetPid.length; ++i)
                        message.targetPid[i] = object.targetPid[i] | 0;
                }
                if (object.targetCmdline) {
                    if (!Array.isArray(object.targetCmdline))
                        throw TypeError(".perfetto.protos.PerfEventConfig.targetCmdline: array expected");
                    message.targetCmdline = [];
                    for (var i = 0; i < object.targetCmdline.length; ++i)
                        message.targetCmdline[i] = String(object.targetCmdline[i]);
                }
                if (object.targetInstalledBy) {
                    if (!Array.isArray(object.targetInstalledBy))
                        throw TypeError(".perfetto.protos.PerfEventConfig.targetInstalledBy: array expected");
                    message.targetInstalledBy = [];
                    for (var i = 0; i < object.targetInstalledBy.length; ++i)
                        message.targetInstalledBy[i] = String(object.targetInstalledBy[i]);
                }
                if (object.excludePid) {
                    if (!Array.isArray(object.excludePid))
                        throw TypeError(".perfetto.protos.PerfEventConfig.excludePid: array expected");
                    message.excludePid = [];
                    for (var i = 0; i < object.excludePid.length; ++i)
                        message.excludePid[i] = object.excludePid[i] | 0;
                }
                if (object.excludeCmdline) {
                    if (!Array.isArray(object.excludeCmdline))
                        throw TypeError(".perfetto.protos.PerfEventConfig.excludeCmdline: array expected");
                    message.excludeCmdline = [];
                    for (var i = 0; i < object.excludeCmdline.length; ++i)
                        message.excludeCmdline[i] = String(object.excludeCmdline[i]);
                }
                if (object.additionalCmdlineCount != null)
                    message.additionalCmdlineCount = object.additionalCmdlineCount >>> 0;
                return message;
            };

            /**
             * Creates a plain object from a PerfEventConfig message. Also converts values to other types if specified.
             * @function toObject
             * @memberof perfetto.protos.PerfEventConfig
             * @static
             * @param {perfetto.protos.PerfEventConfig} message PerfEventConfig
             * @param {$protobuf.IConversionOptions} [options] Conversion options
             * @returns {Object.<string,*>} Plain object
             */
            PerfEventConfig.toObject = function toObject(message, options) {
                if (!options)
                    options = {};
                var object = {};
                if (options.arrays || options.defaults) {
                    object.targetPid = [];
                    object.targetCmdline = [];
                    object.excludePid = [];
                    object.excludeCmdline = [];
                    object.targetInstalledBy = [];
                }
                if (options.defaults) {
                    object.allCpus = false;
                    object.samplingFrequency = 0;
                    object.ringBufferPages = 0;
                    object.ringBufferReadPeriodMs = 0;
                    object.remoteDescriptorTimeoutMs = 0;
                    object.unwindStateClearPeriodMs = 0;
                    object.additionalCmdlineCount = 0;
                    object.kernelFrames = false;
                    object.maxDaemonMemoryKb = 0;
                    object.timebase = null;
                    object.callstackSampling = null;
                    if ($util.Long) {
                        var long = new $util.Long(0, 0, true);
                        object.maxEnqueuedFootprintKb = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
                    } else
                        object.maxEnqueuedFootprintKb = options.longs === String ? "0" : 0;
                }
                if (message.allCpus != null && message.hasOwnProperty("allCpus"))
                    object.allCpus = message.allCpus;
                if (message.samplingFrequency != null && message.hasOwnProperty("samplingFrequency"))
                    object.samplingFrequency = message.samplingFrequency;
                if (message.ringBufferPages != null && message.hasOwnProperty("ringBufferPages"))
                    object.ringBufferPages = message.ringBufferPages;
                if (message.targetPid && message.targetPid.length) {
                    object.targetPid = [];
                    for (var j = 0; j < message.targetPid.length; ++j)
                        object.targetPid[j] = message.targetPid[j];
                }
                if (message.targetCmdline && message.targetCmdline.length) {
                    object.targetCmdline = [];
                    for (var j = 0; j < message.targetCmdline.length; ++j)
                        object.targetCmdline[j] = message.targetCmdline[j];
                }
                if (message.excludePid && message.excludePid.length) {
                    object.excludePid = [];
                    for (var j = 0; j < message.excludePid.length; ++j)
                        object.excludePid[j] = message.excludePid[j];
                }
                if (message.excludeCmdline && message.excludeCmdline.length) {
                    object.excludeCmdline = [];
                    for (var j = 0; j < message.excludeCmdline.length; ++j)
                        object.excludeCmdline[j] = message.excludeCmdline[j];
                }
                if (message.ringBufferReadPeriodMs != null && message.hasOwnProperty("ringBufferReadPeriodMs"))
                    object.ringBufferReadPeriodMs = message.ringBufferReadPeriodMs;
                if (message.remoteDescriptorTimeoutMs != null && message.hasOwnProperty("remoteDescriptorTimeoutMs"))
                    object.remoteDescriptorTimeoutMs = message.remoteDescriptorTimeoutMs;
                if (message.unwindStateClearPeriodMs != null && message.hasOwnProperty("unwindStateClearPeriodMs"))
                    object.unwindStateClearPeriodMs = message.unwindStateClearPeriodMs;
                if (message.additionalCmdlineCount != null && message.hasOwnProperty("additionalCmdlineCount"))
                    object.additionalCmdlineCount = message.additionalCmdlineCount;
                if (message.kernelFrames != null && message.hasOwnProperty("kernelFrames"))
                    object.kernelFrames = message.kernelFrames;
                if (message.maxDaemonMemoryKb != null && message.hasOwnProperty("maxDaemonMemoryKb"))
                    object.maxDaemonMemoryKb = message.maxDaemonMemoryKb;
                if (message.timebase != null && message.hasOwnProperty("timebase"))
                    object.timebase = $root.perfetto.protos.PerfEvents.Timebase.toObject(message.timebase, options);
                if (message.callstackSampling != null && message.hasOwnProperty("callstackSampling"))
                    object.callstackSampling = $root.perfetto.protos.PerfEventConfig.CallstackSampling.toObject(message.callstackSampling, options);
                if (message.maxEnqueuedFootprintKb != null && message.hasOwnProperty("maxEnqueuedFootprintKb"))
                    if (typeof message.maxEnqueuedFootprintKb === "number")
                        object.maxEnqueuedFootprintKb = options.longs === String ? String(message.maxEnqueuedFootprintKb) : message.maxEnqueuedFootprintKb;
                    else
                        object.maxEnqueuedFootprintKb = options.longs === String ? $util.Long.prototype.toString.call(message.maxEnqueuedFootprintKb) : options.longs === Number ? new $util.LongBits(message.maxEnqueuedFootprintKb.low >>> 0, message.maxEnqueuedFootprintKb.high >>> 0).toNumber(true) : message.maxEnqueuedFootprintKb;
                if (message.targetInstalledBy && message.targetInstalledBy.length) {
                    object.targetInstalledBy = [];
                    for (var j = 0; j < message.targetInstalledBy.length; ++j)
                        object.targetInstalledBy[j] = message.targetInstalledBy[j];
                }
                return object;
            };

            /**
             * Converts this PerfEventConfig to JSON.
             * @function toJSON
             * @memberof perfetto.protos.PerfEventConfig
             * @instance
             * @returns {Object.<string,*>} JSON object
             */
            PerfEventConfig.prototype.toJSON = function toJSON() {
                return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
            };

            PerfEventConfig.CallstackSampling = (function() {

                /**
                 * Properties of a CallstackSampling.
                 * @memberof perfetto.protos.PerfEventConfig
                 * @interface ICallstackSampling
                 * @property {perfetto.protos.PerfEventConfig.IScope|null} [scope] CallstackSampling scope
                 * @property {boolean|null} [kernelFrames] CallstackSampling kernelFrames
                 */

                /**
                 * Constructs a new CallstackSampling.
                 * @memberof perfetto.protos.PerfEventConfig
                 * @classdesc Represents a CallstackSampling.
                 * @implements ICallstackSampling
                 * @constructor
                 * @param {perfetto.protos.PerfEventConfig.ICallstackSampling=} [properties] Properties to set
                 */
                function CallstackSampling(properties) {
                    if (properties)
                        for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                            if (properties[keys[i]] != null)
                                this[keys[i]] = properties[keys[i]];
                }

                /**
                 * CallstackSampling scope.
                 * @member {perfetto.protos.PerfEventConfig.IScope|null|undefined} scope
                 * @memberof perfetto.protos.PerfEventConfig.CallstackSampling
                 * @instance
                 */
                CallstackSampling.prototype.scope = null;

                /**
                 * CallstackSampling kernelFrames.
                 * @member {boolean} kernelFrames
                 * @memberof perfetto.protos.PerfEventConfig.CallstackSampling
                 * @instance
                 */
                CallstackSampling.prototype.kernelFrames = false;

                /**
                 * Creates a new CallstackSampling instance using the specified properties.
                 * @function create
                 * @memberof perfetto.protos.PerfEventConfig.CallstackSampling
                 * @static
                 * @param {perfetto.protos.PerfEventConfig.ICallstackSampling=} [properties] Properties to set
                 * @returns {perfetto.protos.PerfEventConfig.CallstackSampling} CallstackSampling instance
                 */
                CallstackSampling.create = function create(properties) {
                    return new CallstackSampling(properties);
                };

                /**
                 * Encodes the specified CallstackSampling message. Does not implicitly {@link perfetto.protos.PerfEventConfig.CallstackSampling.verify|verify} messages.
                 * @function encode
                 * @memberof perfetto.protos.PerfEventConfig.CallstackSampling
                 * @static
                 * @param {perfetto.protos.PerfEventConfig.ICallstackSampling} message CallstackSampling message or plain object to encode
                 * @param {$protobuf.Writer} [writer] Writer to encode to
                 * @returns {$protobuf.Writer} Writer
                 */
                CallstackSampling.encode = function encode(message, writer) {
                    if (!writer)
                        writer = $Writer.create();
                    if (message.scope != null && Object.hasOwnProperty.call(message, "scope"))
                        $root.perfetto.protos.PerfEventConfig.Scope.encode(message.scope, writer.uint32(/* id 1, wireType 2 =*/10).fork()).ldelim();
                    if (message.kernelFrames != null && Object.hasOwnProperty.call(message, "kernelFrames"))
                        writer.uint32(/* id 2, wireType 0 =*/16).bool(message.kernelFrames);
                    return writer;
                };

                /**
                 * Encodes the specified CallstackSampling message, length delimited. Does not implicitly {@link perfetto.protos.PerfEventConfig.CallstackSampling.verify|verify} messages.
                 * @function encodeDelimited
                 * @memberof perfetto.protos.PerfEventConfig.CallstackSampling
                 * @static
                 * @param {perfetto.protos.PerfEventConfig.ICallstackSampling} message CallstackSampling message or plain object to encode
                 * @param {$protobuf.Writer} [writer] Writer to encode to
                 * @returns {$protobuf.Writer} Writer
                 */
                CallstackSampling.encodeDelimited = function encodeDelimited(message, writer) {
                    return this.encode(message, writer).ldelim();
                };

                /**
                 * Decodes a CallstackSampling message from the specified reader or buffer.
                 * @function decode
                 * @memberof perfetto.protos.PerfEventConfig.CallstackSampling
                 * @static
                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                 * @param {number} [length] Message length if known beforehand
                 * @returns {perfetto.protos.PerfEventConfig.CallstackSampling} CallstackSampling
                 * @throws {Error} If the payload is not a reader or valid buffer
                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
                 */
                CallstackSampling.decode = function decode(reader, length) {
                    if (!(reader instanceof $Reader))
                        reader = $Reader.create(reader);
                    var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.PerfEventConfig.CallstackSampling();
                    while (reader.pos < end) {
                        var tag = reader.uint32();
                        switch (tag >>> 3) {
                        case 1:
                            message.scope = $root.perfetto.protos.PerfEventConfig.Scope.decode(reader, reader.uint32());
                            break;
                        case 2:
                            message.kernelFrames = reader.bool();
                            break;
                        default:
                            reader.skipType(tag & 7);
                            break;
                        }
                    }
                    return message;
                };

                /**
                 * Decodes a CallstackSampling message from the specified reader or buffer, length delimited.
                 * @function decodeDelimited
                 * @memberof perfetto.protos.PerfEventConfig.CallstackSampling
                 * @static
                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                 * @returns {perfetto.protos.PerfEventConfig.CallstackSampling} CallstackSampling
                 * @throws {Error} If the payload is not a reader or valid buffer
                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
                 */
                CallstackSampling.decodeDelimited = function decodeDelimited(reader) {
                    if (!(reader instanceof $Reader))
                        reader = new $Reader(reader);
                    return this.decode(reader, reader.uint32());
                };

                /**
                 * Verifies a CallstackSampling message.
                 * @function verify
                 * @memberof perfetto.protos.PerfEventConfig.CallstackSampling
                 * @static
                 * @param {Object.<string,*>} message Plain object to verify
                 * @returns {string|null} `null` if valid, otherwise the reason why it is not
                 */
                CallstackSampling.verify = function verify(message) {
                    if (typeof message !== "object" || message === null)
                        return "object expected";
                    if (message.scope != null && message.hasOwnProperty("scope")) {
                        var error = $root.perfetto.protos.PerfEventConfig.Scope.verify(message.scope);
                        if (error)
                            return "scope." + error;
                    }
                    if (message.kernelFrames != null && message.hasOwnProperty("kernelFrames"))
                        if (typeof message.kernelFrames !== "boolean")
                            return "kernelFrames: boolean expected";
                    return null;
                };

                /**
                 * Creates a CallstackSampling message from a plain object. Also converts values to their respective internal types.
                 * @function fromObject
                 * @memberof perfetto.protos.PerfEventConfig.CallstackSampling
                 * @static
                 * @param {Object.<string,*>} object Plain object
                 * @returns {perfetto.protos.PerfEventConfig.CallstackSampling} CallstackSampling
                 */
                CallstackSampling.fromObject = function fromObject(object) {
                    if (object instanceof $root.perfetto.protos.PerfEventConfig.CallstackSampling)
                        return object;
                    var message = new $root.perfetto.protos.PerfEventConfig.CallstackSampling();
                    if (object.scope != null) {
                        if (typeof object.scope !== "object")
                            throw TypeError(".perfetto.protos.PerfEventConfig.CallstackSampling.scope: object expected");
                        message.scope = $root.perfetto.protos.PerfEventConfig.Scope.fromObject(object.scope);
                    }
                    if (object.kernelFrames != null)
                        message.kernelFrames = Boolean(object.kernelFrames);
                    return message;
                };

                /**
                 * Creates a plain object from a CallstackSampling message. Also converts values to other types if specified.
                 * @function toObject
                 * @memberof perfetto.protos.PerfEventConfig.CallstackSampling
                 * @static
                 * @param {perfetto.protos.PerfEventConfig.CallstackSampling} message CallstackSampling
                 * @param {$protobuf.IConversionOptions} [options] Conversion options
                 * @returns {Object.<string,*>} Plain object
                 */
                CallstackSampling.toObject = function toObject(message, options) {
                    if (!options)
                        options = {};
                    var object = {};
                    if (options.defaults) {
                        object.scope = null;
                        object.kernelFrames = false;
                    }
                    if (message.scope != null && message.hasOwnProperty("scope"))
                        object.scope = $root.perfetto.protos.PerfEventConfig.Scope.toObject(message.scope, options);
                    if (message.kernelFrames != null && message.hasOwnProperty("kernelFrames"))
                        object.kernelFrames = message.kernelFrames;
                    return object;
                };

                /**
                 * Converts this CallstackSampling to JSON.
                 * @function toJSON
                 * @memberof perfetto.protos.PerfEventConfig.CallstackSampling
                 * @instance
                 * @returns {Object.<string,*>} JSON object
                 */
                CallstackSampling.prototype.toJSON = function toJSON() {
                    return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
                };

                return CallstackSampling;
            })();

            PerfEventConfig.Scope = (function() {

                /**
                 * Properties of a Scope.
                 * @memberof perfetto.protos.PerfEventConfig
                 * @interface IScope
                 * @property {Array.<number>|null} [targetPid] Scope targetPid
                 * @property {Array.<string>|null} [targetCmdline] Scope targetCmdline
                 * @property {Array.<number>|null} [excludePid] Scope excludePid
                 * @property {Array.<string>|null} [excludeCmdline] Scope excludeCmdline
                 * @property {number|null} [additionalCmdlineCount] Scope additionalCmdlineCount
                 */

                /**
                 * Constructs a new Scope.
                 * @memberof perfetto.protos.PerfEventConfig
                 * @classdesc Represents a Scope.
                 * @implements IScope
                 * @constructor
                 * @param {perfetto.protos.PerfEventConfig.IScope=} [properties] Properties to set
                 */
                function Scope(properties) {
                    this.targetPid = [];
                    this.targetCmdline = [];
                    this.excludePid = [];
                    this.excludeCmdline = [];
                    if (properties)
                        for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                            if (properties[keys[i]] != null)
                                this[keys[i]] = properties[keys[i]];
                }

                /**
                 * Scope targetPid.
                 * @member {Array.<number>} targetPid
                 * @memberof perfetto.protos.PerfEventConfig.Scope
                 * @instance
                 */
                Scope.prototype.targetPid = $util.emptyArray;

                /**
                 * Scope targetCmdline.
                 * @member {Array.<string>} targetCmdline
                 * @memberof perfetto.protos.PerfEventConfig.Scope
                 * @instance
                 */
                Scope.prototype.targetCmdline = $util.emptyArray;

                /**
                 * Scope excludePid.
                 * @member {Array.<number>} excludePid
                 * @memberof perfetto.protos.PerfEventConfig.Scope
                 * @instance
                 */
                Scope.prototype.excludePid = $util.emptyArray;

                /**
                 * Scope excludeCmdline.
                 * @member {Array.<string>} excludeCmdline
                 * @memberof perfetto.protos.PerfEventConfig.Scope
                 * @instance
                 */
                Scope.prototype.excludeCmdline = $util.emptyArray;

                /**
                 * Scope additionalCmdlineCount.
                 * @member {number} additionalCmdlineCount
                 * @memberof perfetto.protos.PerfEventConfig.Scope
                 * @instance
                 */
                Scope.prototype.additionalCmdlineCount = 0;

                /**
                 * Creates a new Scope instance using the specified properties.
                 * @function create
                 * @memberof perfetto.protos.PerfEventConfig.Scope
                 * @static
                 * @param {perfetto.protos.PerfEventConfig.IScope=} [properties] Properties to set
                 * @returns {perfetto.protos.PerfEventConfig.Scope} Scope instance
                 */
                Scope.create = function create(properties) {
                    return new Scope(properties);
                };

                /**
                 * Encodes the specified Scope message. Does not implicitly {@link perfetto.protos.PerfEventConfig.Scope.verify|verify} messages.
                 * @function encode
                 * @memberof perfetto.protos.PerfEventConfig.Scope
                 * @static
                 * @param {perfetto.protos.PerfEventConfig.IScope} message Scope message or plain object to encode
                 * @param {$protobuf.Writer} [writer] Writer to encode to
                 * @returns {$protobuf.Writer} Writer
                 */
                Scope.encode = function encode(message, writer) {
                    if (!writer)
                        writer = $Writer.create();
                    if (message.targetPid != null && message.targetPid.length)
                        for (var i = 0; i < message.targetPid.length; ++i)
                            writer.uint32(/* id 1, wireType 0 =*/8).int32(message.targetPid[i]);
                    if (message.targetCmdline != null && message.targetCmdline.length)
                        for (var i = 0; i < message.targetCmdline.length; ++i)
                            writer.uint32(/* id 2, wireType 2 =*/18).string(message.targetCmdline[i]);
                    if (message.excludePid != null && message.excludePid.length)
                        for (var i = 0; i < message.excludePid.length; ++i)
                            writer.uint32(/* id 3, wireType 0 =*/24).int32(message.excludePid[i]);
                    if (message.excludeCmdline != null && message.excludeCmdline.length)
                        for (var i = 0; i < message.excludeCmdline.length; ++i)
                            writer.uint32(/* id 4, wireType 2 =*/34).string(message.excludeCmdline[i]);
                    if (message.additionalCmdlineCount != null && Object.hasOwnProperty.call(message, "additionalCmdlineCount"))
                        writer.uint32(/* id 5, wireType 0 =*/40).uint32(message.additionalCmdlineCount);
                    return writer;
                };

                /**
                 * Encodes the specified Scope message, length delimited. Does not implicitly {@link perfetto.protos.PerfEventConfig.Scope.verify|verify} messages.
                 * @function encodeDelimited
                 * @memberof perfetto.protos.PerfEventConfig.Scope
                 * @static
                 * @param {perfetto.protos.PerfEventConfig.IScope} message Scope message or plain object to encode
                 * @param {$protobuf.Writer} [writer] Writer to encode to
                 * @returns {$protobuf.Writer} Writer
                 */
                Scope.encodeDelimited = function encodeDelimited(message, writer) {
                    return this.encode(message, writer).ldelim();
                };

                /**
                 * Decodes a Scope message from the specified reader or buffer.
                 * @function decode
                 * @memberof perfetto.protos.PerfEventConfig.Scope
                 * @static
                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                 * @param {number} [length] Message length if known beforehand
                 * @returns {perfetto.protos.PerfEventConfig.Scope} Scope
                 * @throws {Error} If the payload is not a reader or valid buffer
                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
                 */
                Scope.decode = function decode(reader, length) {
                    if (!(reader instanceof $Reader))
                        reader = $Reader.create(reader);
                    var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.PerfEventConfig.Scope();
                    while (reader.pos < end) {
                        var tag = reader.uint32();
                        switch (tag >>> 3) {
                        case 1:
                            if (!(message.targetPid && message.targetPid.length))
                                message.targetPid = [];
                            if ((tag & 7) === 2) {
                                var end2 = reader.uint32() + reader.pos;
                                while (reader.pos < end2)
                                    message.targetPid.push(reader.int32());
                            } else
                                message.targetPid.push(reader.int32());
                            break;
                        case 2:
                            if (!(message.targetCmdline && message.targetCmdline.length))
                                message.targetCmdline = [];
                            message.targetCmdline.push(reader.string());
                            break;
                        case 3:
                            if (!(message.excludePid && message.excludePid.length))
                                message.excludePid = [];
                            if ((tag & 7) === 2) {
                                var end2 = reader.uint32() + reader.pos;
                                while (reader.pos < end2)
                                    message.excludePid.push(reader.int32());
                            } else
                                message.excludePid.push(reader.int32());
                            break;
                        case 4:
                            if (!(message.excludeCmdline && message.excludeCmdline.length))
                                message.excludeCmdline = [];
                            message.excludeCmdline.push(reader.string());
                            break;
                        case 5:
                            message.additionalCmdlineCount = reader.uint32();
                            break;
                        default:
                            reader.skipType(tag & 7);
                            break;
                        }
                    }
                    return message;
                };

                /**
                 * Decodes a Scope message from the specified reader or buffer, length delimited.
                 * @function decodeDelimited
                 * @memberof perfetto.protos.PerfEventConfig.Scope
                 * @static
                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                 * @returns {perfetto.protos.PerfEventConfig.Scope} Scope
                 * @throws {Error} If the payload is not a reader or valid buffer
                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
                 */
                Scope.decodeDelimited = function decodeDelimited(reader) {
                    if (!(reader instanceof $Reader))
                        reader = new $Reader(reader);
                    return this.decode(reader, reader.uint32());
                };

                /**
                 * Verifies a Scope message.
                 * @function verify
                 * @memberof perfetto.protos.PerfEventConfig.Scope
                 * @static
                 * @param {Object.<string,*>} message Plain object to verify
                 * @returns {string|null} `null` if valid, otherwise the reason why it is not
                 */
                Scope.verify = function verify(message) {
                    if (typeof message !== "object" || message === null)
                        return "object expected";
                    if (message.targetPid != null && message.hasOwnProperty("targetPid")) {
                        if (!Array.isArray(message.targetPid))
                            return "targetPid: array expected";
                        for (var i = 0; i < message.targetPid.length; ++i)
                            if (!$util.isInteger(message.targetPid[i]))
                                return "targetPid: integer[] expected";
                    }
                    if (message.targetCmdline != null && message.hasOwnProperty("targetCmdline")) {
                        if (!Array.isArray(message.targetCmdline))
                            return "targetCmdline: array expected";
                        for (var i = 0; i < message.targetCmdline.length; ++i)
                            if (!$util.isString(message.targetCmdline[i]))
                                return "targetCmdline: string[] expected";
                    }
                    if (message.excludePid != null && message.hasOwnProperty("excludePid")) {
                        if (!Array.isArray(message.excludePid))
                            return "excludePid: array expected";
                        for (var i = 0; i < message.excludePid.length; ++i)
                            if (!$util.isInteger(message.excludePid[i]))
                                return "excludePid: integer[] expected";
                    }
                    if (message.excludeCmdline != null && message.hasOwnProperty("excludeCmdline")) {
                        if (!Array.isArray(message.excludeCmdline))
                            return "excludeCmdline: array expected";
                        for (var i = 0; i < message.excludeCmdline.length; ++i)
                            if (!$util.isString(message.excludeCmdline[i]))
                                return "excludeCmdline: string[] expected";
                    }
                    if (message.additionalCmdlineCount != null && message.hasOwnProperty("additionalCmdlineCount"))
                        if (!$util.isInteger(message.additionalCmdlineCount))
                            return "additionalCmdlineCount: integer expected";
                    return null;
                };

                /**
                 * Creates a Scope message from a plain object. Also converts values to their respective internal types.
                 * @function fromObject
                 * @memberof perfetto.protos.PerfEventConfig.Scope
                 * @static
                 * @param {Object.<string,*>} object Plain object
                 * @returns {perfetto.protos.PerfEventConfig.Scope} Scope
                 */
                Scope.fromObject = function fromObject(object) {
                    if (object instanceof $root.perfetto.protos.PerfEventConfig.Scope)
                        return object;
                    var message = new $root.perfetto.protos.PerfEventConfig.Scope();
                    if (object.targetPid) {
                        if (!Array.isArray(object.targetPid))
                            throw TypeError(".perfetto.protos.PerfEventConfig.Scope.targetPid: array expected");
                        message.targetPid = [];
                        for (var i = 0; i < object.targetPid.length; ++i)
                            message.targetPid[i] = object.targetPid[i] | 0;
                    }
                    if (object.targetCmdline) {
                        if (!Array.isArray(object.targetCmdline))
                            throw TypeError(".perfetto.protos.PerfEventConfig.Scope.targetCmdline: array expected");
                        message.targetCmdline = [];
                        for (var i = 0; i < object.targetCmdline.length; ++i)
                            message.targetCmdline[i] = String(object.targetCmdline[i]);
                    }
                    if (object.excludePid) {
                        if (!Array.isArray(object.excludePid))
                            throw TypeError(".perfetto.protos.PerfEventConfig.Scope.excludePid: array expected");
                        message.excludePid = [];
                        for (var i = 0; i < object.excludePid.length; ++i)
                            message.excludePid[i] = object.excludePid[i] | 0;
                    }
                    if (object.excludeCmdline) {
                        if (!Array.isArray(object.excludeCmdline))
                            throw TypeError(".perfetto.protos.PerfEventConfig.Scope.excludeCmdline: array expected");
                        message.excludeCmdline = [];
                        for (var i = 0; i < object.excludeCmdline.length; ++i)
                            message.excludeCmdline[i] = String(object.excludeCmdline[i]);
                    }
                    if (object.additionalCmdlineCount != null)
                        message.additionalCmdlineCount = object.additionalCmdlineCount >>> 0;
                    return message;
                };

                /**
                 * Creates a plain object from a Scope message. Also converts values to other types if specified.
                 * @function toObject
                 * @memberof perfetto.protos.PerfEventConfig.Scope
                 * @static
                 * @param {perfetto.protos.PerfEventConfig.Scope} message Scope
                 * @param {$protobuf.IConversionOptions} [options] Conversion options
                 * @returns {Object.<string,*>} Plain object
                 */
                Scope.toObject = function toObject(message, options) {
                    if (!options)
                        options = {};
                    var object = {};
                    if (options.arrays || options.defaults) {
                        object.targetPid = [];
                        object.targetCmdline = [];
                        object.excludePid = [];
                        object.excludeCmdline = [];
                    }
                    if (options.defaults)
                        object.additionalCmdlineCount = 0;
                    if (message.targetPid && message.targetPid.length) {
                        object.targetPid = [];
                        for (var j = 0; j < message.targetPid.length; ++j)
                            object.targetPid[j] = message.targetPid[j];
                    }
                    if (message.targetCmdline && message.targetCmdline.length) {
                        object.targetCmdline = [];
                        for (var j = 0; j < message.targetCmdline.length; ++j)
                            object.targetCmdline[j] = message.targetCmdline[j];
                    }
                    if (message.excludePid && message.excludePid.length) {
                        object.excludePid = [];
                        for (var j = 0; j < message.excludePid.length; ++j)
                            object.excludePid[j] = message.excludePid[j];
                    }
                    if (message.excludeCmdline && message.excludeCmdline.length) {
                        object.excludeCmdline = [];
                        for (var j = 0; j < message.excludeCmdline.length; ++j)
                            object.excludeCmdline[j] = message.excludeCmdline[j];
                    }
                    if (message.additionalCmdlineCount != null && message.hasOwnProperty("additionalCmdlineCount"))
                        object.additionalCmdlineCount = message.additionalCmdlineCount;
                    return object;
                };

                /**
                 * Converts this Scope to JSON.
                 * @function toJSON
                 * @memberof perfetto.protos.PerfEventConfig.Scope
                 * @instance
                 * @returns {Object.<string,*>} JSON object
                 */
                Scope.prototype.toJSON = function toJSON() {
                    return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
                };

                return Scope;
            })();

            return PerfEventConfig;
        })();

        /**
         * MeminfoCounters enum.
         * @name perfetto.protos.MeminfoCounters
         * @enum {number}
         * @property {number} MEMINFO_UNSPECIFIED=0 MEMINFO_UNSPECIFIED value
         * @property {number} MEMINFO_MEM_TOTAL=1 MEMINFO_MEM_TOTAL value
         * @property {number} MEMINFO_MEM_FREE=2 MEMINFO_MEM_FREE value
         * @property {number} MEMINFO_MEM_AVAILABLE=3 MEMINFO_MEM_AVAILABLE value
         * @property {number} MEMINFO_BUFFERS=4 MEMINFO_BUFFERS value
         * @property {number} MEMINFO_CACHED=5 MEMINFO_CACHED value
         * @property {number} MEMINFO_SWAP_CACHED=6 MEMINFO_SWAP_CACHED value
         * @property {number} MEMINFO_ACTIVE=7 MEMINFO_ACTIVE value
         * @property {number} MEMINFO_INACTIVE=8 MEMINFO_INACTIVE value
         * @property {number} MEMINFO_ACTIVE_ANON=9 MEMINFO_ACTIVE_ANON value
         * @property {number} MEMINFO_INACTIVE_ANON=10 MEMINFO_INACTIVE_ANON value
         * @property {number} MEMINFO_ACTIVE_FILE=11 MEMINFO_ACTIVE_FILE value
         * @property {number} MEMINFO_INACTIVE_FILE=12 MEMINFO_INACTIVE_FILE value
         * @property {number} MEMINFO_UNEVICTABLE=13 MEMINFO_UNEVICTABLE value
         * @property {number} MEMINFO_MLOCKED=14 MEMINFO_MLOCKED value
         * @property {number} MEMINFO_SWAP_TOTAL=15 MEMINFO_SWAP_TOTAL value
         * @property {number} MEMINFO_SWAP_FREE=16 MEMINFO_SWAP_FREE value
         * @property {number} MEMINFO_DIRTY=17 MEMINFO_DIRTY value
         * @property {number} MEMINFO_WRITEBACK=18 MEMINFO_WRITEBACK value
         * @property {number} MEMINFO_ANON_PAGES=19 MEMINFO_ANON_PAGES value
         * @property {number} MEMINFO_MAPPED=20 MEMINFO_MAPPED value
         * @property {number} MEMINFO_SHMEM=21 MEMINFO_SHMEM value
         * @property {number} MEMINFO_SLAB=22 MEMINFO_SLAB value
         * @property {number} MEMINFO_SLAB_RECLAIMABLE=23 MEMINFO_SLAB_RECLAIMABLE value
         * @property {number} MEMINFO_SLAB_UNRECLAIMABLE=24 MEMINFO_SLAB_UNRECLAIMABLE value
         * @property {number} MEMINFO_KERNEL_STACK=25 MEMINFO_KERNEL_STACK value
         * @property {number} MEMINFO_PAGE_TABLES=26 MEMINFO_PAGE_TABLES value
         * @property {number} MEMINFO_COMMIT_LIMIT=27 MEMINFO_COMMIT_LIMIT value
         * @property {number} MEMINFO_COMMITED_AS=28 MEMINFO_COMMITED_AS value
         * @property {number} MEMINFO_VMALLOC_TOTAL=29 MEMINFO_VMALLOC_TOTAL value
         * @property {number} MEMINFO_VMALLOC_USED=30 MEMINFO_VMALLOC_USED value
         * @property {number} MEMINFO_VMALLOC_CHUNK=31 MEMINFO_VMALLOC_CHUNK value
         * @property {number} MEMINFO_CMA_TOTAL=32 MEMINFO_CMA_TOTAL value
         * @property {number} MEMINFO_CMA_FREE=33 MEMINFO_CMA_FREE value
         */
        protos.MeminfoCounters = (function() {
            var valuesById = {}, values = Object.create(valuesById);
            values[valuesById[0] = "MEMINFO_UNSPECIFIED"] = 0;
            values[valuesById[1] = "MEMINFO_MEM_TOTAL"] = 1;
            values[valuesById[2] = "MEMINFO_MEM_FREE"] = 2;
            values[valuesById[3] = "MEMINFO_MEM_AVAILABLE"] = 3;
            values[valuesById[4] = "MEMINFO_BUFFERS"] = 4;
            values[valuesById[5] = "MEMINFO_CACHED"] = 5;
            values[valuesById[6] = "MEMINFO_SWAP_CACHED"] = 6;
            values[valuesById[7] = "MEMINFO_ACTIVE"] = 7;
            values[valuesById[8] = "MEMINFO_INACTIVE"] = 8;
            values[valuesById[9] = "MEMINFO_ACTIVE_ANON"] = 9;
            values[valuesById[10] = "MEMINFO_INACTIVE_ANON"] = 10;
            values[valuesById[11] = "MEMINFO_ACTIVE_FILE"] = 11;
            values[valuesById[12] = "MEMINFO_INACTIVE_FILE"] = 12;
            values[valuesById[13] = "MEMINFO_UNEVICTABLE"] = 13;
            values[valuesById[14] = "MEMINFO_MLOCKED"] = 14;
            values[valuesById[15] = "MEMINFO_SWAP_TOTAL"] = 15;
            values[valuesById[16] = "MEMINFO_SWAP_FREE"] = 16;
            values[valuesById[17] = "MEMINFO_DIRTY"] = 17;
            values[valuesById[18] = "MEMINFO_WRITEBACK"] = 18;
            values[valuesById[19] = "MEMINFO_ANON_PAGES"] = 19;
            values[valuesById[20] = "MEMINFO_MAPPED"] = 20;
            values[valuesById[21] = "MEMINFO_SHMEM"] = 21;
            values[valuesById[22] = "MEMINFO_SLAB"] = 22;
            values[valuesById[23] = "MEMINFO_SLAB_RECLAIMABLE"] = 23;
            values[valuesById[24] = "MEMINFO_SLAB_UNRECLAIMABLE"] = 24;
            values[valuesById[25] = "MEMINFO_KERNEL_STACK"] = 25;
            values[valuesById[26] = "MEMINFO_PAGE_TABLES"] = 26;
            values[valuesById[27] = "MEMINFO_COMMIT_LIMIT"] = 27;
            values[valuesById[28] = "MEMINFO_COMMITED_AS"] = 28;
            values[valuesById[29] = "MEMINFO_VMALLOC_TOTAL"] = 29;
            values[valuesById[30] = "MEMINFO_VMALLOC_USED"] = 30;
            values[valuesById[31] = "MEMINFO_VMALLOC_CHUNK"] = 31;
            values[valuesById[32] = "MEMINFO_CMA_TOTAL"] = 32;
            values[valuesById[33] = "MEMINFO_CMA_FREE"] = 33;
            return values;
        })();

        /**
         * VmstatCounters enum.
         * @name perfetto.protos.VmstatCounters
         * @enum {number}
         * @property {number} VMSTAT_UNSPECIFIED=0 VMSTAT_UNSPECIFIED value
         * @property {number} VMSTAT_NR_FREE_PAGES=1 VMSTAT_NR_FREE_PAGES value
         * @property {number} VMSTAT_NR_ALLOC_BATCH=2 VMSTAT_NR_ALLOC_BATCH value
         * @property {number} VMSTAT_NR_INACTIVE_ANON=3 VMSTAT_NR_INACTIVE_ANON value
         * @property {number} VMSTAT_NR_ACTIVE_ANON=4 VMSTAT_NR_ACTIVE_ANON value
         * @property {number} VMSTAT_NR_INACTIVE_FILE=5 VMSTAT_NR_INACTIVE_FILE value
         * @property {number} VMSTAT_NR_ACTIVE_FILE=6 VMSTAT_NR_ACTIVE_FILE value
         * @property {number} VMSTAT_NR_UNEVICTABLE=7 VMSTAT_NR_UNEVICTABLE value
         * @property {number} VMSTAT_NR_MLOCK=8 VMSTAT_NR_MLOCK value
         * @property {number} VMSTAT_NR_ANON_PAGES=9 VMSTAT_NR_ANON_PAGES value
         * @property {number} VMSTAT_NR_MAPPED=10 VMSTAT_NR_MAPPED value
         * @property {number} VMSTAT_NR_FILE_PAGES=11 VMSTAT_NR_FILE_PAGES value
         * @property {number} VMSTAT_NR_DIRTY=12 VMSTAT_NR_DIRTY value
         * @property {number} VMSTAT_NR_WRITEBACK=13 VMSTAT_NR_WRITEBACK value
         * @property {number} VMSTAT_NR_SLAB_RECLAIMABLE=14 VMSTAT_NR_SLAB_RECLAIMABLE value
         * @property {number} VMSTAT_NR_SLAB_UNRECLAIMABLE=15 VMSTAT_NR_SLAB_UNRECLAIMABLE value
         * @property {number} VMSTAT_NR_PAGE_TABLE_PAGES=16 VMSTAT_NR_PAGE_TABLE_PAGES value
         * @property {number} VMSTAT_NR_KERNEL_STACK=17 VMSTAT_NR_KERNEL_STACK value
         * @property {number} VMSTAT_NR_OVERHEAD=18 VMSTAT_NR_OVERHEAD value
         * @property {number} VMSTAT_NR_UNSTABLE=19 VMSTAT_NR_UNSTABLE value
         * @property {number} VMSTAT_NR_BOUNCE=20 VMSTAT_NR_BOUNCE value
         * @property {number} VMSTAT_NR_VMSCAN_WRITE=21 VMSTAT_NR_VMSCAN_WRITE value
         * @property {number} VMSTAT_NR_VMSCAN_IMMEDIATE_RECLAIM=22 VMSTAT_NR_VMSCAN_IMMEDIATE_RECLAIM value
         * @property {number} VMSTAT_NR_WRITEBACK_TEMP=23 VMSTAT_NR_WRITEBACK_TEMP value
         * @property {number} VMSTAT_NR_ISOLATED_ANON=24 VMSTAT_NR_ISOLATED_ANON value
         * @property {number} VMSTAT_NR_ISOLATED_FILE=25 VMSTAT_NR_ISOLATED_FILE value
         * @property {number} VMSTAT_NR_SHMEM=26 VMSTAT_NR_SHMEM value
         * @property {number} VMSTAT_NR_DIRTIED=27 VMSTAT_NR_DIRTIED value
         * @property {number} VMSTAT_NR_WRITTEN=28 VMSTAT_NR_WRITTEN value
         * @property {number} VMSTAT_NR_PAGES_SCANNED=29 VMSTAT_NR_PAGES_SCANNED value
         * @property {number} VMSTAT_WORKINGSET_REFAULT=30 VMSTAT_WORKINGSET_REFAULT value
         * @property {number} VMSTAT_WORKINGSET_ACTIVATE=31 VMSTAT_WORKINGSET_ACTIVATE value
         * @property {number} VMSTAT_WORKINGSET_NODERECLAIM=32 VMSTAT_WORKINGSET_NODERECLAIM value
         * @property {number} VMSTAT_NR_ANON_TRANSPARENT_HUGEPAGES=33 VMSTAT_NR_ANON_TRANSPARENT_HUGEPAGES value
         * @property {number} VMSTAT_NR_FREE_CMA=34 VMSTAT_NR_FREE_CMA value
         * @property {number} VMSTAT_NR_SWAPCACHE=35 VMSTAT_NR_SWAPCACHE value
         * @property {number} VMSTAT_NR_DIRTY_THRESHOLD=36 VMSTAT_NR_DIRTY_THRESHOLD value
         * @property {number} VMSTAT_NR_DIRTY_BACKGROUND_THRESHOLD=37 VMSTAT_NR_DIRTY_BACKGROUND_THRESHOLD value
         * @property {number} VMSTAT_PGPGIN=38 VMSTAT_PGPGIN value
         * @property {number} VMSTAT_PGPGOUT=39 VMSTAT_PGPGOUT value
         * @property {number} VMSTAT_PGPGOUTCLEAN=40 VMSTAT_PGPGOUTCLEAN value
         * @property {number} VMSTAT_PSWPIN=41 VMSTAT_PSWPIN value
         * @property {number} VMSTAT_PSWPOUT=42 VMSTAT_PSWPOUT value
         * @property {number} VMSTAT_PGALLOC_DMA=43 VMSTAT_PGALLOC_DMA value
         * @property {number} VMSTAT_PGALLOC_NORMAL=44 VMSTAT_PGALLOC_NORMAL value
         * @property {number} VMSTAT_PGALLOC_MOVABLE=45 VMSTAT_PGALLOC_MOVABLE value
         * @property {number} VMSTAT_PGFREE=46 VMSTAT_PGFREE value
         * @property {number} VMSTAT_PGACTIVATE=47 VMSTAT_PGACTIVATE value
         * @property {number} VMSTAT_PGDEACTIVATE=48 VMSTAT_PGDEACTIVATE value
         * @property {number} VMSTAT_PGFAULT=49 VMSTAT_PGFAULT value
         * @property {number} VMSTAT_PGMAJFAULT=50 VMSTAT_PGMAJFAULT value
         * @property {number} VMSTAT_PGREFILL_DMA=51 VMSTAT_PGREFILL_DMA value
         * @property {number} VMSTAT_PGREFILL_NORMAL=52 VMSTAT_PGREFILL_NORMAL value
         * @property {number} VMSTAT_PGREFILL_MOVABLE=53 VMSTAT_PGREFILL_MOVABLE value
         * @property {number} VMSTAT_PGSTEAL_KSWAPD_DMA=54 VMSTAT_PGSTEAL_KSWAPD_DMA value
         * @property {number} VMSTAT_PGSTEAL_KSWAPD_NORMAL=55 VMSTAT_PGSTEAL_KSWAPD_NORMAL value
         * @property {number} VMSTAT_PGSTEAL_KSWAPD_MOVABLE=56 VMSTAT_PGSTEAL_KSWAPD_MOVABLE value
         * @property {number} VMSTAT_PGSTEAL_DIRECT_DMA=57 VMSTAT_PGSTEAL_DIRECT_DMA value
         * @property {number} VMSTAT_PGSTEAL_DIRECT_NORMAL=58 VMSTAT_PGSTEAL_DIRECT_NORMAL value
         * @property {number} VMSTAT_PGSTEAL_DIRECT_MOVABLE=59 VMSTAT_PGSTEAL_DIRECT_MOVABLE value
         * @property {number} VMSTAT_PGSCAN_KSWAPD_DMA=60 VMSTAT_PGSCAN_KSWAPD_DMA value
         * @property {number} VMSTAT_PGSCAN_KSWAPD_NORMAL=61 VMSTAT_PGSCAN_KSWAPD_NORMAL value
         * @property {number} VMSTAT_PGSCAN_KSWAPD_MOVABLE=62 VMSTAT_PGSCAN_KSWAPD_MOVABLE value
         * @property {number} VMSTAT_PGSCAN_DIRECT_DMA=63 VMSTAT_PGSCAN_DIRECT_DMA value
         * @property {number} VMSTAT_PGSCAN_DIRECT_NORMAL=64 VMSTAT_PGSCAN_DIRECT_NORMAL value
         * @property {number} VMSTAT_PGSCAN_DIRECT_MOVABLE=65 VMSTAT_PGSCAN_DIRECT_MOVABLE value
         * @property {number} VMSTAT_PGSCAN_DIRECT_THROTTLE=66 VMSTAT_PGSCAN_DIRECT_THROTTLE value
         * @property {number} VMSTAT_PGINODESTEAL=67 VMSTAT_PGINODESTEAL value
         * @property {number} VMSTAT_SLABS_SCANNED=68 VMSTAT_SLABS_SCANNED value
         * @property {number} VMSTAT_KSWAPD_INODESTEAL=69 VMSTAT_KSWAPD_INODESTEAL value
         * @property {number} VMSTAT_KSWAPD_LOW_WMARK_HIT_QUICKLY=70 VMSTAT_KSWAPD_LOW_WMARK_HIT_QUICKLY value
         * @property {number} VMSTAT_KSWAPD_HIGH_WMARK_HIT_QUICKLY=71 VMSTAT_KSWAPD_HIGH_WMARK_HIT_QUICKLY value
         * @property {number} VMSTAT_PAGEOUTRUN=72 VMSTAT_PAGEOUTRUN value
         * @property {number} VMSTAT_ALLOCSTALL=73 VMSTAT_ALLOCSTALL value
         * @property {number} VMSTAT_PGROTATED=74 VMSTAT_PGROTATED value
         * @property {number} VMSTAT_DROP_PAGECACHE=75 VMSTAT_DROP_PAGECACHE value
         * @property {number} VMSTAT_DROP_SLAB=76 VMSTAT_DROP_SLAB value
         * @property {number} VMSTAT_PGMIGRATE_SUCCESS=77 VMSTAT_PGMIGRATE_SUCCESS value
         * @property {number} VMSTAT_PGMIGRATE_FAIL=78 VMSTAT_PGMIGRATE_FAIL value
         * @property {number} VMSTAT_COMPACT_MIGRATE_SCANNED=79 VMSTAT_COMPACT_MIGRATE_SCANNED value
         * @property {number} VMSTAT_COMPACT_FREE_SCANNED=80 VMSTAT_COMPACT_FREE_SCANNED value
         * @property {number} VMSTAT_COMPACT_ISOLATED=81 VMSTAT_COMPACT_ISOLATED value
         * @property {number} VMSTAT_COMPACT_STALL=82 VMSTAT_COMPACT_STALL value
         * @property {number} VMSTAT_COMPACT_FAIL=83 VMSTAT_COMPACT_FAIL value
         * @property {number} VMSTAT_COMPACT_SUCCESS=84 VMSTAT_COMPACT_SUCCESS value
         * @property {number} VMSTAT_COMPACT_DAEMON_WAKE=85 VMSTAT_COMPACT_DAEMON_WAKE value
         * @property {number} VMSTAT_UNEVICTABLE_PGS_CULLED=86 VMSTAT_UNEVICTABLE_PGS_CULLED value
         * @property {number} VMSTAT_UNEVICTABLE_PGS_SCANNED=87 VMSTAT_UNEVICTABLE_PGS_SCANNED value
         * @property {number} VMSTAT_UNEVICTABLE_PGS_RESCUED=88 VMSTAT_UNEVICTABLE_PGS_RESCUED value
         * @property {number} VMSTAT_UNEVICTABLE_PGS_MLOCKED=89 VMSTAT_UNEVICTABLE_PGS_MLOCKED value
         * @property {number} VMSTAT_UNEVICTABLE_PGS_MUNLOCKED=90 VMSTAT_UNEVICTABLE_PGS_MUNLOCKED value
         * @property {number} VMSTAT_UNEVICTABLE_PGS_CLEARED=91 VMSTAT_UNEVICTABLE_PGS_CLEARED value
         * @property {number} VMSTAT_UNEVICTABLE_PGS_STRANDED=92 VMSTAT_UNEVICTABLE_PGS_STRANDED value
         * @property {number} VMSTAT_NR_ZSPAGES=93 VMSTAT_NR_ZSPAGES value
         * @property {number} VMSTAT_NR_ION_HEAP=94 VMSTAT_NR_ION_HEAP value
         * @property {number} VMSTAT_NR_GPU_HEAP=95 VMSTAT_NR_GPU_HEAP value
         * @property {number} VMSTAT_ALLOCSTALL_DMA=96 VMSTAT_ALLOCSTALL_DMA value
         * @property {number} VMSTAT_ALLOCSTALL_MOVABLE=97 VMSTAT_ALLOCSTALL_MOVABLE value
         * @property {number} VMSTAT_ALLOCSTALL_NORMAL=98 VMSTAT_ALLOCSTALL_NORMAL value
         * @property {number} VMSTAT_COMPACT_DAEMON_FREE_SCANNED=99 VMSTAT_COMPACT_DAEMON_FREE_SCANNED value
         * @property {number} VMSTAT_COMPACT_DAEMON_MIGRATE_SCANNED=100 VMSTAT_COMPACT_DAEMON_MIGRATE_SCANNED value
         * @property {number} VMSTAT_NR_FASTRPC=101 VMSTAT_NR_FASTRPC value
         * @property {number} VMSTAT_NR_INDIRECTLY_RECLAIMABLE=102 VMSTAT_NR_INDIRECTLY_RECLAIMABLE value
         * @property {number} VMSTAT_NR_ION_HEAP_POOL=103 VMSTAT_NR_ION_HEAP_POOL value
         * @property {number} VMSTAT_NR_KERNEL_MISC_RECLAIMABLE=104 VMSTAT_NR_KERNEL_MISC_RECLAIMABLE value
         * @property {number} VMSTAT_NR_SHADOW_CALL_STACK_BYTES=105 VMSTAT_NR_SHADOW_CALL_STACK_BYTES value
         * @property {number} VMSTAT_NR_SHMEM_HUGEPAGES=106 VMSTAT_NR_SHMEM_HUGEPAGES value
         * @property {number} VMSTAT_NR_SHMEM_PMDMAPPED=107 VMSTAT_NR_SHMEM_PMDMAPPED value
         * @property {number} VMSTAT_NR_UNRECLAIMABLE_PAGES=108 VMSTAT_NR_UNRECLAIMABLE_PAGES value
         * @property {number} VMSTAT_NR_ZONE_ACTIVE_ANON=109 VMSTAT_NR_ZONE_ACTIVE_ANON value
         * @property {number} VMSTAT_NR_ZONE_ACTIVE_FILE=110 VMSTAT_NR_ZONE_ACTIVE_FILE value
         * @property {number} VMSTAT_NR_ZONE_INACTIVE_ANON=111 VMSTAT_NR_ZONE_INACTIVE_ANON value
         * @property {number} VMSTAT_NR_ZONE_INACTIVE_FILE=112 VMSTAT_NR_ZONE_INACTIVE_FILE value
         * @property {number} VMSTAT_NR_ZONE_UNEVICTABLE=113 VMSTAT_NR_ZONE_UNEVICTABLE value
         * @property {number} VMSTAT_NR_ZONE_WRITE_PENDING=114 VMSTAT_NR_ZONE_WRITE_PENDING value
         * @property {number} VMSTAT_OOM_KILL=115 VMSTAT_OOM_KILL value
         * @property {number} VMSTAT_PGLAZYFREE=116 VMSTAT_PGLAZYFREE value
         * @property {number} VMSTAT_PGLAZYFREED=117 VMSTAT_PGLAZYFREED value
         * @property {number} VMSTAT_PGREFILL=118 VMSTAT_PGREFILL value
         * @property {number} VMSTAT_PGSCAN_DIRECT=119 VMSTAT_PGSCAN_DIRECT value
         * @property {number} VMSTAT_PGSCAN_KSWAPD=120 VMSTAT_PGSCAN_KSWAPD value
         * @property {number} VMSTAT_PGSKIP_DMA=121 VMSTAT_PGSKIP_DMA value
         * @property {number} VMSTAT_PGSKIP_MOVABLE=122 VMSTAT_PGSKIP_MOVABLE value
         * @property {number} VMSTAT_PGSKIP_NORMAL=123 VMSTAT_PGSKIP_NORMAL value
         * @property {number} VMSTAT_PGSTEAL_DIRECT=124 VMSTAT_PGSTEAL_DIRECT value
         * @property {number} VMSTAT_PGSTEAL_KSWAPD=125 VMSTAT_PGSTEAL_KSWAPD value
         * @property {number} VMSTAT_SWAP_RA=126 VMSTAT_SWAP_RA value
         * @property {number} VMSTAT_SWAP_RA_HIT=127 VMSTAT_SWAP_RA_HIT value
         * @property {number} VMSTAT_WORKINGSET_RESTORE=128 VMSTAT_WORKINGSET_RESTORE value
         */
        protos.VmstatCounters = (function() {
            var valuesById = {}, values = Object.create(valuesById);
            values[valuesById[0] = "VMSTAT_UNSPECIFIED"] = 0;
            values[valuesById[1] = "VMSTAT_NR_FREE_PAGES"] = 1;
            values[valuesById[2] = "VMSTAT_NR_ALLOC_BATCH"] = 2;
            values[valuesById[3] = "VMSTAT_NR_INACTIVE_ANON"] = 3;
            values[valuesById[4] = "VMSTAT_NR_ACTIVE_ANON"] = 4;
            values[valuesById[5] = "VMSTAT_NR_INACTIVE_FILE"] = 5;
            values[valuesById[6] = "VMSTAT_NR_ACTIVE_FILE"] = 6;
            values[valuesById[7] = "VMSTAT_NR_UNEVICTABLE"] = 7;
            values[valuesById[8] = "VMSTAT_NR_MLOCK"] = 8;
            values[valuesById[9] = "VMSTAT_NR_ANON_PAGES"] = 9;
            values[valuesById[10] = "VMSTAT_NR_MAPPED"] = 10;
            values[valuesById[11] = "VMSTAT_NR_FILE_PAGES"] = 11;
            values[valuesById[12] = "VMSTAT_NR_DIRTY"] = 12;
            values[valuesById[13] = "VMSTAT_NR_WRITEBACK"] = 13;
            values[valuesById[14] = "VMSTAT_NR_SLAB_RECLAIMABLE"] = 14;
            values[valuesById[15] = "VMSTAT_NR_SLAB_UNRECLAIMABLE"] = 15;
            values[valuesById[16] = "VMSTAT_NR_PAGE_TABLE_PAGES"] = 16;
            values[valuesById[17] = "VMSTAT_NR_KERNEL_STACK"] = 17;
            values[valuesById[18] = "VMSTAT_NR_OVERHEAD"] = 18;
            values[valuesById[19] = "VMSTAT_NR_UNSTABLE"] = 19;
            values[valuesById[20] = "VMSTAT_NR_BOUNCE"] = 20;
            values[valuesById[21] = "VMSTAT_NR_VMSCAN_WRITE"] = 21;
            values[valuesById[22] = "VMSTAT_NR_VMSCAN_IMMEDIATE_RECLAIM"] = 22;
            values[valuesById[23] = "VMSTAT_NR_WRITEBACK_TEMP"] = 23;
            values[valuesById[24] = "VMSTAT_NR_ISOLATED_ANON"] = 24;
            values[valuesById[25] = "VMSTAT_NR_ISOLATED_FILE"] = 25;
            values[valuesById[26] = "VMSTAT_NR_SHMEM"] = 26;
            values[valuesById[27] = "VMSTAT_NR_DIRTIED"] = 27;
            values[valuesById[28] = "VMSTAT_NR_WRITTEN"] = 28;
            values[valuesById[29] = "VMSTAT_NR_PAGES_SCANNED"] = 29;
            values[valuesById[30] = "VMSTAT_WORKINGSET_REFAULT"] = 30;
            values[valuesById[31] = "VMSTAT_WORKINGSET_ACTIVATE"] = 31;
            values[valuesById[32] = "VMSTAT_WORKINGSET_NODERECLAIM"] = 32;
            values[valuesById[33] = "VMSTAT_NR_ANON_TRANSPARENT_HUGEPAGES"] = 33;
            values[valuesById[34] = "VMSTAT_NR_FREE_CMA"] = 34;
            values[valuesById[35] = "VMSTAT_NR_SWAPCACHE"] = 35;
            values[valuesById[36] = "VMSTAT_NR_DIRTY_THRESHOLD"] = 36;
            values[valuesById[37] = "VMSTAT_NR_DIRTY_BACKGROUND_THRESHOLD"] = 37;
            values[valuesById[38] = "VMSTAT_PGPGIN"] = 38;
            values[valuesById[39] = "VMSTAT_PGPGOUT"] = 39;
            values[valuesById[40] = "VMSTAT_PGPGOUTCLEAN"] = 40;
            values[valuesById[41] = "VMSTAT_PSWPIN"] = 41;
            values[valuesById[42] = "VMSTAT_PSWPOUT"] = 42;
            values[valuesById[43] = "VMSTAT_PGALLOC_DMA"] = 43;
            values[valuesById[44] = "VMSTAT_PGALLOC_NORMAL"] = 44;
            values[valuesById[45] = "VMSTAT_PGALLOC_MOVABLE"] = 45;
            values[valuesById[46] = "VMSTAT_PGFREE"] = 46;
            values[valuesById[47] = "VMSTAT_PGACTIVATE"] = 47;
            values[valuesById[48] = "VMSTAT_PGDEACTIVATE"] = 48;
            values[valuesById[49] = "VMSTAT_PGFAULT"] = 49;
            values[valuesById[50] = "VMSTAT_PGMAJFAULT"] = 50;
            values[valuesById[51] = "VMSTAT_PGREFILL_DMA"] = 51;
            values[valuesById[52] = "VMSTAT_PGREFILL_NORMAL"] = 52;
            values[valuesById[53] = "VMSTAT_PGREFILL_MOVABLE"] = 53;
            values[valuesById[54] = "VMSTAT_PGSTEAL_KSWAPD_DMA"] = 54;
            values[valuesById[55] = "VMSTAT_PGSTEAL_KSWAPD_NORMAL"] = 55;
            values[valuesById[56] = "VMSTAT_PGSTEAL_KSWAPD_MOVABLE"] = 56;
            values[valuesById[57] = "VMSTAT_PGSTEAL_DIRECT_DMA"] = 57;
            values[valuesById[58] = "VMSTAT_PGSTEAL_DIRECT_NORMAL"] = 58;
            values[valuesById[59] = "VMSTAT_PGSTEAL_DIRECT_MOVABLE"] = 59;
            values[valuesById[60] = "VMSTAT_PGSCAN_KSWAPD_DMA"] = 60;
            values[valuesById[61] = "VMSTAT_PGSCAN_KSWAPD_NORMAL"] = 61;
            values[valuesById[62] = "VMSTAT_PGSCAN_KSWAPD_MOVABLE"] = 62;
            values[valuesById[63] = "VMSTAT_PGSCAN_DIRECT_DMA"] = 63;
            values[valuesById[64] = "VMSTAT_PGSCAN_DIRECT_NORMAL"] = 64;
            values[valuesById[65] = "VMSTAT_PGSCAN_DIRECT_MOVABLE"] = 65;
            values[valuesById[66] = "VMSTAT_PGSCAN_DIRECT_THROTTLE"] = 66;
            values[valuesById[67] = "VMSTAT_PGINODESTEAL"] = 67;
            values[valuesById[68] = "VMSTAT_SLABS_SCANNED"] = 68;
            values[valuesById[69] = "VMSTAT_KSWAPD_INODESTEAL"] = 69;
            values[valuesById[70] = "VMSTAT_KSWAPD_LOW_WMARK_HIT_QUICKLY"] = 70;
            values[valuesById[71] = "VMSTAT_KSWAPD_HIGH_WMARK_HIT_QUICKLY"] = 71;
            values[valuesById[72] = "VMSTAT_PAGEOUTRUN"] = 72;
            values[valuesById[73] = "VMSTAT_ALLOCSTALL"] = 73;
            values[valuesById[74] = "VMSTAT_PGROTATED"] = 74;
            values[valuesById[75] = "VMSTAT_DROP_PAGECACHE"] = 75;
            values[valuesById[76] = "VMSTAT_DROP_SLAB"] = 76;
            values[valuesById[77] = "VMSTAT_PGMIGRATE_SUCCESS"] = 77;
            values[valuesById[78] = "VMSTAT_PGMIGRATE_FAIL"] = 78;
            values[valuesById[79] = "VMSTAT_COMPACT_MIGRATE_SCANNED"] = 79;
            values[valuesById[80] = "VMSTAT_COMPACT_FREE_SCANNED"] = 80;
            values[valuesById[81] = "VMSTAT_COMPACT_ISOLATED"] = 81;
            values[valuesById[82] = "VMSTAT_COMPACT_STALL"] = 82;
            values[valuesById[83] = "VMSTAT_COMPACT_FAIL"] = 83;
            values[valuesById[84] = "VMSTAT_COMPACT_SUCCESS"] = 84;
            values[valuesById[85] = "VMSTAT_COMPACT_DAEMON_WAKE"] = 85;
            values[valuesById[86] = "VMSTAT_UNEVICTABLE_PGS_CULLED"] = 86;
            values[valuesById[87] = "VMSTAT_UNEVICTABLE_PGS_SCANNED"] = 87;
            values[valuesById[88] = "VMSTAT_UNEVICTABLE_PGS_RESCUED"] = 88;
            values[valuesById[89] = "VMSTAT_UNEVICTABLE_PGS_MLOCKED"] = 89;
            values[valuesById[90] = "VMSTAT_UNEVICTABLE_PGS_MUNLOCKED"] = 90;
            values[valuesById[91] = "VMSTAT_UNEVICTABLE_PGS_CLEARED"] = 91;
            values[valuesById[92] = "VMSTAT_UNEVICTABLE_PGS_STRANDED"] = 92;
            values[valuesById[93] = "VMSTAT_NR_ZSPAGES"] = 93;
            values[valuesById[94] = "VMSTAT_NR_ION_HEAP"] = 94;
            values[valuesById[95] = "VMSTAT_NR_GPU_HEAP"] = 95;
            values[valuesById[96] = "VMSTAT_ALLOCSTALL_DMA"] = 96;
            values[valuesById[97] = "VMSTAT_ALLOCSTALL_MOVABLE"] = 97;
            values[valuesById[98] = "VMSTAT_ALLOCSTALL_NORMAL"] = 98;
            values[valuesById[99] = "VMSTAT_COMPACT_DAEMON_FREE_SCANNED"] = 99;
            values[valuesById[100] = "VMSTAT_COMPACT_DAEMON_MIGRATE_SCANNED"] = 100;
            values[valuesById[101] = "VMSTAT_NR_FASTRPC"] = 101;
            values[valuesById[102] = "VMSTAT_NR_INDIRECTLY_RECLAIMABLE"] = 102;
            values[valuesById[103] = "VMSTAT_NR_ION_HEAP_POOL"] = 103;
            values[valuesById[104] = "VMSTAT_NR_KERNEL_MISC_RECLAIMABLE"] = 104;
            values[valuesById[105] = "VMSTAT_NR_SHADOW_CALL_STACK_BYTES"] = 105;
            values[valuesById[106] = "VMSTAT_NR_SHMEM_HUGEPAGES"] = 106;
            values[valuesById[107] = "VMSTAT_NR_SHMEM_PMDMAPPED"] = 107;
            values[valuesById[108] = "VMSTAT_NR_UNRECLAIMABLE_PAGES"] = 108;
            values[valuesById[109] = "VMSTAT_NR_ZONE_ACTIVE_ANON"] = 109;
            values[valuesById[110] = "VMSTAT_NR_ZONE_ACTIVE_FILE"] = 110;
            values[valuesById[111] = "VMSTAT_NR_ZONE_INACTIVE_ANON"] = 111;
            values[valuesById[112] = "VMSTAT_NR_ZONE_INACTIVE_FILE"] = 112;
            values[valuesById[113] = "VMSTAT_NR_ZONE_UNEVICTABLE"] = 113;
            values[valuesById[114] = "VMSTAT_NR_ZONE_WRITE_PENDING"] = 114;
            values[valuesById[115] = "VMSTAT_OOM_KILL"] = 115;
            values[valuesById[116] = "VMSTAT_PGLAZYFREE"] = 116;
            values[valuesById[117] = "VMSTAT_PGLAZYFREED"] = 117;
            values[valuesById[118] = "VMSTAT_PGREFILL"] = 118;
            values[valuesById[119] = "VMSTAT_PGSCAN_DIRECT"] = 119;
            values[valuesById[120] = "VMSTAT_PGSCAN_KSWAPD"] = 120;
            values[valuesById[121] = "VMSTAT_PGSKIP_DMA"] = 121;
            values[valuesById[122] = "VMSTAT_PGSKIP_MOVABLE"] = 122;
            values[valuesById[123] = "VMSTAT_PGSKIP_NORMAL"] = 123;
            values[valuesById[124] = "VMSTAT_PGSTEAL_DIRECT"] = 124;
            values[valuesById[125] = "VMSTAT_PGSTEAL_KSWAPD"] = 125;
            values[valuesById[126] = "VMSTAT_SWAP_RA"] = 126;
            values[valuesById[127] = "VMSTAT_SWAP_RA_HIT"] = 127;
            values[valuesById[128] = "VMSTAT_WORKINGSET_RESTORE"] = 128;
            return values;
        })();

        protos.SysStatsConfig = (function() {

            /**
             * Properties of a SysStatsConfig.
             * @memberof perfetto.protos
             * @interface ISysStatsConfig
             * @property {number|null} [meminfoPeriodMs] SysStatsConfig meminfoPeriodMs
             * @property {Array.<perfetto.protos.MeminfoCounters>|null} [meminfoCounters] SysStatsConfig meminfoCounters
             * @property {number|null} [vmstatPeriodMs] SysStatsConfig vmstatPeriodMs
             * @property {Array.<perfetto.protos.VmstatCounters>|null} [vmstatCounters] SysStatsConfig vmstatCounters
             * @property {number|null} [statPeriodMs] SysStatsConfig statPeriodMs
             * @property {Array.<perfetto.protos.SysStatsConfig.StatCounters>|null} [statCounters] SysStatsConfig statCounters
             * @property {number|null} [devfreqPeriodMs] SysStatsConfig devfreqPeriodMs
             */

            /**
             * Constructs a new SysStatsConfig.
             * @memberof perfetto.protos
             * @classdesc Represents a SysStatsConfig.
             * @implements ISysStatsConfig
             * @constructor
             * @param {perfetto.protos.ISysStatsConfig=} [properties] Properties to set
             */
            function SysStatsConfig(properties) {
                this.meminfoCounters = [];
                this.vmstatCounters = [];
                this.statCounters = [];
                if (properties)
                    for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                        if (properties[keys[i]] != null)
                            this[keys[i]] = properties[keys[i]];
            }

            /**
             * SysStatsConfig meminfoPeriodMs.
             * @member {number} meminfoPeriodMs
             * @memberof perfetto.protos.SysStatsConfig
             * @instance
             */
            SysStatsConfig.prototype.meminfoPeriodMs = 0;

            /**
             * SysStatsConfig meminfoCounters.
             * @member {Array.<perfetto.protos.MeminfoCounters>} meminfoCounters
             * @memberof perfetto.protos.SysStatsConfig
             * @instance
             */
            SysStatsConfig.prototype.meminfoCounters = $util.emptyArray;

            /**
             * SysStatsConfig vmstatPeriodMs.
             * @member {number} vmstatPeriodMs
             * @memberof perfetto.protos.SysStatsConfig
             * @instance
             */
            SysStatsConfig.prototype.vmstatPeriodMs = 0;

            /**
             * SysStatsConfig vmstatCounters.
             * @member {Array.<perfetto.protos.VmstatCounters>} vmstatCounters
             * @memberof perfetto.protos.SysStatsConfig
             * @instance
             */
            SysStatsConfig.prototype.vmstatCounters = $util.emptyArray;

            /**
             * SysStatsConfig statPeriodMs.
             * @member {number} statPeriodMs
             * @memberof perfetto.protos.SysStatsConfig
             * @instance
             */
            SysStatsConfig.prototype.statPeriodMs = 0;

            /**
             * SysStatsConfig statCounters.
             * @member {Array.<perfetto.protos.SysStatsConfig.StatCounters>} statCounters
             * @memberof perfetto.protos.SysStatsConfig
             * @instance
             */
            SysStatsConfig.prototype.statCounters = $util.emptyArray;

            /**
             * SysStatsConfig devfreqPeriodMs.
             * @member {number} devfreqPeriodMs
             * @memberof perfetto.protos.SysStatsConfig
             * @instance
             */
            SysStatsConfig.prototype.devfreqPeriodMs = 0;

            /**
             * Creates a new SysStatsConfig instance using the specified properties.
             * @function create
             * @memberof perfetto.protos.SysStatsConfig
             * @static
             * @param {perfetto.protos.ISysStatsConfig=} [properties] Properties to set
             * @returns {perfetto.protos.SysStatsConfig} SysStatsConfig instance
             */
            SysStatsConfig.create = function create(properties) {
                return new SysStatsConfig(properties);
            };

            /**
             * Encodes the specified SysStatsConfig message. Does not implicitly {@link perfetto.protos.SysStatsConfig.verify|verify} messages.
             * @function encode
             * @memberof perfetto.protos.SysStatsConfig
             * @static
             * @param {perfetto.protos.ISysStatsConfig} message SysStatsConfig message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            SysStatsConfig.encode = function encode(message, writer) {
                if (!writer)
                    writer = $Writer.create();
                if (message.meminfoPeriodMs != null && Object.hasOwnProperty.call(message, "meminfoPeriodMs"))
                    writer.uint32(/* id 1, wireType 0 =*/8).uint32(message.meminfoPeriodMs);
                if (message.meminfoCounters != null && message.meminfoCounters.length)
                    for (var i = 0; i < message.meminfoCounters.length; ++i)
                        writer.uint32(/* id 2, wireType 0 =*/16).int32(message.meminfoCounters[i]);
                if (message.vmstatPeriodMs != null && Object.hasOwnProperty.call(message, "vmstatPeriodMs"))
                    writer.uint32(/* id 3, wireType 0 =*/24).uint32(message.vmstatPeriodMs);
                if (message.vmstatCounters != null && message.vmstatCounters.length)
                    for (var i = 0; i < message.vmstatCounters.length; ++i)
                        writer.uint32(/* id 4, wireType 0 =*/32).int32(message.vmstatCounters[i]);
                if (message.statPeriodMs != null && Object.hasOwnProperty.call(message, "statPeriodMs"))
                    writer.uint32(/* id 5, wireType 0 =*/40).uint32(message.statPeriodMs);
                if (message.statCounters != null && message.statCounters.length)
                    for (var i = 0; i < message.statCounters.length; ++i)
                        writer.uint32(/* id 6, wireType 0 =*/48).int32(message.statCounters[i]);
                if (message.devfreqPeriodMs != null && Object.hasOwnProperty.call(message, "devfreqPeriodMs"))
                    writer.uint32(/* id 7, wireType 0 =*/56).uint32(message.devfreqPeriodMs);
                return writer;
            };

            /**
             * Encodes the specified SysStatsConfig message, length delimited. Does not implicitly {@link perfetto.protos.SysStatsConfig.verify|verify} messages.
             * @function encodeDelimited
             * @memberof perfetto.protos.SysStatsConfig
             * @static
             * @param {perfetto.protos.ISysStatsConfig} message SysStatsConfig message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            SysStatsConfig.encodeDelimited = function encodeDelimited(message, writer) {
                return this.encode(message, writer).ldelim();
            };

            /**
             * Decodes a SysStatsConfig message from the specified reader or buffer.
             * @function decode
             * @memberof perfetto.protos.SysStatsConfig
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @param {number} [length] Message length if known beforehand
             * @returns {perfetto.protos.SysStatsConfig} SysStatsConfig
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            SysStatsConfig.decode = function decode(reader, length) {
                if (!(reader instanceof $Reader))
                    reader = $Reader.create(reader);
                var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.SysStatsConfig();
                while (reader.pos < end) {
                    var tag = reader.uint32();
                    switch (tag >>> 3) {
                    case 1:
                        message.meminfoPeriodMs = reader.uint32();
                        break;
                    case 2:
                        if (!(message.meminfoCounters && message.meminfoCounters.length))
                            message.meminfoCounters = [];
                        if ((tag & 7) === 2) {
                            var end2 = reader.uint32() + reader.pos;
                            while (reader.pos < end2)
                                message.meminfoCounters.push(reader.int32());
                        } else
                            message.meminfoCounters.push(reader.int32());
                        break;
                    case 3:
                        message.vmstatPeriodMs = reader.uint32();
                        break;
                    case 4:
                        if (!(message.vmstatCounters && message.vmstatCounters.length))
                            message.vmstatCounters = [];
                        if ((tag & 7) === 2) {
                            var end2 = reader.uint32() + reader.pos;
                            while (reader.pos < end2)
                                message.vmstatCounters.push(reader.int32());
                        } else
                            message.vmstatCounters.push(reader.int32());
                        break;
                    case 5:
                        message.statPeriodMs = reader.uint32();
                        break;
                    case 6:
                        if (!(message.statCounters && message.statCounters.length))
                            message.statCounters = [];
                        if ((tag & 7) === 2) {
                            var end2 = reader.uint32() + reader.pos;
                            while (reader.pos < end2)
                                message.statCounters.push(reader.int32());
                        } else
                            message.statCounters.push(reader.int32());
                        break;
                    case 7:
                        message.devfreqPeriodMs = reader.uint32();
                        break;
                    default:
                        reader.skipType(tag & 7);
                        break;
                    }
                }
                return message;
            };

            /**
             * Decodes a SysStatsConfig message from the specified reader or buffer, length delimited.
             * @function decodeDelimited
             * @memberof perfetto.protos.SysStatsConfig
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @returns {perfetto.protos.SysStatsConfig} SysStatsConfig
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            SysStatsConfig.decodeDelimited = function decodeDelimited(reader) {
                if (!(reader instanceof $Reader))
                    reader = new $Reader(reader);
                return this.decode(reader, reader.uint32());
            };

            /**
             * Verifies a SysStatsConfig message.
             * @function verify
             * @memberof perfetto.protos.SysStatsConfig
             * @static
             * @param {Object.<string,*>} message Plain object to verify
             * @returns {string|null} `null` if valid, otherwise the reason why it is not
             */
            SysStatsConfig.verify = function verify(message) {
                if (typeof message !== "object" || message === null)
                    return "object expected";
                if (message.meminfoPeriodMs != null && message.hasOwnProperty("meminfoPeriodMs"))
                    if (!$util.isInteger(message.meminfoPeriodMs))
                        return "meminfoPeriodMs: integer expected";
                if (message.meminfoCounters != null && message.hasOwnProperty("meminfoCounters")) {
                    if (!Array.isArray(message.meminfoCounters))
                        return "meminfoCounters: array expected";
                    for (var i = 0; i < message.meminfoCounters.length; ++i)
                        switch (message.meminfoCounters[i]) {
                        default:
                            return "meminfoCounters: enum value[] expected";
                        case 0:
                        case 1:
                        case 2:
                        case 3:
                        case 4:
                        case 5:
                        case 6:
                        case 7:
                        case 8:
                        case 9:
                        case 10:
                        case 11:
                        case 12:
                        case 13:
                        case 14:
                        case 15:
                        case 16:
                        case 17:
                        case 18:
                        case 19:
                        case 20:
                        case 21:
                        case 22:
                        case 23:
                        case 24:
                        case 25:
                        case 26:
                        case 27:
                        case 28:
                        case 29:
                        case 30:
                        case 31:
                        case 32:
                        case 33:
                            break;
                        }
                }
                if (message.vmstatPeriodMs != null && message.hasOwnProperty("vmstatPeriodMs"))
                    if (!$util.isInteger(message.vmstatPeriodMs))
                        return "vmstatPeriodMs: integer expected";
                if (message.vmstatCounters != null && message.hasOwnProperty("vmstatCounters")) {
                    if (!Array.isArray(message.vmstatCounters))
                        return "vmstatCounters: array expected";
                    for (var i = 0; i < message.vmstatCounters.length; ++i)
                        switch (message.vmstatCounters[i]) {
                        default:
                            return "vmstatCounters: enum value[] expected";
                        case 0:
                        case 1:
                        case 2:
                        case 3:
                        case 4:
                        case 5:
                        case 6:
                        case 7:
                        case 8:
                        case 9:
                        case 10:
                        case 11:
                        case 12:
                        case 13:
                        case 14:
                        case 15:
                        case 16:
                        case 17:
                        case 18:
                        case 19:
                        case 20:
                        case 21:
                        case 22:
                        case 23:
                        case 24:
                        case 25:
                        case 26:
                        case 27:
                        case 28:
                        case 29:
                        case 30:
                        case 31:
                        case 32:
                        case 33:
                        case 34:
                        case 35:
                        case 36:
                        case 37:
                        case 38:
                        case 39:
                        case 40:
                        case 41:
                        case 42:
                        case 43:
                        case 44:
                        case 45:
                        case 46:
                        case 47:
                        case 48:
                        case 49:
                        case 50:
                        case 51:
                        case 52:
                        case 53:
                        case 54:
                        case 55:
                        case 56:
                        case 57:
                        case 58:
                        case 59:
                        case 60:
                        case 61:
                        case 62:
                        case 63:
                        case 64:
                        case 65:
                        case 66:
                        case 67:
                        case 68:
                        case 69:
                        case 70:
                        case 71:
                        case 72:
                        case 73:
                        case 74:
                        case 75:
                        case 76:
                        case 77:
                        case 78:
                        case 79:
                        case 80:
                        case 81:
                        case 82:
                        case 83:
                        case 84:
                        case 85:
                        case 86:
                        case 87:
                        case 88:
                        case 89:
                        case 90:
                        case 91:
                        case 92:
                        case 93:
                        case 94:
                        case 95:
                        case 96:
                        case 97:
                        case 98:
                        case 99:
                        case 100:
                        case 101:
                        case 102:
                        case 103:
                        case 104:
                        case 105:
                        case 106:
                        case 107:
                        case 108:
                        case 109:
                        case 110:
                        case 111:
                        case 112:
                        case 113:
                        case 114:
                        case 115:
                        case 116:
                        case 117:
                        case 118:
                        case 119:
                        case 120:
                        case 121:
                        case 122:
                        case 123:
                        case 124:
                        case 125:
                        case 126:
                        case 127:
                        case 128:
                            break;
                        }
                }
                if (message.statPeriodMs != null && message.hasOwnProperty("statPeriodMs"))
                    if (!$util.isInteger(message.statPeriodMs))
                        return "statPeriodMs: integer expected";
                if (message.statCounters != null && message.hasOwnProperty("statCounters")) {
                    if (!Array.isArray(message.statCounters))
                        return "statCounters: array expected";
                    for (var i = 0; i < message.statCounters.length; ++i)
                        switch (message.statCounters[i]) {
                        default:
                            return "statCounters: enum value[] expected";
                        case 0:
                        case 1:
                        case 2:
                        case 3:
                        case 4:
                            break;
                        }
                }
                if (message.devfreqPeriodMs != null && message.hasOwnProperty("devfreqPeriodMs"))
                    if (!$util.isInteger(message.devfreqPeriodMs))
                        return "devfreqPeriodMs: integer expected";
                return null;
            };

            /**
             * Creates a SysStatsConfig message from a plain object. Also converts values to their respective internal types.
             * @function fromObject
             * @memberof perfetto.protos.SysStatsConfig
             * @static
             * @param {Object.<string,*>} object Plain object
             * @returns {perfetto.protos.SysStatsConfig} SysStatsConfig
             */
            SysStatsConfig.fromObject = function fromObject(object) {
                if (object instanceof $root.perfetto.protos.SysStatsConfig)
                    return object;
                var message = new $root.perfetto.protos.SysStatsConfig();
                if (object.meminfoPeriodMs != null)
                    message.meminfoPeriodMs = object.meminfoPeriodMs >>> 0;
                if (object.meminfoCounters) {
                    if (!Array.isArray(object.meminfoCounters))
                        throw TypeError(".perfetto.protos.SysStatsConfig.meminfoCounters: array expected");
                    message.meminfoCounters = [];
                    for (var i = 0; i < object.meminfoCounters.length; ++i)
                        switch (object.meminfoCounters[i]) {
                        default:
                        case "MEMINFO_UNSPECIFIED":
                        case 0:
                            message.meminfoCounters[i] = 0;
                            break;
                        case "MEMINFO_MEM_TOTAL":
                        case 1:
                            message.meminfoCounters[i] = 1;
                            break;
                        case "MEMINFO_MEM_FREE":
                        case 2:
                            message.meminfoCounters[i] = 2;
                            break;
                        case "MEMINFO_MEM_AVAILABLE":
                        case 3:
                            message.meminfoCounters[i] = 3;
                            break;
                        case "MEMINFO_BUFFERS":
                        case 4:
                            message.meminfoCounters[i] = 4;
                            break;
                        case "MEMINFO_CACHED":
                        case 5:
                            message.meminfoCounters[i] = 5;
                            break;
                        case "MEMINFO_SWAP_CACHED":
                        case 6:
                            message.meminfoCounters[i] = 6;
                            break;
                        case "MEMINFO_ACTIVE":
                        case 7:
                            message.meminfoCounters[i] = 7;
                            break;
                        case "MEMINFO_INACTIVE":
                        case 8:
                            message.meminfoCounters[i] = 8;
                            break;
                        case "MEMINFO_ACTIVE_ANON":
                        case 9:
                            message.meminfoCounters[i] = 9;
                            break;
                        case "MEMINFO_INACTIVE_ANON":
                        case 10:
                            message.meminfoCounters[i] = 10;
                            break;
                        case "MEMINFO_ACTIVE_FILE":
                        case 11:
                            message.meminfoCounters[i] = 11;
                            break;
                        case "MEMINFO_INACTIVE_FILE":
                        case 12:
                            message.meminfoCounters[i] = 12;
                            break;
                        case "MEMINFO_UNEVICTABLE":
                        case 13:
                            message.meminfoCounters[i] = 13;
                            break;
                        case "MEMINFO_MLOCKED":
                        case 14:
                            message.meminfoCounters[i] = 14;
                            break;
                        case "MEMINFO_SWAP_TOTAL":
                        case 15:
                            message.meminfoCounters[i] = 15;
                            break;
                        case "MEMINFO_SWAP_FREE":
                        case 16:
                            message.meminfoCounters[i] = 16;
                            break;
                        case "MEMINFO_DIRTY":
                        case 17:
                            message.meminfoCounters[i] = 17;
                            break;
                        case "MEMINFO_WRITEBACK":
                        case 18:
                            message.meminfoCounters[i] = 18;
                            break;
                        case "MEMINFO_ANON_PAGES":
                        case 19:
                            message.meminfoCounters[i] = 19;
                            break;
                        case "MEMINFO_MAPPED":
                        case 20:
                            message.meminfoCounters[i] = 20;
                            break;
                        case "MEMINFO_SHMEM":
                        case 21:
                            message.meminfoCounters[i] = 21;
                            break;
                        case "MEMINFO_SLAB":
                        case 22:
                            message.meminfoCounters[i] = 22;
                            break;
                        case "MEMINFO_SLAB_RECLAIMABLE":
                        case 23:
                            message.meminfoCounters[i] = 23;
                            break;
                        case "MEMINFO_SLAB_UNRECLAIMABLE":
                        case 24:
                            message.meminfoCounters[i] = 24;
                            break;
                        case "MEMINFO_KERNEL_STACK":
                        case 25:
                            message.meminfoCounters[i] = 25;
                            break;
                        case "MEMINFO_PAGE_TABLES":
                        case 26:
                            message.meminfoCounters[i] = 26;
                            break;
                        case "MEMINFO_COMMIT_LIMIT":
                        case 27:
                            message.meminfoCounters[i] = 27;
                            break;
                        case "MEMINFO_COMMITED_AS":
                        case 28:
                            message.meminfoCounters[i] = 28;
                            break;
                        case "MEMINFO_VMALLOC_TOTAL":
                        case 29:
                            message.meminfoCounters[i] = 29;
                            break;
                        case "MEMINFO_VMALLOC_USED":
                        case 30:
                            message.meminfoCounters[i] = 30;
                            break;
                        case "MEMINFO_VMALLOC_CHUNK":
                        case 31:
                            message.meminfoCounters[i] = 31;
                            break;
                        case "MEMINFO_CMA_TOTAL":
                        case 32:
                            message.meminfoCounters[i] = 32;
                            break;
                        case "MEMINFO_CMA_FREE":
                        case 33:
                            message.meminfoCounters[i] = 33;
                            break;
                        }
                }
                if (object.vmstatPeriodMs != null)
                    message.vmstatPeriodMs = object.vmstatPeriodMs >>> 0;
                if (object.vmstatCounters) {
                    if (!Array.isArray(object.vmstatCounters))
                        throw TypeError(".perfetto.protos.SysStatsConfig.vmstatCounters: array expected");
                    message.vmstatCounters = [];
                    for (var i = 0; i < object.vmstatCounters.length; ++i)
                        switch (object.vmstatCounters[i]) {
                        default:
                        case "VMSTAT_UNSPECIFIED":
                        case 0:
                            message.vmstatCounters[i] = 0;
                            break;
                        case "VMSTAT_NR_FREE_PAGES":
                        case 1:
                            message.vmstatCounters[i] = 1;
                            break;
                        case "VMSTAT_NR_ALLOC_BATCH":
                        case 2:
                            message.vmstatCounters[i] = 2;
                            break;
                        case "VMSTAT_NR_INACTIVE_ANON":
                        case 3:
                            message.vmstatCounters[i] = 3;
                            break;
                        case "VMSTAT_NR_ACTIVE_ANON":
                        case 4:
                            message.vmstatCounters[i] = 4;
                            break;
                        case "VMSTAT_NR_INACTIVE_FILE":
                        case 5:
                            message.vmstatCounters[i] = 5;
                            break;
                        case "VMSTAT_NR_ACTIVE_FILE":
                        case 6:
                            message.vmstatCounters[i] = 6;
                            break;
                        case "VMSTAT_NR_UNEVICTABLE":
                        case 7:
                            message.vmstatCounters[i] = 7;
                            break;
                        case "VMSTAT_NR_MLOCK":
                        case 8:
                            message.vmstatCounters[i] = 8;
                            break;
                        case "VMSTAT_NR_ANON_PAGES":
                        case 9:
                            message.vmstatCounters[i] = 9;
                            break;
                        case "VMSTAT_NR_MAPPED":
                        case 10:
                            message.vmstatCounters[i] = 10;
                            break;
                        case "VMSTAT_NR_FILE_PAGES":
                        case 11:
                            message.vmstatCounters[i] = 11;
                            break;
                        case "VMSTAT_NR_DIRTY":
                        case 12:
                            message.vmstatCounters[i] = 12;
                            break;
                        case "VMSTAT_NR_WRITEBACK":
                        case 13:
                            message.vmstatCounters[i] = 13;
                            break;
                        case "VMSTAT_NR_SLAB_RECLAIMABLE":
                        case 14:
                            message.vmstatCounters[i] = 14;
                            break;
                        case "VMSTAT_NR_SLAB_UNRECLAIMABLE":
                        case 15:
                            message.vmstatCounters[i] = 15;
                            break;
                        case "VMSTAT_NR_PAGE_TABLE_PAGES":
                        case 16:
                            message.vmstatCounters[i] = 16;
                            break;
                        case "VMSTAT_NR_KERNEL_STACK":
                        case 17:
                            message.vmstatCounters[i] = 17;
                            break;
                        case "VMSTAT_NR_OVERHEAD":
                        case 18:
                            message.vmstatCounters[i] = 18;
                            break;
                        case "VMSTAT_NR_UNSTABLE":
                        case 19:
                            message.vmstatCounters[i] = 19;
                            break;
                        case "VMSTAT_NR_BOUNCE":
                        case 20:
                            message.vmstatCounters[i] = 20;
                            break;
                        case "VMSTAT_NR_VMSCAN_WRITE":
                        case 21:
                            message.vmstatCounters[i] = 21;
                            break;
                        case "VMSTAT_NR_VMSCAN_IMMEDIATE_RECLAIM":
                        case 22:
                            message.vmstatCounters[i] = 22;
                            break;
                        case "VMSTAT_NR_WRITEBACK_TEMP":
                        case 23:
                            message.vmstatCounters[i] = 23;
                            break;
                        case "VMSTAT_NR_ISOLATED_ANON":
                        case 24:
                            message.vmstatCounters[i] = 24;
                            break;
                        case "VMSTAT_NR_ISOLATED_FILE":
                        case 25:
                            message.vmstatCounters[i] = 25;
                            break;
                        case "VMSTAT_NR_SHMEM":
                        case 26:
                            message.vmstatCounters[i] = 26;
                            break;
                        case "VMSTAT_NR_DIRTIED":
                        case 27:
                            message.vmstatCounters[i] = 27;
                            break;
                        case "VMSTAT_NR_WRITTEN":
                        case 28:
                            message.vmstatCounters[i] = 28;
                            break;
                        case "VMSTAT_NR_PAGES_SCANNED":
                        case 29:
                            message.vmstatCounters[i] = 29;
                            break;
                        case "VMSTAT_WORKINGSET_REFAULT":
                        case 30:
                            message.vmstatCounters[i] = 30;
                            break;
                        case "VMSTAT_WORKINGSET_ACTIVATE":
                        case 31:
                            message.vmstatCounters[i] = 31;
                            break;
                        case "VMSTAT_WORKINGSET_NODERECLAIM":
                        case 32:
                            message.vmstatCounters[i] = 32;
                            break;
                        case "VMSTAT_NR_ANON_TRANSPARENT_HUGEPAGES":
                        case 33:
                            message.vmstatCounters[i] = 33;
                            break;
                        case "VMSTAT_NR_FREE_CMA":
                        case 34:
                            message.vmstatCounters[i] = 34;
                            break;
                        case "VMSTAT_NR_SWAPCACHE":
                        case 35:
                            message.vmstatCounters[i] = 35;
                            break;
                        case "VMSTAT_NR_DIRTY_THRESHOLD":
                        case 36:
                            message.vmstatCounters[i] = 36;
                            break;
                        case "VMSTAT_NR_DIRTY_BACKGROUND_THRESHOLD":
                        case 37:
                            message.vmstatCounters[i] = 37;
                            break;
                        case "VMSTAT_PGPGIN":
                        case 38:
                            message.vmstatCounters[i] = 38;
                            break;
                        case "VMSTAT_PGPGOUT":
                        case 39:
                            message.vmstatCounters[i] = 39;
                            break;
                        case "VMSTAT_PGPGOUTCLEAN":
                        case 40:
                            message.vmstatCounters[i] = 40;
                            break;
                        case "VMSTAT_PSWPIN":
                        case 41:
                            message.vmstatCounters[i] = 41;
                            break;
                        case "VMSTAT_PSWPOUT":
                        case 42:
                            message.vmstatCounters[i] = 42;
                            break;
                        case "VMSTAT_PGALLOC_DMA":
                        case 43:
                            message.vmstatCounters[i] = 43;
                            break;
                        case "VMSTAT_PGALLOC_NORMAL":
                        case 44:
                            message.vmstatCounters[i] = 44;
                            break;
                        case "VMSTAT_PGALLOC_MOVABLE":
                        case 45:
                            message.vmstatCounters[i] = 45;
                            break;
                        case "VMSTAT_PGFREE":
                        case 46:
                            message.vmstatCounters[i] = 46;
                            break;
                        case "VMSTAT_PGACTIVATE":
                        case 47:
                            message.vmstatCounters[i] = 47;
                            break;
                        case "VMSTAT_PGDEACTIVATE":
                        case 48:
                            message.vmstatCounters[i] = 48;
                            break;
                        case "VMSTAT_PGFAULT":
                        case 49:
                            message.vmstatCounters[i] = 49;
                            break;
                        case "VMSTAT_PGMAJFAULT":
                        case 50:
                            message.vmstatCounters[i] = 50;
                            break;
                        case "VMSTAT_PGREFILL_DMA":
                        case 51:
                            message.vmstatCounters[i] = 51;
                            break;
                        case "VMSTAT_PGREFILL_NORMAL":
                        case 52:
                            message.vmstatCounters[i] = 52;
                            break;
                        case "VMSTAT_PGREFILL_MOVABLE":
                        case 53:
                            message.vmstatCounters[i] = 53;
                            break;
                        case "VMSTAT_PGSTEAL_KSWAPD_DMA":
                        case 54:
                            message.vmstatCounters[i] = 54;
                            break;
                        case "VMSTAT_PGSTEAL_KSWAPD_NORMAL":
                        case 55:
                            message.vmstatCounters[i] = 55;
                            break;
                        case "VMSTAT_PGSTEAL_KSWAPD_MOVABLE":
                        case 56:
                            message.vmstatCounters[i] = 56;
                            break;
                        case "VMSTAT_PGSTEAL_DIRECT_DMA":
                        case 57:
                            message.vmstatCounters[i] = 57;
                            break;
                        case "VMSTAT_PGSTEAL_DIRECT_NORMAL":
                        case 58:
                            message.vmstatCounters[i] = 58;
                            break;
                        case "VMSTAT_PGSTEAL_DIRECT_MOVABLE":
                        case 59:
                            message.vmstatCounters[i] = 59;
                            break;
                        case "VMSTAT_PGSCAN_KSWAPD_DMA":
                        case 60:
                            message.vmstatCounters[i] = 60;
                            break;
                        case "VMSTAT_PGSCAN_KSWAPD_NORMAL":
                        case 61:
                            message.vmstatCounters[i] = 61;
                            break;
                        case "VMSTAT_PGSCAN_KSWAPD_MOVABLE":
                        case 62:
                            message.vmstatCounters[i] = 62;
                            break;
                        case "VMSTAT_PGSCAN_DIRECT_DMA":
                        case 63:
                            message.vmstatCounters[i] = 63;
                            break;
                        case "VMSTAT_PGSCAN_DIRECT_NORMAL":
                        case 64:
                            message.vmstatCounters[i] = 64;
                            break;
                        case "VMSTAT_PGSCAN_DIRECT_MOVABLE":
                        case 65:
                            message.vmstatCounters[i] = 65;
                            break;
                        case "VMSTAT_PGSCAN_DIRECT_THROTTLE":
                        case 66:
                            message.vmstatCounters[i] = 66;
                            break;
                        case "VMSTAT_PGINODESTEAL":
                        case 67:
                            message.vmstatCounters[i] = 67;
                            break;
                        case "VMSTAT_SLABS_SCANNED":
                        case 68:
                            message.vmstatCounters[i] = 68;
                            break;
                        case "VMSTAT_KSWAPD_INODESTEAL":
                        case 69:
                            message.vmstatCounters[i] = 69;
                            break;
                        case "VMSTAT_KSWAPD_LOW_WMARK_HIT_QUICKLY":
                        case 70:
                            message.vmstatCounters[i] = 70;
                            break;
                        case "VMSTAT_KSWAPD_HIGH_WMARK_HIT_QUICKLY":
                        case 71:
                            message.vmstatCounters[i] = 71;
                            break;
                        case "VMSTAT_PAGEOUTRUN":
                        case 72:
                            message.vmstatCounters[i] = 72;
                            break;
                        case "VMSTAT_ALLOCSTALL":
                        case 73:
                            message.vmstatCounters[i] = 73;
                            break;
                        case "VMSTAT_PGROTATED":
                        case 74:
                            message.vmstatCounters[i] = 74;
                            break;
                        case "VMSTAT_DROP_PAGECACHE":
                        case 75:
                            message.vmstatCounters[i] = 75;
                            break;
                        case "VMSTAT_DROP_SLAB":
                        case 76:
                            message.vmstatCounters[i] = 76;
                            break;
                        case "VMSTAT_PGMIGRATE_SUCCESS":
                        case 77:
                            message.vmstatCounters[i] = 77;
                            break;
                        case "VMSTAT_PGMIGRATE_FAIL":
                        case 78:
                            message.vmstatCounters[i] = 78;
                            break;
                        case "VMSTAT_COMPACT_MIGRATE_SCANNED":
                        case 79:
                            message.vmstatCounters[i] = 79;
                            break;
                        case "VMSTAT_COMPACT_FREE_SCANNED":
                        case 80:
                            message.vmstatCounters[i] = 80;
                            break;
                        case "VMSTAT_COMPACT_ISOLATED":
                        case 81:
                            message.vmstatCounters[i] = 81;
                            break;
                        case "VMSTAT_COMPACT_STALL":
                        case 82:
                            message.vmstatCounters[i] = 82;
                            break;
                        case "VMSTAT_COMPACT_FAIL":
                        case 83:
                            message.vmstatCounters[i] = 83;
                            break;
                        case "VMSTAT_COMPACT_SUCCESS":
                        case 84:
                            message.vmstatCounters[i] = 84;
                            break;
                        case "VMSTAT_COMPACT_DAEMON_WAKE":
                        case 85:
                            message.vmstatCounters[i] = 85;
                            break;
                        case "VMSTAT_UNEVICTABLE_PGS_CULLED":
                        case 86:
                            message.vmstatCounters[i] = 86;
                            break;
                        case "VMSTAT_UNEVICTABLE_PGS_SCANNED":
                        case 87:
                            message.vmstatCounters[i] = 87;
                            break;
                        case "VMSTAT_UNEVICTABLE_PGS_RESCUED":
                        case 88:
                            message.vmstatCounters[i] = 88;
                            break;
                        case "VMSTAT_UNEVICTABLE_PGS_MLOCKED":
                        case 89:
                            message.vmstatCounters[i] = 89;
                            break;
                        case "VMSTAT_UNEVICTABLE_PGS_MUNLOCKED":
                        case 90:
                            message.vmstatCounters[i] = 90;
                            break;
                        case "VMSTAT_UNEVICTABLE_PGS_CLEARED":
                        case 91:
                            message.vmstatCounters[i] = 91;
                            break;
                        case "VMSTAT_UNEVICTABLE_PGS_STRANDED":
                        case 92:
                            message.vmstatCounters[i] = 92;
                            break;
                        case "VMSTAT_NR_ZSPAGES":
                        case 93:
                            message.vmstatCounters[i] = 93;
                            break;
                        case "VMSTAT_NR_ION_HEAP":
                        case 94:
                            message.vmstatCounters[i] = 94;
                            break;
                        case "VMSTAT_NR_GPU_HEAP":
                        case 95:
                            message.vmstatCounters[i] = 95;
                            break;
                        case "VMSTAT_ALLOCSTALL_DMA":
                        case 96:
                            message.vmstatCounters[i] = 96;
                            break;
                        case "VMSTAT_ALLOCSTALL_MOVABLE":
                        case 97:
                            message.vmstatCounters[i] = 97;
                            break;
                        case "VMSTAT_ALLOCSTALL_NORMAL":
                        case 98:
                            message.vmstatCounters[i] = 98;
                            break;
                        case "VMSTAT_COMPACT_DAEMON_FREE_SCANNED":
                        case 99:
                            message.vmstatCounters[i] = 99;
                            break;
                        case "VMSTAT_COMPACT_DAEMON_MIGRATE_SCANNED":
                        case 100:
                            message.vmstatCounters[i] = 100;
                            break;
                        case "VMSTAT_NR_FASTRPC":
                        case 101:
                            message.vmstatCounters[i] = 101;
                            break;
                        case "VMSTAT_NR_INDIRECTLY_RECLAIMABLE":
                        case 102:
                            message.vmstatCounters[i] = 102;
                            break;
                        case "VMSTAT_NR_ION_HEAP_POOL":
                        case 103:
                            message.vmstatCounters[i] = 103;
                            break;
                        case "VMSTAT_NR_KERNEL_MISC_RECLAIMABLE":
                        case 104:
                            message.vmstatCounters[i] = 104;
                            break;
                        case "VMSTAT_NR_SHADOW_CALL_STACK_BYTES":
                        case 105:
                            message.vmstatCounters[i] = 105;
                            break;
                        case "VMSTAT_NR_SHMEM_HUGEPAGES":
                        case 106:
                            message.vmstatCounters[i] = 106;
                            break;
                        case "VMSTAT_NR_SHMEM_PMDMAPPED":
                        case 107:
                            message.vmstatCounters[i] = 107;
                            break;
                        case "VMSTAT_NR_UNRECLAIMABLE_PAGES":
                        case 108:
                            message.vmstatCounters[i] = 108;
                            break;
                        case "VMSTAT_NR_ZONE_ACTIVE_ANON":
                        case 109:
                            message.vmstatCounters[i] = 109;
                            break;
                        case "VMSTAT_NR_ZONE_ACTIVE_FILE":
                        case 110:
                            message.vmstatCounters[i] = 110;
                            break;
                        case "VMSTAT_NR_ZONE_INACTIVE_ANON":
                        case 111:
                            message.vmstatCounters[i] = 111;
                            break;
                        case "VMSTAT_NR_ZONE_INACTIVE_FILE":
                        case 112:
                            message.vmstatCounters[i] = 112;
                            break;
                        case "VMSTAT_NR_ZONE_UNEVICTABLE":
                        case 113:
                            message.vmstatCounters[i] = 113;
                            break;
                        case "VMSTAT_NR_ZONE_WRITE_PENDING":
                        case 114:
                            message.vmstatCounters[i] = 114;
                            break;
                        case "VMSTAT_OOM_KILL":
                        case 115:
                            message.vmstatCounters[i] = 115;
                            break;
                        case "VMSTAT_PGLAZYFREE":
                        case 116:
                            message.vmstatCounters[i] = 116;
                            break;
                        case "VMSTAT_PGLAZYFREED":
                        case 117:
                            message.vmstatCounters[i] = 117;
                            break;
                        case "VMSTAT_PGREFILL":
                        case 118:
                            message.vmstatCounters[i] = 118;
                            break;
                        case "VMSTAT_PGSCAN_DIRECT":
                        case 119:
                            message.vmstatCounters[i] = 119;
                            break;
                        case "VMSTAT_PGSCAN_KSWAPD":
                        case 120:
                            message.vmstatCounters[i] = 120;
                            break;
                        case "VMSTAT_PGSKIP_DMA":
                        case 121:
                            message.vmstatCounters[i] = 121;
                            break;
                        case "VMSTAT_PGSKIP_MOVABLE":
                        case 122:
                            message.vmstatCounters[i] = 122;
                            break;
                        case "VMSTAT_PGSKIP_NORMAL":
                        case 123:
                            message.vmstatCounters[i] = 123;
                            break;
                        case "VMSTAT_PGSTEAL_DIRECT":
                        case 124:
                            message.vmstatCounters[i] = 124;
                            break;
                        case "VMSTAT_PGSTEAL_KSWAPD":
                        case 125:
                            message.vmstatCounters[i] = 125;
                            break;
                        case "VMSTAT_SWAP_RA":
                        case 126:
                            message.vmstatCounters[i] = 126;
                            break;
                        case "VMSTAT_SWAP_RA_HIT":
                        case 127:
                            message.vmstatCounters[i] = 127;
                            break;
                        case "VMSTAT_WORKINGSET_RESTORE":
                        case 128:
                            message.vmstatCounters[i] = 128;
                            break;
                        }
                }
                if (object.statPeriodMs != null)
                    message.statPeriodMs = object.statPeriodMs >>> 0;
                if (object.statCounters) {
                    if (!Array.isArray(object.statCounters))
                        throw TypeError(".perfetto.protos.SysStatsConfig.statCounters: array expected");
                    message.statCounters = [];
                    for (var i = 0; i < object.statCounters.length; ++i)
                        switch (object.statCounters[i]) {
                        default:
                        case "STAT_UNSPECIFIED":
                        case 0:
                            message.statCounters[i] = 0;
                            break;
                        case "STAT_CPU_TIMES":
                        case 1:
                            message.statCounters[i] = 1;
                            break;
                        case "STAT_IRQ_COUNTS":
                        case 2:
                            message.statCounters[i] = 2;
                            break;
                        case "STAT_SOFTIRQ_COUNTS":
                        case 3:
                            message.statCounters[i] = 3;
                            break;
                        case "STAT_FORK_COUNT":
                        case 4:
                            message.statCounters[i] = 4;
                            break;
                        }
                }
                if (object.devfreqPeriodMs != null)
                    message.devfreqPeriodMs = object.devfreqPeriodMs >>> 0;
                return message;
            };

            /**
             * Creates a plain object from a SysStatsConfig message. Also converts values to other types if specified.
             * @function toObject
             * @memberof perfetto.protos.SysStatsConfig
             * @static
             * @param {perfetto.protos.SysStatsConfig} message SysStatsConfig
             * @param {$protobuf.IConversionOptions} [options] Conversion options
             * @returns {Object.<string,*>} Plain object
             */
            SysStatsConfig.toObject = function toObject(message, options) {
                if (!options)
                    options = {};
                var object = {};
                if (options.arrays || options.defaults) {
                    object.meminfoCounters = [];
                    object.vmstatCounters = [];
                    object.statCounters = [];
                }
                if (options.defaults) {
                    object.meminfoPeriodMs = 0;
                    object.vmstatPeriodMs = 0;
                    object.statPeriodMs = 0;
                    object.devfreqPeriodMs = 0;
                }
                if (message.meminfoPeriodMs != null && message.hasOwnProperty("meminfoPeriodMs"))
                    object.meminfoPeriodMs = message.meminfoPeriodMs;
                if (message.meminfoCounters && message.meminfoCounters.length) {
                    object.meminfoCounters = [];
                    for (var j = 0; j < message.meminfoCounters.length; ++j)
                        object.meminfoCounters[j] = options.enums === String ? $root.perfetto.protos.MeminfoCounters[message.meminfoCounters[j]] : message.meminfoCounters[j];
                }
                if (message.vmstatPeriodMs != null && message.hasOwnProperty("vmstatPeriodMs"))
                    object.vmstatPeriodMs = message.vmstatPeriodMs;
                if (message.vmstatCounters && message.vmstatCounters.length) {
                    object.vmstatCounters = [];
                    for (var j = 0; j < message.vmstatCounters.length; ++j)
                        object.vmstatCounters[j] = options.enums === String ? $root.perfetto.protos.VmstatCounters[message.vmstatCounters[j]] : message.vmstatCounters[j];
                }
                if (message.statPeriodMs != null && message.hasOwnProperty("statPeriodMs"))
                    object.statPeriodMs = message.statPeriodMs;
                if (message.statCounters && message.statCounters.length) {
                    object.statCounters = [];
                    for (var j = 0; j < message.statCounters.length; ++j)
                        object.statCounters[j] = options.enums === String ? $root.perfetto.protos.SysStatsConfig.StatCounters[message.statCounters[j]] : message.statCounters[j];
                }
                if (message.devfreqPeriodMs != null && message.hasOwnProperty("devfreqPeriodMs"))
                    object.devfreqPeriodMs = message.devfreqPeriodMs;
                return object;
            };

            /**
             * Converts this SysStatsConfig to JSON.
             * @function toJSON
             * @memberof perfetto.protos.SysStatsConfig
             * @instance
             * @returns {Object.<string,*>} JSON object
             */
            SysStatsConfig.prototype.toJSON = function toJSON() {
                return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
            };

            /**
             * StatCounters enum.
             * @name perfetto.protos.SysStatsConfig.StatCounters
             * @enum {number}
             * @property {number} STAT_UNSPECIFIED=0 STAT_UNSPECIFIED value
             * @property {number} STAT_CPU_TIMES=1 STAT_CPU_TIMES value
             * @property {number} STAT_IRQ_COUNTS=2 STAT_IRQ_COUNTS value
             * @property {number} STAT_SOFTIRQ_COUNTS=3 STAT_SOFTIRQ_COUNTS value
             * @property {number} STAT_FORK_COUNT=4 STAT_FORK_COUNT value
             */
            SysStatsConfig.StatCounters = (function() {
                var valuesById = {}, values = Object.create(valuesById);
                values[valuesById[0] = "STAT_UNSPECIFIED"] = 0;
                values[valuesById[1] = "STAT_CPU_TIMES"] = 1;
                values[valuesById[2] = "STAT_IRQ_COUNTS"] = 2;
                values[valuesById[3] = "STAT_SOFTIRQ_COUNTS"] = 3;
                values[valuesById[4] = "STAT_FORK_COUNT"] = 4;
                return values;
            })();

            return SysStatsConfig;
        })();

        protos.TestConfig = (function() {

            /**
             * Properties of a TestConfig.
             * @memberof perfetto.protos
             * @interface ITestConfig
             * @property {number|null} [messageCount] TestConfig messageCount
             * @property {number|null} [maxMessagesPerSecond] TestConfig maxMessagesPerSecond
             * @property {number|null} [seed] TestConfig seed
             * @property {number|null} [messageSize] TestConfig messageSize
             * @property {boolean|null} [sendBatchOnRegister] TestConfig sendBatchOnRegister
             * @property {perfetto.protos.TestConfig.IDummyFields|null} [dummyFields] TestConfig dummyFields
             */

            /**
             * Constructs a new TestConfig.
             * @memberof perfetto.protos
             * @classdesc Represents a TestConfig.
             * @implements ITestConfig
             * @constructor
             * @param {perfetto.protos.ITestConfig=} [properties] Properties to set
             */
            function TestConfig(properties) {
                if (properties)
                    for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                        if (properties[keys[i]] != null)
                            this[keys[i]] = properties[keys[i]];
            }

            /**
             * TestConfig messageCount.
             * @member {number} messageCount
             * @memberof perfetto.protos.TestConfig
             * @instance
             */
            TestConfig.prototype.messageCount = 0;

            /**
             * TestConfig maxMessagesPerSecond.
             * @member {number} maxMessagesPerSecond
             * @memberof perfetto.protos.TestConfig
             * @instance
             */
            TestConfig.prototype.maxMessagesPerSecond = 0;

            /**
             * TestConfig seed.
             * @member {number} seed
             * @memberof perfetto.protos.TestConfig
             * @instance
             */
            TestConfig.prototype.seed = 0;

            /**
             * TestConfig messageSize.
             * @member {number} messageSize
             * @memberof perfetto.protos.TestConfig
             * @instance
             */
            TestConfig.prototype.messageSize = 0;

            /**
             * TestConfig sendBatchOnRegister.
             * @member {boolean} sendBatchOnRegister
             * @memberof perfetto.protos.TestConfig
             * @instance
             */
            TestConfig.prototype.sendBatchOnRegister = false;

            /**
             * TestConfig dummyFields.
             * @member {perfetto.protos.TestConfig.IDummyFields|null|undefined} dummyFields
             * @memberof perfetto.protos.TestConfig
             * @instance
             */
            TestConfig.prototype.dummyFields = null;

            /**
             * Creates a new TestConfig instance using the specified properties.
             * @function create
             * @memberof perfetto.protos.TestConfig
             * @static
             * @param {perfetto.protos.ITestConfig=} [properties] Properties to set
             * @returns {perfetto.protos.TestConfig} TestConfig instance
             */
            TestConfig.create = function create(properties) {
                return new TestConfig(properties);
            };

            /**
             * Encodes the specified TestConfig message. Does not implicitly {@link perfetto.protos.TestConfig.verify|verify} messages.
             * @function encode
             * @memberof perfetto.protos.TestConfig
             * @static
             * @param {perfetto.protos.ITestConfig} message TestConfig message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            TestConfig.encode = function encode(message, writer) {
                if (!writer)
                    writer = $Writer.create();
                if (message.messageCount != null && Object.hasOwnProperty.call(message, "messageCount"))
                    writer.uint32(/* id 1, wireType 0 =*/8).uint32(message.messageCount);
                if (message.maxMessagesPerSecond != null && Object.hasOwnProperty.call(message, "maxMessagesPerSecond"))
                    writer.uint32(/* id 2, wireType 0 =*/16).uint32(message.maxMessagesPerSecond);
                if (message.seed != null && Object.hasOwnProperty.call(message, "seed"))
                    writer.uint32(/* id 3, wireType 0 =*/24).uint32(message.seed);
                if (message.messageSize != null && Object.hasOwnProperty.call(message, "messageSize"))
                    writer.uint32(/* id 4, wireType 0 =*/32).uint32(message.messageSize);
                if (message.sendBatchOnRegister != null && Object.hasOwnProperty.call(message, "sendBatchOnRegister"))
                    writer.uint32(/* id 5, wireType 0 =*/40).bool(message.sendBatchOnRegister);
                if (message.dummyFields != null && Object.hasOwnProperty.call(message, "dummyFields"))
                    $root.perfetto.protos.TestConfig.DummyFields.encode(message.dummyFields, writer.uint32(/* id 6, wireType 2 =*/50).fork()).ldelim();
                return writer;
            };

            /**
             * Encodes the specified TestConfig message, length delimited. Does not implicitly {@link perfetto.protos.TestConfig.verify|verify} messages.
             * @function encodeDelimited
             * @memberof perfetto.protos.TestConfig
             * @static
             * @param {perfetto.protos.ITestConfig} message TestConfig message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            TestConfig.encodeDelimited = function encodeDelimited(message, writer) {
                return this.encode(message, writer).ldelim();
            };

            /**
             * Decodes a TestConfig message from the specified reader or buffer.
             * @function decode
             * @memberof perfetto.protos.TestConfig
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @param {number} [length] Message length if known beforehand
             * @returns {perfetto.protos.TestConfig} TestConfig
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            TestConfig.decode = function decode(reader, length) {
                if (!(reader instanceof $Reader))
                    reader = $Reader.create(reader);
                var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.TestConfig();
                while (reader.pos < end) {
                    var tag = reader.uint32();
                    switch (tag >>> 3) {
                    case 1:
                        message.messageCount = reader.uint32();
                        break;
                    case 2:
                        message.maxMessagesPerSecond = reader.uint32();
                        break;
                    case 3:
                        message.seed = reader.uint32();
                        break;
                    case 4:
                        message.messageSize = reader.uint32();
                        break;
                    case 5:
                        message.sendBatchOnRegister = reader.bool();
                        break;
                    case 6:
                        message.dummyFields = $root.perfetto.protos.TestConfig.DummyFields.decode(reader, reader.uint32());
                        break;
                    default:
                        reader.skipType(tag & 7);
                        break;
                    }
                }
                return message;
            };

            /**
             * Decodes a TestConfig message from the specified reader or buffer, length delimited.
             * @function decodeDelimited
             * @memberof perfetto.protos.TestConfig
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @returns {perfetto.protos.TestConfig} TestConfig
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            TestConfig.decodeDelimited = function decodeDelimited(reader) {
                if (!(reader instanceof $Reader))
                    reader = new $Reader(reader);
                return this.decode(reader, reader.uint32());
            };

            /**
             * Verifies a TestConfig message.
             * @function verify
             * @memberof perfetto.protos.TestConfig
             * @static
             * @param {Object.<string,*>} message Plain object to verify
             * @returns {string|null} `null` if valid, otherwise the reason why it is not
             */
            TestConfig.verify = function verify(message) {
                if (typeof message !== "object" || message === null)
                    return "object expected";
                if (message.messageCount != null && message.hasOwnProperty("messageCount"))
                    if (!$util.isInteger(message.messageCount))
                        return "messageCount: integer expected";
                if (message.maxMessagesPerSecond != null && message.hasOwnProperty("maxMessagesPerSecond"))
                    if (!$util.isInteger(message.maxMessagesPerSecond))
                        return "maxMessagesPerSecond: integer expected";
                if (message.seed != null && message.hasOwnProperty("seed"))
                    if (!$util.isInteger(message.seed))
                        return "seed: integer expected";
                if (message.messageSize != null && message.hasOwnProperty("messageSize"))
                    if (!$util.isInteger(message.messageSize))
                        return "messageSize: integer expected";
                if (message.sendBatchOnRegister != null && message.hasOwnProperty("sendBatchOnRegister"))
                    if (typeof message.sendBatchOnRegister !== "boolean")
                        return "sendBatchOnRegister: boolean expected";
                if (message.dummyFields != null && message.hasOwnProperty("dummyFields")) {
                    var error = $root.perfetto.protos.TestConfig.DummyFields.verify(message.dummyFields);
                    if (error)
                        return "dummyFields." + error;
                }
                return null;
            };

            /**
             * Creates a TestConfig message from a plain object. Also converts values to their respective internal types.
             * @function fromObject
             * @memberof perfetto.protos.TestConfig
             * @static
             * @param {Object.<string,*>} object Plain object
             * @returns {perfetto.protos.TestConfig} TestConfig
             */
            TestConfig.fromObject = function fromObject(object) {
                if (object instanceof $root.perfetto.protos.TestConfig)
                    return object;
                var message = new $root.perfetto.protos.TestConfig();
                if (object.messageCount != null)
                    message.messageCount = object.messageCount >>> 0;
                if (object.maxMessagesPerSecond != null)
                    message.maxMessagesPerSecond = object.maxMessagesPerSecond >>> 0;
                if (object.seed != null)
                    message.seed = object.seed >>> 0;
                if (object.messageSize != null)
                    message.messageSize = object.messageSize >>> 0;
                if (object.sendBatchOnRegister != null)
                    message.sendBatchOnRegister = Boolean(object.sendBatchOnRegister);
                if (object.dummyFields != null) {
                    if (typeof object.dummyFields !== "object")
                        throw TypeError(".perfetto.protos.TestConfig.dummyFields: object expected");
                    message.dummyFields = $root.perfetto.protos.TestConfig.DummyFields.fromObject(object.dummyFields);
                }
                return message;
            };

            /**
             * Creates a plain object from a TestConfig message. Also converts values to other types if specified.
             * @function toObject
             * @memberof perfetto.protos.TestConfig
             * @static
             * @param {perfetto.protos.TestConfig} message TestConfig
             * @param {$protobuf.IConversionOptions} [options] Conversion options
             * @returns {Object.<string,*>} Plain object
             */
            TestConfig.toObject = function toObject(message, options) {
                if (!options)
                    options = {};
                var object = {};
                if (options.defaults) {
                    object.messageCount = 0;
                    object.maxMessagesPerSecond = 0;
                    object.seed = 0;
                    object.messageSize = 0;
                    object.sendBatchOnRegister = false;
                    object.dummyFields = null;
                }
                if (message.messageCount != null && message.hasOwnProperty("messageCount"))
                    object.messageCount = message.messageCount;
                if (message.maxMessagesPerSecond != null && message.hasOwnProperty("maxMessagesPerSecond"))
                    object.maxMessagesPerSecond = message.maxMessagesPerSecond;
                if (message.seed != null && message.hasOwnProperty("seed"))
                    object.seed = message.seed;
                if (message.messageSize != null && message.hasOwnProperty("messageSize"))
                    object.messageSize = message.messageSize;
                if (message.sendBatchOnRegister != null && message.hasOwnProperty("sendBatchOnRegister"))
                    object.sendBatchOnRegister = message.sendBatchOnRegister;
                if (message.dummyFields != null && message.hasOwnProperty("dummyFields"))
                    object.dummyFields = $root.perfetto.protos.TestConfig.DummyFields.toObject(message.dummyFields, options);
                return object;
            };

            /**
             * Converts this TestConfig to JSON.
             * @function toJSON
             * @memberof perfetto.protos.TestConfig
             * @instance
             * @returns {Object.<string,*>} JSON object
             */
            TestConfig.prototype.toJSON = function toJSON() {
                return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
            };

            TestConfig.DummyFields = (function() {

                /**
                 * Properties of a DummyFields.
                 * @memberof perfetto.protos.TestConfig
                 * @interface IDummyFields
                 * @property {number|null} [fieldUint32] DummyFields fieldUint32
                 * @property {number|null} [fieldInt32] DummyFields fieldInt32
                 * @property {number|null} [fieldUint64] DummyFields fieldUint64
                 * @property {number|null} [fieldInt64] DummyFields fieldInt64
                 * @property {number|null} [fieldFixed64] DummyFields fieldFixed64
                 * @property {number|null} [fieldSfixed64] DummyFields fieldSfixed64
                 * @property {number|null} [fieldFixed32] DummyFields fieldFixed32
                 * @property {number|null} [fieldSfixed32] DummyFields fieldSfixed32
                 * @property {number|null} [fieldDouble] DummyFields fieldDouble
                 * @property {number|null} [fieldFloat] DummyFields fieldFloat
                 * @property {number|null} [fieldSint64] DummyFields fieldSint64
                 * @property {number|null} [fieldSint32] DummyFields fieldSint32
                 * @property {string|null} [fieldString] DummyFields fieldString
                 * @property {Uint8Array|null} [fieldBytes] DummyFields fieldBytes
                 */

                /**
                 * Constructs a new DummyFields.
                 * @memberof perfetto.protos.TestConfig
                 * @classdesc Represents a DummyFields.
                 * @implements IDummyFields
                 * @constructor
                 * @param {perfetto.protos.TestConfig.IDummyFields=} [properties] Properties to set
                 */
                function DummyFields(properties) {
                    if (properties)
                        for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                            if (properties[keys[i]] != null)
                                this[keys[i]] = properties[keys[i]];
                }

                /**
                 * DummyFields fieldUint32.
                 * @member {number} fieldUint32
                 * @memberof perfetto.protos.TestConfig.DummyFields
                 * @instance
                 */
                DummyFields.prototype.fieldUint32 = 0;

                /**
                 * DummyFields fieldInt32.
                 * @member {number} fieldInt32
                 * @memberof perfetto.protos.TestConfig.DummyFields
                 * @instance
                 */
                DummyFields.prototype.fieldInt32 = 0;

                /**
                 * DummyFields fieldUint64.
                 * @member {number} fieldUint64
                 * @memberof perfetto.protos.TestConfig.DummyFields
                 * @instance
                 */
                DummyFields.prototype.fieldUint64 = $util.Long ? $util.Long.fromBits(0,0,true) : 0;

                /**
                 * DummyFields fieldInt64.
                 * @member {number} fieldInt64
                 * @memberof perfetto.protos.TestConfig.DummyFields
                 * @instance
                 */
                DummyFields.prototype.fieldInt64 = $util.Long ? $util.Long.fromBits(0,0,false) : 0;

                /**
                 * DummyFields fieldFixed64.
                 * @member {number} fieldFixed64
                 * @memberof perfetto.protos.TestConfig.DummyFields
                 * @instance
                 */
                DummyFields.prototype.fieldFixed64 = $util.Long ? $util.Long.fromBits(0,0,false) : 0;

                /**
                 * DummyFields fieldSfixed64.
                 * @member {number} fieldSfixed64
                 * @memberof perfetto.protos.TestConfig.DummyFields
                 * @instance
                 */
                DummyFields.prototype.fieldSfixed64 = $util.Long ? $util.Long.fromBits(0,0,false) : 0;

                /**
                 * DummyFields fieldFixed32.
                 * @member {number} fieldFixed32
                 * @memberof perfetto.protos.TestConfig.DummyFields
                 * @instance
                 */
                DummyFields.prototype.fieldFixed32 = 0;

                /**
                 * DummyFields fieldSfixed32.
                 * @member {number} fieldSfixed32
                 * @memberof perfetto.protos.TestConfig.DummyFields
                 * @instance
                 */
                DummyFields.prototype.fieldSfixed32 = 0;

                /**
                 * DummyFields fieldDouble.
                 * @member {number} fieldDouble
                 * @memberof perfetto.protos.TestConfig.DummyFields
                 * @instance
                 */
                DummyFields.prototype.fieldDouble = 0;

                /**
                 * DummyFields fieldFloat.
                 * @member {number} fieldFloat
                 * @memberof perfetto.protos.TestConfig.DummyFields
                 * @instance
                 */
                DummyFields.prototype.fieldFloat = 0;

                /**
                 * DummyFields fieldSint64.
                 * @member {number} fieldSint64
                 * @memberof perfetto.protos.TestConfig.DummyFields
                 * @instance
                 */
                DummyFields.prototype.fieldSint64 = $util.Long ? $util.Long.fromBits(0,0,false) : 0;

                /**
                 * DummyFields fieldSint32.
                 * @member {number} fieldSint32
                 * @memberof perfetto.protos.TestConfig.DummyFields
                 * @instance
                 */
                DummyFields.prototype.fieldSint32 = 0;

                /**
                 * DummyFields fieldString.
                 * @member {string} fieldString
                 * @memberof perfetto.protos.TestConfig.DummyFields
                 * @instance
                 */
                DummyFields.prototype.fieldString = "";

                /**
                 * DummyFields fieldBytes.
                 * @member {Uint8Array} fieldBytes
                 * @memberof perfetto.protos.TestConfig.DummyFields
                 * @instance
                 */
                DummyFields.prototype.fieldBytes = $util.newBuffer([]);

                /**
                 * Creates a new DummyFields instance using the specified properties.
                 * @function create
                 * @memberof perfetto.protos.TestConfig.DummyFields
                 * @static
                 * @param {perfetto.protos.TestConfig.IDummyFields=} [properties] Properties to set
                 * @returns {perfetto.protos.TestConfig.DummyFields} DummyFields instance
                 */
                DummyFields.create = function create(properties) {
                    return new DummyFields(properties);
                };

                /**
                 * Encodes the specified DummyFields message. Does not implicitly {@link perfetto.protos.TestConfig.DummyFields.verify|verify} messages.
                 * @function encode
                 * @memberof perfetto.protos.TestConfig.DummyFields
                 * @static
                 * @param {perfetto.protos.TestConfig.IDummyFields} message DummyFields message or plain object to encode
                 * @param {$protobuf.Writer} [writer] Writer to encode to
                 * @returns {$protobuf.Writer} Writer
                 */
                DummyFields.encode = function encode(message, writer) {
                    if (!writer)
                        writer = $Writer.create();
                    if (message.fieldUint32 != null && Object.hasOwnProperty.call(message, "fieldUint32"))
                        writer.uint32(/* id 1, wireType 0 =*/8).uint32(message.fieldUint32);
                    if (message.fieldInt32 != null && Object.hasOwnProperty.call(message, "fieldInt32"))
                        writer.uint32(/* id 2, wireType 0 =*/16).int32(message.fieldInt32);
                    if (message.fieldUint64 != null && Object.hasOwnProperty.call(message, "fieldUint64"))
                        writer.uint32(/* id 3, wireType 0 =*/24).uint64(message.fieldUint64);
                    if (message.fieldInt64 != null && Object.hasOwnProperty.call(message, "fieldInt64"))
                        writer.uint32(/* id 4, wireType 0 =*/32).int64(message.fieldInt64);
                    if (message.fieldFixed64 != null && Object.hasOwnProperty.call(message, "fieldFixed64"))
                        writer.uint32(/* id 5, wireType 1 =*/41).fixed64(message.fieldFixed64);
                    if (message.fieldSfixed64 != null && Object.hasOwnProperty.call(message, "fieldSfixed64"))
                        writer.uint32(/* id 6, wireType 1 =*/49).sfixed64(message.fieldSfixed64);
                    if (message.fieldFixed32 != null && Object.hasOwnProperty.call(message, "fieldFixed32"))
                        writer.uint32(/* id 7, wireType 5 =*/61).fixed32(message.fieldFixed32);
                    if (message.fieldSfixed32 != null && Object.hasOwnProperty.call(message, "fieldSfixed32"))
                        writer.uint32(/* id 8, wireType 5 =*/69).sfixed32(message.fieldSfixed32);
                    if (message.fieldDouble != null && Object.hasOwnProperty.call(message, "fieldDouble"))
                        writer.uint32(/* id 9, wireType 1 =*/73).double(message.fieldDouble);
                    if (message.fieldFloat != null && Object.hasOwnProperty.call(message, "fieldFloat"))
                        writer.uint32(/* id 10, wireType 5 =*/85).float(message.fieldFloat);
                    if (message.fieldSint64 != null && Object.hasOwnProperty.call(message, "fieldSint64"))
                        writer.uint32(/* id 11, wireType 0 =*/88).sint64(message.fieldSint64);
                    if (message.fieldSint32 != null && Object.hasOwnProperty.call(message, "fieldSint32"))
                        writer.uint32(/* id 12, wireType 0 =*/96).sint32(message.fieldSint32);
                    if (message.fieldString != null && Object.hasOwnProperty.call(message, "fieldString"))
                        writer.uint32(/* id 13, wireType 2 =*/106).string(message.fieldString);
                    if (message.fieldBytes != null && Object.hasOwnProperty.call(message, "fieldBytes"))
                        writer.uint32(/* id 14, wireType 2 =*/114).bytes(message.fieldBytes);
                    return writer;
                };

                /**
                 * Encodes the specified DummyFields message, length delimited. Does not implicitly {@link perfetto.protos.TestConfig.DummyFields.verify|verify} messages.
                 * @function encodeDelimited
                 * @memberof perfetto.protos.TestConfig.DummyFields
                 * @static
                 * @param {perfetto.protos.TestConfig.IDummyFields} message DummyFields message or plain object to encode
                 * @param {$protobuf.Writer} [writer] Writer to encode to
                 * @returns {$protobuf.Writer} Writer
                 */
                DummyFields.encodeDelimited = function encodeDelimited(message, writer) {
                    return this.encode(message, writer).ldelim();
                };

                /**
                 * Decodes a DummyFields message from the specified reader or buffer.
                 * @function decode
                 * @memberof perfetto.protos.TestConfig.DummyFields
                 * @static
                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                 * @param {number} [length] Message length if known beforehand
                 * @returns {perfetto.protos.TestConfig.DummyFields} DummyFields
                 * @throws {Error} If the payload is not a reader or valid buffer
                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
                 */
                DummyFields.decode = function decode(reader, length) {
                    if (!(reader instanceof $Reader))
                        reader = $Reader.create(reader);
                    var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.TestConfig.DummyFields();
                    while (reader.pos < end) {
                        var tag = reader.uint32();
                        switch (tag >>> 3) {
                        case 1:
                            message.fieldUint32 = reader.uint32();
                            break;
                        case 2:
                            message.fieldInt32 = reader.int32();
                            break;
                        case 3:
                            message.fieldUint64 = reader.uint64();
                            break;
                        case 4:
                            message.fieldInt64 = reader.int64();
                            break;
                        case 5:
                            message.fieldFixed64 = reader.fixed64();
                            break;
                        case 6:
                            message.fieldSfixed64 = reader.sfixed64();
                            break;
                        case 7:
                            message.fieldFixed32 = reader.fixed32();
                            break;
                        case 8:
                            message.fieldSfixed32 = reader.sfixed32();
                            break;
                        case 9:
                            message.fieldDouble = reader.double();
                            break;
                        case 10:
                            message.fieldFloat = reader.float();
                            break;
                        case 11:
                            message.fieldSint64 = reader.sint64();
                            break;
                        case 12:
                            message.fieldSint32 = reader.sint32();
                            break;
                        case 13:
                            message.fieldString = reader.string();
                            break;
                        case 14:
                            message.fieldBytes = reader.bytes();
                            break;
                        default:
                            reader.skipType(tag & 7);
                            break;
                        }
                    }
                    return message;
                };

                /**
                 * Decodes a DummyFields message from the specified reader or buffer, length delimited.
                 * @function decodeDelimited
                 * @memberof perfetto.protos.TestConfig.DummyFields
                 * @static
                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                 * @returns {perfetto.protos.TestConfig.DummyFields} DummyFields
                 * @throws {Error} If the payload is not a reader or valid buffer
                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
                 */
                DummyFields.decodeDelimited = function decodeDelimited(reader) {
                    if (!(reader instanceof $Reader))
                        reader = new $Reader(reader);
                    return this.decode(reader, reader.uint32());
                };

                /**
                 * Verifies a DummyFields message.
                 * @function verify
                 * @memberof perfetto.protos.TestConfig.DummyFields
                 * @static
                 * @param {Object.<string,*>} message Plain object to verify
                 * @returns {string|null} `null` if valid, otherwise the reason why it is not
                 */
                DummyFields.verify = function verify(message) {
                    if (typeof message !== "object" || message === null)
                        return "object expected";
                    if (message.fieldUint32 != null && message.hasOwnProperty("fieldUint32"))
                        if (!$util.isInteger(message.fieldUint32))
                            return "fieldUint32: integer expected";
                    if (message.fieldInt32 != null && message.hasOwnProperty("fieldInt32"))
                        if (!$util.isInteger(message.fieldInt32))
                            return "fieldInt32: integer expected";
                    if (message.fieldUint64 != null && message.hasOwnProperty("fieldUint64"))
                        if (!$util.isInteger(message.fieldUint64) && !(message.fieldUint64 && $util.isInteger(message.fieldUint64.low) && $util.isInteger(message.fieldUint64.high)))
                            return "fieldUint64: integer|Long expected";
                    if (message.fieldInt64 != null && message.hasOwnProperty("fieldInt64"))
                        if (!$util.isInteger(message.fieldInt64) && !(message.fieldInt64 && $util.isInteger(message.fieldInt64.low) && $util.isInteger(message.fieldInt64.high)))
                            return "fieldInt64: integer|Long expected";
                    if (message.fieldFixed64 != null && message.hasOwnProperty("fieldFixed64"))
                        if (!$util.isInteger(message.fieldFixed64) && !(message.fieldFixed64 && $util.isInteger(message.fieldFixed64.low) && $util.isInteger(message.fieldFixed64.high)))
                            return "fieldFixed64: integer|Long expected";
                    if (message.fieldSfixed64 != null && message.hasOwnProperty("fieldSfixed64"))
                        if (!$util.isInteger(message.fieldSfixed64) && !(message.fieldSfixed64 && $util.isInteger(message.fieldSfixed64.low) && $util.isInteger(message.fieldSfixed64.high)))
                            return "fieldSfixed64: integer|Long expected";
                    if (message.fieldFixed32 != null && message.hasOwnProperty("fieldFixed32"))
                        if (!$util.isInteger(message.fieldFixed32))
                            return "fieldFixed32: integer expected";
                    if (message.fieldSfixed32 != null && message.hasOwnProperty("fieldSfixed32"))
                        if (!$util.isInteger(message.fieldSfixed32))
                            return "fieldSfixed32: integer expected";
                    if (message.fieldDouble != null && message.hasOwnProperty("fieldDouble"))
                        if (typeof message.fieldDouble !== "number")
                            return "fieldDouble: number expected";
                    if (message.fieldFloat != null && message.hasOwnProperty("fieldFloat"))
                        if (typeof message.fieldFloat !== "number")
                            return "fieldFloat: number expected";
                    if (message.fieldSint64 != null && message.hasOwnProperty("fieldSint64"))
                        if (!$util.isInteger(message.fieldSint64) && !(message.fieldSint64 && $util.isInteger(message.fieldSint64.low) && $util.isInteger(message.fieldSint64.high)))
                            return "fieldSint64: integer|Long expected";
                    if (message.fieldSint32 != null && message.hasOwnProperty("fieldSint32"))
                        if (!$util.isInteger(message.fieldSint32))
                            return "fieldSint32: integer expected";
                    if (message.fieldString != null && message.hasOwnProperty("fieldString"))
                        if (!$util.isString(message.fieldString))
                            return "fieldString: string expected";
                    if (message.fieldBytes != null && message.hasOwnProperty("fieldBytes"))
                        if (!(message.fieldBytes && typeof message.fieldBytes.length === "number" || $util.isString(message.fieldBytes)))
                            return "fieldBytes: buffer expected";
                    return null;
                };

                /**
                 * Creates a DummyFields message from a plain object. Also converts values to their respective internal types.
                 * @function fromObject
                 * @memberof perfetto.protos.TestConfig.DummyFields
                 * @static
                 * @param {Object.<string,*>} object Plain object
                 * @returns {perfetto.protos.TestConfig.DummyFields} DummyFields
                 */
                DummyFields.fromObject = function fromObject(object) {
                    if (object instanceof $root.perfetto.protos.TestConfig.DummyFields)
                        return object;
                    var message = new $root.perfetto.protos.TestConfig.DummyFields();
                    if (object.fieldUint32 != null)
                        message.fieldUint32 = object.fieldUint32 >>> 0;
                    if (object.fieldInt32 != null)
                        message.fieldInt32 = object.fieldInt32 | 0;
                    if (object.fieldUint64 != null)
                        if ($util.Long)
                            (message.fieldUint64 = $util.Long.fromValue(object.fieldUint64)).unsigned = true;
                        else if (typeof object.fieldUint64 === "string")
                            message.fieldUint64 = parseInt(object.fieldUint64, 10);
                        else if (typeof object.fieldUint64 === "number")
                            message.fieldUint64 = object.fieldUint64;
                        else if (typeof object.fieldUint64 === "object")
                            message.fieldUint64 = new $util.LongBits(object.fieldUint64.low >>> 0, object.fieldUint64.high >>> 0).toNumber(true);
                    if (object.fieldInt64 != null)
                        if ($util.Long)
                            (message.fieldInt64 = $util.Long.fromValue(object.fieldInt64)).unsigned = false;
                        else if (typeof object.fieldInt64 === "string")
                            message.fieldInt64 = parseInt(object.fieldInt64, 10);
                        else if (typeof object.fieldInt64 === "number")
                            message.fieldInt64 = object.fieldInt64;
                        else if (typeof object.fieldInt64 === "object")
                            message.fieldInt64 = new $util.LongBits(object.fieldInt64.low >>> 0, object.fieldInt64.high >>> 0).toNumber();
                    if (object.fieldFixed64 != null)
                        if ($util.Long)
                            (message.fieldFixed64 = $util.Long.fromValue(object.fieldFixed64)).unsigned = false;
                        else if (typeof object.fieldFixed64 === "string")
                            message.fieldFixed64 = parseInt(object.fieldFixed64, 10);
                        else if (typeof object.fieldFixed64 === "number")
                            message.fieldFixed64 = object.fieldFixed64;
                        else if (typeof object.fieldFixed64 === "object")
                            message.fieldFixed64 = new $util.LongBits(object.fieldFixed64.low >>> 0, object.fieldFixed64.high >>> 0).toNumber();
                    if (object.fieldSfixed64 != null)
                        if ($util.Long)
                            (message.fieldSfixed64 = $util.Long.fromValue(object.fieldSfixed64)).unsigned = false;
                        else if (typeof object.fieldSfixed64 === "string")
                            message.fieldSfixed64 = parseInt(object.fieldSfixed64, 10);
                        else if (typeof object.fieldSfixed64 === "number")
                            message.fieldSfixed64 = object.fieldSfixed64;
                        else if (typeof object.fieldSfixed64 === "object")
                            message.fieldSfixed64 = new $util.LongBits(object.fieldSfixed64.low >>> 0, object.fieldSfixed64.high >>> 0).toNumber();
                    if (object.fieldFixed32 != null)
                        message.fieldFixed32 = object.fieldFixed32 >>> 0;
                    if (object.fieldSfixed32 != null)
                        message.fieldSfixed32 = object.fieldSfixed32 | 0;
                    if (object.fieldDouble != null)
                        message.fieldDouble = Number(object.fieldDouble);
                    if (object.fieldFloat != null)
                        message.fieldFloat = Number(object.fieldFloat);
                    if (object.fieldSint64 != null)
                        if ($util.Long)
                            (message.fieldSint64 = $util.Long.fromValue(object.fieldSint64)).unsigned = false;
                        else if (typeof object.fieldSint64 === "string")
                            message.fieldSint64 = parseInt(object.fieldSint64, 10);
                        else if (typeof object.fieldSint64 === "number")
                            message.fieldSint64 = object.fieldSint64;
                        else if (typeof object.fieldSint64 === "object")
                            message.fieldSint64 = new $util.LongBits(object.fieldSint64.low >>> 0, object.fieldSint64.high >>> 0).toNumber();
                    if (object.fieldSint32 != null)
                        message.fieldSint32 = object.fieldSint32 | 0;
                    if (object.fieldString != null)
                        message.fieldString = String(object.fieldString);
                    if (object.fieldBytes != null)
                        if (typeof object.fieldBytes === "string")
                            $util.base64.decode(object.fieldBytes, message.fieldBytes = $util.newBuffer($util.base64.length(object.fieldBytes)), 0);
                        else if (object.fieldBytes.length)
                            message.fieldBytes = object.fieldBytes;
                    return message;
                };

                /**
                 * Creates a plain object from a DummyFields message. Also converts values to other types if specified.
                 * @function toObject
                 * @memberof perfetto.protos.TestConfig.DummyFields
                 * @static
                 * @param {perfetto.protos.TestConfig.DummyFields} message DummyFields
                 * @param {$protobuf.IConversionOptions} [options] Conversion options
                 * @returns {Object.<string,*>} Plain object
                 */
                DummyFields.toObject = function toObject(message, options) {
                    if (!options)
                        options = {};
                    var object = {};
                    if (options.defaults) {
                        object.fieldUint32 = 0;
                        object.fieldInt32 = 0;
                        if ($util.Long) {
                            var long = new $util.Long(0, 0, true);
                            object.fieldUint64 = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
                        } else
                            object.fieldUint64 = options.longs === String ? "0" : 0;
                        if ($util.Long) {
                            var long = new $util.Long(0, 0, false);
                            object.fieldInt64 = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
                        } else
                            object.fieldInt64 = options.longs === String ? "0" : 0;
                        if ($util.Long) {
                            var long = new $util.Long(0, 0, false);
                            object.fieldFixed64 = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
                        } else
                            object.fieldFixed64 = options.longs === String ? "0" : 0;
                        if ($util.Long) {
                            var long = new $util.Long(0, 0, false);
                            object.fieldSfixed64 = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
                        } else
                            object.fieldSfixed64 = options.longs === String ? "0" : 0;
                        object.fieldFixed32 = 0;
                        object.fieldSfixed32 = 0;
                        object.fieldDouble = 0;
                        object.fieldFloat = 0;
                        if ($util.Long) {
                            var long = new $util.Long(0, 0, false);
                            object.fieldSint64 = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
                        } else
                            object.fieldSint64 = options.longs === String ? "0" : 0;
                        object.fieldSint32 = 0;
                        object.fieldString = "";
                        if (options.bytes === String)
                            object.fieldBytes = "";
                        else {
                            object.fieldBytes = [];
                            if (options.bytes !== Array)
                                object.fieldBytes = $util.newBuffer(object.fieldBytes);
                        }
                    }
                    if (message.fieldUint32 != null && message.hasOwnProperty("fieldUint32"))
                        object.fieldUint32 = message.fieldUint32;
                    if (message.fieldInt32 != null && message.hasOwnProperty("fieldInt32"))
                        object.fieldInt32 = message.fieldInt32;
                    if (message.fieldUint64 != null && message.hasOwnProperty("fieldUint64"))
                        if (typeof message.fieldUint64 === "number")
                            object.fieldUint64 = options.longs === String ? String(message.fieldUint64) : message.fieldUint64;
                        else
                            object.fieldUint64 = options.longs === String ? $util.Long.prototype.toString.call(message.fieldUint64) : options.longs === Number ? new $util.LongBits(message.fieldUint64.low >>> 0, message.fieldUint64.high >>> 0).toNumber(true) : message.fieldUint64;
                    if (message.fieldInt64 != null && message.hasOwnProperty("fieldInt64"))
                        if (typeof message.fieldInt64 === "number")
                            object.fieldInt64 = options.longs === String ? String(message.fieldInt64) : message.fieldInt64;
                        else
                            object.fieldInt64 = options.longs === String ? $util.Long.prototype.toString.call(message.fieldInt64) : options.longs === Number ? new $util.LongBits(message.fieldInt64.low >>> 0, message.fieldInt64.high >>> 0).toNumber() : message.fieldInt64;
                    if (message.fieldFixed64 != null && message.hasOwnProperty("fieldFixed64"))
                        if (typeof message.fieldFixed64 === "number")
                            object.fieldFixed64 = options.longs === String ? String(message.fieldFixed64) : message.fieldFixed64;
                        else
                            object.fieldFixed64 = options.longs === String ? $util.Long.prototype.toString.call(message.fieldFixed64) : options.longs === Number ? new $util.LongBits(message.fieldFixed64.low >>> 0, message.fieldFixed64.high >>> 0).toNumber() : message.fieldFixed64;
                    if (message.fieldSfixed64 != null && message.hasOwnProperty("fieldSfixed64"))
                        if (typeof message.fieldSfixed64 === "number")
                            object.fieldSfixed64 = options.longs === String ? String(message.fieldSfixed64) : message.fieldSfixed64;
                        else
                            object.fieldSfixed64 = options.longs === String ? $util.Long.prototype.toString.call(message.fieldSfixed64) : options.longs === Number ? new $util.LongBits(message.fieldSfixed64.low >>> 0, message.fieldSfixed64.high >>> 0).toNumber() : message.fieldSfixed64;
                    if (message.fieldFixed32 != null && message.hasOwnProperty("fieldFixed32"))
                        object.fieldFixed32 = message.fieldFixed32;
                    if (message.fieldSfixed32 != null && message.hasOwnProperty("fieldSfixed32"))
                        object.fieldSfixed32 = message.fieldSfixed32;
                    if (message.fieldDouble != null && message.hasOwnProperty("fieldDouble"))
                        object.fieldDouble = options.json && !isFinite(message.fieldDouble) ? String(message.fieldDouble) : message.fieldDouble;
                    if (message.fieldFloat != null && message.hasOwnProperty("fieldFloat"))
                        object.fieldFloat = options.json && !isFinite(message.fieldFloat) ? String(message.fieldFloat) : message.fieldFloat;
                    if (message.fieldSint64 != null && message.hasOwnProperty("fieldSint64"))
                        if (typeof message.fieldSint64 === "number")
                            object.fieldSint64 = options.longs === String ? String(message.fieldSint64) : message.fieldSint64;
                        else
                            object.fieldSint64 = options.longs === String ? $util.Long.prototype.toString.call(message.fieldSint64) : options.longs === Number ? new $util.LongBits(message.fieldSint64.low >>> 0, message.fieldSint64.high >>> 0).toNumber() : message.fieldSint64;
                    if (message.fieldSint32 != null && message.hasOwnProperty("fieldSint32"))
                        object.fieldSint32 = message.fieldSint32;
                    if (message.fieldString != null && message.hasOwnProperty("fieldString"))
                        object.fieldString = message.fieldString;
                    if (message.fieldBytes != null && message.hasOwnProperty("fieldBytes"))
                        object.fieldBytes = options.bytes === String ? $util.base64.encode(message.fieldBytes, 0, message.fieldBytes.length) : options.bytes === Array ? Array.prototype.slice.call(message.fieldBytes) : message.fieldBytes;
                    return object;
                };

                /**
                 * Converts this DummyFields to JSON.
                 * @function toJSON
                 * @memberof perfetto.protos.TestConfig.DummyFields
                 * @instance
                 * @returns {Object.<string,*>} JSON object
                 */
                DummyFields.prototype.toJSON = function toJSON() {
                    return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
                };

                return DummyFields;
            })();

            return TestConfig;
        })();

        protos.TrackEventConfig = (function() {

            /**
             * Properties of a TrackEventConfig.
             * @memberof perfetto.protos
             * @interface ITrackEventConfig
             * @property {Array.<string>|null} [disabledCategories] TrackEventConfig disabledCategories
             * @property {Array.<string>|null} [enabledCategories] TrackEventConfig enabledCategories
             * @property {Array.<string>|null} [disabledTags] TrackEventConfig disabledTags
             * @property {Array.<string>|null} [enabledTags] TrackEventConfig enabledTags
             */

            /**
             * Constructs a new TrackEventConfig.
             * @memberof perfetto.protos
             * @classdesc Represents a TrackEventConfig.
             * @implements ITrackEventConfig
             * @constructor
             * @param {perfetto.protos.ITrackEventConfig=} [properties] Properties to set
             */
            function TrackEventConfig(properties) {
                this.disabledCategories = [];
                this.enabledCategories = [];
                this.disabledTags = [];
                this.enabledTags = [];
                if (properties)
                    for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                        if (properties[keys[i]] != null)
                            this[keys[i]] = properties[keys[i]];
            }

            /**
             * TrackEventConfig disabledCategories.
             * @member {Array.<string>} disabledCategories
             * @memberof perfetto.protos.TrackEventConfig
             * @instance
             */
            TrackEventConfig.prototype.disabledCategories = $util.emptyArray;

            /**
             * TrackEventConfig enabledCategories.
             * @member {Array.<string>} enabledCategories
             * @memberof perfetto.protos.TrackEventConfig
             * @instance
             */
            TrackEventConfig.prototype.enabledCategories = $util.emptyArray;

            /**
             * TrackEventConfig disabledTags.
             * @member {Array.<string>} disabledTags
             * @memberof perfetto.protos.TrackEventConfig
             * @instance
             */
            TrackEventConfig.prototype.disabledTags = $util.emptyArray;

            /**
             * TrackEventConfig enabledTags.
             * @member {Array.<string>} enabledTags
             * @memberof perfetto.protos.TrackEventConfig
             * @instance
             */
            TrackEventConfig.prototype.enabledTags = $util.emptyArray;

            /**
             * Creates a new TrackEventConfig instance using the specified properties.
             * @function create
             * @memberof perfetto.protos.TrackEventConfig
             * @static
             * @param {perfetto.protos.ITrackEventConfig=} [properties] Properties to set
             * @returns {perfetto.protos.TrackEventConfig} TrackEventConfig instance
             */
            TrackEventConfig.create = function create(properties) {
                return new TrackEventConfig(properties);
            };

            /**
             * Encodes the specified TrackEventConfig message. Does not implicitly {@link perfetto.protos.TrackEventConfig.verify|verify} messages.
             * @function encode
             * @memberof perfetto.protos.TrackEventConfig
             * @static
             * @param {perfetto.protos.ITrackEventConfig} message TrackEventConfig message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            TrackEventConfig.encode = function encode(message, writer) {
                if (!writer)
                    writer = $Writer.create();
                if (message.disabledCategories != null && message.disabledCategories.length)
                    for (var i = 0; i < message.disabledCategories.length; ++i)
                        writer.uint32(/* id 1, wireType 2 =*/10).string(message.disabledCategories[i]);
                if (message.enabledCategories != null && message.enabledCategories.length)
                    for (var i = 0; i < message.enabledCategories.length; ++i)
                        writer.uint32(/* id 2, wireType 2 =*/18).string(message.enabledCategories[i]);
                if (message.disabledTags != null && message.disabledTags.length)
                    for (var i = 0; i < message.disabledTags.length; ++i)
                        writer.uint32(/* id 3, wireType 2 =*/26).string(message.disabledTags[i]);
                if (message.enabledTags != null && message.enabledTags.length)
                    for (var i = 0; i < message.enabledTags.length; ++i)
                        writer.uint32(/* id 4, wireType 2 =*/34).string(message.enabledTags[i]);
                return writer;
            };

            /**
             * Encodes the specified TrackEventConfig message, length delimited. Does not implicitly {@link perfetto.protos.TrackEventConfig.verify|verify} messages.
             * @function encodeDelimited
             * @memberof perfetto.protos.TrackEventConfig
             * @static
             * @param {perfetto.protos.ITrackEventConfig} message TrackEventConfig message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            TrackEventConfig.encodeDelimited = function encodeDelimited(message, writer) {
                return this.encode(message, writer).ldelim();
            };

            /**
             * Decodes a TrackEventConfig message from the specified reader or buffer.
             * @function decode
             * @memberof perfetto.protos.TrackEventConfig
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @param {number} [length] Message length if known beforehand
             * @returns {perfetto.protos.TrackEventConfig} TrackEventConfig
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            TrackEventConfig.decode = function decode(reader, length) {
                if (!(reader instanceof $Reader))
                    reader = $Reader.create(reader);
                var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.TrackEventConfig();
                while (reader.pos < end) {
                    var tag = reader.uint32();
                    switch (tag >>> 3) {
                    case 1:
                        if (!(message.disabledCategories && message.disabledCategories.length))
                            message.disabledCategories = [];
                        message.disabledCategories.push(reader.string());
                        break;
                    case 2:
                        if (!(message.enabledCategories && message.enabledCategories.length))
                            message.enabledCategories = [];
                        message.enabledCategories.push(reader.string());
                        break;
                    case 3:
                        if (!(message.disabledTags && message.disabledTags.length))
                            message.disabledTags = [];
                        message.disabledTags.push(reader.string());
                        break;
                    case 4:
                        if (!(message.enabledTags && message.enabledTags.length))
                            message.enabledTags = [];
                        message.enabledTags.push(reader.string());
                        break;
                    default:
                        reader.skipType(tag & 7);
                        break;
                    }
                }
                return message;
            };

            /**
             * Decodes a TrackEventConfig message from the specified reader or buffer, length delimited.
             * @function decodeDelimited
             * @memberof perfetto.protos.TrackEventConfig
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @returns {perfetto.protos.TrackEventConfig} TrackEventConfig
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            TrackEventConfig.decodeDelimited = function decodeDelimited(reader) {
                if (!(reader instanceof $Reader))
                    reader = new $Reader(reader);
                return this.decode(reader, reader.uint32());
            };

            /**
             * Verifies a TrackEventConfig message.
             * @function verify
             * @memberof perfetto.protos.TrackEventConfig
             * @static
             * @param {Object.<string,*>} message Plain object to verify
             * @returns {string|null} `null` if valid, otherwise the reason why it is not
             */
            TrackEventConfig.verify = function verify(message) {
                if (typeof message !== "object" || message === null)
                    return "object expected";
                if (message.disabledCategories != null && message.hasOwnProperty("disabledCategories")) {
                    if (!Array.isArray(message.disabledCategories))
                        return "disabledCategories: array expected";
                    for (var i = 0; i < message.disabledCategories.length; ++i)
                        if (!$util.isString(message.disabledCategories[i]))
                            return "disabledCategories: string[] expected";
                }
                if (message.enabledCategories != null && message.hasOwnProperty("enabledCategories")) {
                    if (!Array.isArray(message.enabledCategories))
                        return "enabledCategories: array expected";
                    for (var i = 0; i < message.enabledCategories.length; ++i)
                        if (!$util.isString(message.enabledCategories[i]))
                            return "enabledCategories: string[] expected";
                }
                if (message.disabledTags != null && message.hasOwnProperty("disabledTags")) {
                    if (!Array.isArray(message.disabledTags))
                        return "disabledTags: array expected";
                    for (var i = 0; i < message.disabledTags.length; ++i)
                        if (!$util.isString(message.disabledTags[i]))
                            return "disabledTags: string[] expected";
                }
                if (message.enabledTags != null && message.hasOwnProperty("enabledTags")) {
                    if (!Array.isArray(message.enabledTags))
                        return "enabledTags: array expected";
                    for (var i = 0; i < message.enabledTags.length; ++i)
                        if (!$util.isString(message.enabledTags[i]))
                            return "enabledTags: string[] expected";
                }
                return null;
            };

            /**
             * Creates a TrackEventConfig message from a plain object. Also converts values to their respective internal types.
             * @function fromObject
             * @memberof perfetto.protos.TrackEventConfig
             * @static
             * @param {Object.<string,*>} object Plain object
             * @returns {perfetto.protos.TrackEventConfig} TrackEventConfig
             */
            TrackEventConfig.fromObject = function fromObject(object) {
                if (object instanceof $root.perfetto.protos.TrackEventConfig)
                    return object;
                var message = new $root.perfetto.protos.TrackEventConfig();
                if (object.disabledCategories) {
                    if (!Array.isArray(object.disabledCategories))
                        throw TypeError(".perfetto.protos.TrackEventConfig.disabledCategories: array expected");
                    message.disabledCategories = [];
                    for (var i = 0; i < object.disabledCategories.length; ++i)
                        message.disabledCategories[i] = String(object.disabledCategories[i]);
                }
                if (object.enabledCategories) {
                    if (!Array.isArray(object.enabledCategories))
                        throw TypeError(".perfetto.protos.TrackEventConfig.enabledCategories: array expected");
                    message.enabledCategories = [];
                    for (var i = 0; i < object.enabledCategories.length; ++i)
                        message.enabledCategories[i] = String(object.enabledCategories[i]);
                }
                if (object.disabledTags) {
                    if (!Array.isArray(object.disabledTags))
                        throw TypeError(".perfetto.protos.TrackEventConfig.disabledTags: array expected");
                    message.disabledTags = [];
                    for (var i = 0; i < object.disabledTags.length; ++i)
                        message.disabledTags[i] = String(object.disabledTags[i]);
                }
                if (object.enabledTags) {
                    if (!Array.isArray(object.enabledTags))
                        throw TypeError(".perfetto.protos.TrackEventConfig.enabledTags: array expected");
                    message.enabledTags = [];
                    for (var i = 0; i < object.enabledTags.length; ++i)
                        message.enabledTags[i] = String(object.enabledTags[i]);
                }
                return message;
            };

            /**
             * Creates a plain object from a TrackEventConfig message. Also converts values to other types if specified.
             * @function toObject
             * @memberof perfetto.protos.TrackEventConfig
             * @static
             * @param {perfetto.protos.TrackEventConfig} message TrackEventConfig
             * @param {$protobuf.IConversionOptions} [options] Conversion options
             * @returns {Object.<string,*>} Plain object
             */
            TrackEventConfig.toObject = function toObject(message, options) {
                if (!options)
                    options = {};
                var object = {};
                if (options.arrays || options.defaults) {
                    object.disabledCategories = [];
                    object.enabledCategories = [];
                    object.disabledTags = [];
                    object.enabledTags = [];
                }
                if (message.disabledCategories && message.disabledCategories.length) {
                    object.disabledCategories = [];
                    for (var j = 0; j < message.disabledCategories.length; ++j)
                        object.disabledCategories[j] = message.disabledCategories[j];
                }
                if (message.enabledCategories && message.enabledCategories.length) {
                    object.enabledCategories = [];
                    for (var j = 0; j < message.enabledCategories.length; ++j)
                        object.enabledCategories[j] = message.enabledCategories[j];
                }
                if (message.disabledTags && message.disabledTags.length) {
                    object.disabledTags = [];
                    for (var j = 0; j < message.disabledTags.length; ++j)
                        object.disabledTags[j] = message.disabledTags[j];
                }
                if (message.enabledTags && message.enabledTags.length) {
                    object.enabledTags = [];
                    for (var j = 0; j < message.enabledTags.length; ++j)
                        object.enabledTags[j] = message.enabledTags[j];
                }
                return object;
            };

            /**
             * Converts this TrackEventConfig to JSON.
             * @function toJSON
             * @memberof perfetto.protos.TrackEventConfig
             * @instance
             * @returns {Object.<string,*>} JSON object
             */
            TrackEventConfig.prototype.toJSON = function toJSON() {
                return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
            };

            return TrackEventConfig;
        })();

        protos.DataSourceConfig = (function() {

            /**
             * Properties of a DataSourceConfig.
             * @memberof perfetto.protos
             * @interface IDataSourceConfig
             * @property {string|null} [name] DataSourceConfig name
             * @property {number|null} [targetBuffer] DataSourceConfig targetBuffer
             * @property {number|null} [traceDurationMs] DataSourceConfig traceDurationMs
             * @property {number|null} [stopTimeoutMs] DataSourceConfig stopTimeoutMs
             * @property {boolean|null} [enableExtraGuardrails] DataSourceConfig enableExtraGuardrails
             * @property {perfetto.protos.DataSourceConfig.SessionInitiator|null} [sessionInitiator] DataSourceConfig sessionInitiator
             * @property {number|null} [tracingSessionId] DataSourceConfig tracingSessionId
             * @property {perfetto.protos.IFtraceConfig|null} [ftraceConfig] DataSourceConfig ftraceConfig
             * @property {perfetto.protos.IInodeFileConfig|null} [inodeFileConfig] DataSourceConfig inodeFileConfig
             * @property {perfetto.protos.IProcessStatsConfig|null} [processStatsConfig] DataSourceConfig processStatsConfig
             * @property {perfetto.protos.ISysStatsConfig|null} [sysStatsConfig] DataSourceConfig sysStatsConfig
             * @property {perfetto.protos.IHeapprofdConfig|null} [heapprofdConfig] DataSourceConfig heapprofdConfig
             * @property {perfetto.protos.IJavaHprofConfig|null} [javaHprofConfig] DataSourceConfig javaHprofConfig
             * @property {perfetto.protos.IAndroidPowerConfig|null} [androidPowerConfig] DataSourceConfig androidPowerConfig
             * @property {perfetto.protos.IAndroidLogConfig|null} [androidLogConfig] DataSourceConfig androidLogConfig
             * @property {perfetto.protos.IGpuCounterConfig|null} [gpuCounterConfig] DataSourceConfig gpuCounterConfig
             * @property {perfetto.protos.IPackagesListConfig|null} [packagesListConfig] DataSourceConfig packagesListConfig
             * @property {perfetto.protos.IPerfEventConfig|null} [perfEventConfig] DataSourceConfig perfEventConfig
             * @property {perfetto.protos.IVulkanMemoryConfig|null} [vulkanMemoryConfig] DataSourceConfig vulkanMemoryConfig
             * @property {perfetto.protos.ITrackEventConfig|null} [trackEventConfig] DataSourceConfig trackEventConfig
             * @property {perfetto.protos.IAndroidPolledStateConfig|null} [androidPolledStateConfig] DataSourceConfig androidPolledStateConfig
             * @property {perfetto.protos.IChromeConfig|null} [chromeConfig] DataSourceConfig chromeConfig
             * @property {perfetto.protos.IInterceptorConfig|null} [interceptorConfig] DataSourceConfig interceptorConfig
             * @property {string|null} [legacyConfig] DataSourceConfig legacyConfig
             * @property {perfetto.protos.ITestConfig|null} [forTesting] DataSourceConfig forTesting
             */

            /**
             * Constructs a new DataSourceConfig.
             * @memberof perfetto.protos
             * @classdesc Represents a DataSourceConfig.
             * @implements IDataSourceConfig
             * @constructor
             * @param {perfetto.protos.IDataSourceConfig=} [properties] Properties to set
             */
            function DataSourceConfig(properties) {
                if (properties)
                    for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                        if (properties[keys[i]] != null)
                            this[keys[i]] = properties[keys[i]];
            }

            /**
             * DataSourceConfig name.
             * @member {string} name
             * @memberof perfetto.protos.DataSourceConfig
             * @instance
             */
            DataSourceConfig.prototype.name = "";

            /**
             * DataSourceConfig targetBuffer.
             * @member {number} targetBuffer
             * @memberof perfetto.protos.DataSourceConfig
             * @instance
             */
            DataSourceConfig.prototype.targetBuffer = 0;

            /**
             * DataSourceConfig traceDurationMs.
             * @member {number} traceDurationMs
             * @memberof perfetto.protos.DataSourceConfig
             * @instance
             */
            DataSourceConfig.prototype.traceDurationMs = 0;

            /**
             * DataSourceConfig stopTimeoutMs.
             * @member {number} stopTimeoutMs
             * @memberof perfetto.protos.DataSourceConfig
             * @instance
             */
            DataSourceConfig.prototype.stopTimeoutMs = 0;

            /**
             * DataSourceConfig enableExtraGuardrails.
             * @member {boolean} enableExtraGuardrails
             * @memberof perfetto.protos.DataSourceConfig
             * @instance
             */
            DataSourceConfig.prototype.enableExtraGuardrails = false;

            /**
             * DataSourceConfig sessionInitiator.
             * @member {perfetto.protos.DataSourceConfig.SessionInitiator} sessionInitiator
             * @memberof perfetto.protos.DataSourceConfig
             * @instance
             */
            DataSourceConfig.prototype.sessionInitiator = 0;

            /**
             * DataSourceConfig tracingSessionId.
             * @member {number} tracingSessionId
             * @memberof perfetto.protos.DataSourceConfig
             * @instance
             */
            DataSourceConfig.prototype.tracingSessionId = $util.Long ? $util.Long.fromBits(0,0,true) : 0;

            /**
             * DataSourceConfig ftraceConfig.
             * @member {perfetto.protos.IFtraceConfig|null|undefined} ftraceConfig
             * @memberof perfetto.protos.DataSourceConfig
             * @instance
             */
            DataSourceConfig.prototype.ftraceConfig = null;

            /**
             * DataSourceConfig inodeFileConfig.
             * @member {perfetto.protos.IInodeFileConfig|null|undefined} inodeFileConfig
             * @memberof perfetto.protos.DataSourceConfig
             * @instance
             */
            DataSourceConfig.prototype.inodeFileConfig = null;

            /**
             * DataSourceConfig processStatsConfig.
             * @member {perfetto.protos.IProcessStatsConfig|null|undefined} processStatsConfig
             * @memberof perfetto.protos.DataSourceConfig
             * @instance
             */
            DataSourceConfig.prototype.processStatsConfig = null;

            /**
             * DataSourceConfig sysStatsConfig.
             * @member {perfetto.protos.ISysStatsConfig|null|undefined} sysStatsConfig
             * @memberof perfetto.protos.DataSourceConfig
             * @instance
             */
            DataSourceConfig.prototype.sysStatsConfig = null;

            /**
             * DataSourceConfig heapprofdConfig.
             * @member {perfetto.protos.IHeapprofdConfig|null|undefined} heapprofdConfig
             * @memberof perfetto.protos.DataSourceConfig
             * @instance
             */
            DataSourceConfig.prototype.heapprofdConfig = null;

            /**
             * DataSourceConfig javaHprofConfig.
             * @member {perfetto.protos.IJavaHprofConfig|null|undefined} javaHprofConfig
             * @memberof perfetto.protos.DataSourceConfig
             * @instance
             */
            DataSourceConfig.prototype.javaHprofConfig = null;

            /**
             * DataSourceConfig androidPowerConfig.
             * @member {perfetto.protos.IAndroidPowerConfig|null|undefined} androidPowerConfig
             * @memberof perfetto.protos.DataSourceConfig
             * @instance
             */
            DataSourceConfig.prototype.androidPowerConfig = null;

            /**
             * DataSourceConfig androidLogConfig.
             * @member {perfetto.protos.IAndroidLogConfig|null|undefined} androidLogConfig
             * @memberof perfetto.protos.DataSourceConfig
             * @instance
             */
            DataSourceConfig.prototype.androidLogConfig = null;

            /**
             * DataSourceConfig gpuCounterConfig.
             * @member {perfetto.protos.IGpuCounterConfig|null|undefined} gpuCounterConfig
             * @memberof perfetto.protos.DataSourceConfig
             * @instance
             */
            DataSourceConfig.prototype.gpuCounterConfig = null;

            /**
             * DataSourceConfig packagesListConfig.
             * @member {perfetto.protos.IPackagesListConfig|null|undefined} packagesListConfig
             * @memberof perfetto.protos.DataSourceConfig
             * @instance
             */
            DataSourceConfig.prototype.packagesListConfig = null;

            /**
             * DataSourceConfig perfEventConfig.
             * @member {perfetto.protos.IPerfEventConfig|null|undefined} perfEventConfig
             * @memberof perfetto.protos.DataSourceConfig
             * @instance
             */
            DataSourceConfig.prototype.perfEventConfig = null;

            /**
             * DataSourceConfig vulkanMemoryConfig.
             * @member {perfetto.protos.IVulkanMemoryConfig|null|undefined} vulkanMemoryConfig
             * @memberof perfetto.protos.DataSourceConfig
             * @instance
             */
            DataSourceConfig.prototype.vulkanMemoryConfig = null;

            /**
             * DataSourceConfig trackEventConfig.
             * @member {perfetto.protos.ITrackEventConfig|null|undefined} trackEventConfig
             * @memberof perfetto.protos.DataSourceConfig
             * @instance
             */
            DataSourceConfig.prototype.trackEventConfig = null;

            /**
             * DataSourceConfig androidPolledStateConfig.
             * @member {perfetto.protos.IAndroidPolledStateConfig|null|undefined} androidPolledStateConfig
             * @memberof perfetto.protos.DataSourceConfig
             * @instance
             */
            DataSourceConfig.prototype.androidPolledStateConfig = null;

            /**
             * DataSourceConfig chromeConfig.
             * @member {perfetto.protos.IChromeConfig|null|undefined} chromeConfig
             * @memberof perfetto.protos.DataSourceConfig
             * @instance
             */
            DataSourceConfig.prototype.chromeConfig = null;

            /**
             * DataSourceConfig interceptorConfig.
             * @member {perfetto.protos.IInterceptorConfig|null|undefined} interceptorConfig
             * @memberof perfetto.protos.DataSourceConfig
             * @instance
             */
            DataSourceConfig.prototype.interceptorConfig = null;

            /**
             * DataSourceConfig legacyConfig.
             * @member {string} legacyConfig
             * @memberof perfetto.protos.DataSourceConfig
             * @instance
             */
            DataSourceConfig.prototype.legacyConfig = "";

            /**
             * DataSourceConfig forTesting.
             * @member {perfetto.protos.ITestConfig|null|undefined} forTesting
             * @memberof perfetto.protos.DataSourceConfig
             * @instance
             */
            DataSourceConfig.prototype.forTesting = null;

            /**
             * Creates a new DataSourceConfig instance using the specified properties.
             * @function create
             * @memberof perfetto.protos.DataSourceConfig
             * @static
             * @param {perfetto.protos.IDataSourceConfig=} [properties] Properties to set
             * @returns {perfetto.protos.DataSourceConfig} DataSourceConfig instance
             */
            DataSourceConfig.create = function create(properties) {
                return new DataSourceConfig(properties);
            };

            /**
             * Encodes the specified DataSourceConfig message. Does not implicitly {@link perfetto.protos.DataSourceConfig.verify|verify} messages.
             * @function encode
             * @memberof perfetto.protos.DataSourceConfig
             * @static
             * @param {perfetto.protos.IDataSourceConfig} message DataSourceConfig message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            DataSourceConfig.encode = function encode(message, writer) {
                if (!writer)
                    writer = $Writer.create();
                if (message.name != null && Object.hasOwnProperty.call(message, "name"))
                    writer.uint32(/* id 1, wireType 2 =*/10).string(message.name);
                if (message.targetBuffer != null && Object.hasOwnProperty.call(message, "targetBuffer"))
                    writer.uint32(/* id 2, wireType 0 =*/16).uint32(message.targetBuffer);
                if (message.traceDurationMs != null && Object.hasOwnProperty.call(message, "traceDurationMs"))
                    writer.uint32(/* id 3, wireType 0 =*/24).uint32(message.traceDurationMs);
                if (message.tracingSessionId != null && Object.hasOwnProperty.call(message, "tracingSessionId"))
                    writer.uint32(/* id 4, wireType 0 =*/32).uint64(message.tracingSessionId);
                if (message.enableExtraGuardrails != null && Object.hasOwnProperty.call(message, "enableExtraGuardrails"))
                    writer.uint32(/* id 6, wireType 0 =*/48).bool(message.enableExtraGuardrails);
                if (message.stopTimeoutMs != null && Object.hasOwnProperty.call(message, "stopTimeoutMs"))
                    writer.uint32(/* id 7, wireType 0 =*/56).uint32(message.stopTimeoutMs);
                if (message.sessionInitiator != null && Object.hasOwnProperty.call(message, "sessionInitiator"))
                    writer.uint32(/* id 8, wireType 0 =*/64).int32(message.sessionInitiator);
                if (message.ftraceConfig != null && Object.hasOwnProperty.call(message, "ftraceConfig"))
                    $root.perfetto.protos.FtraceConfig.encode(message.ftraceConfig, writer.uint32(/* id 100, wireType 2 =*/802).fork()).ldelim();
                if (message.chromeConfig != null && Object.hasOwnProperty.call(message, "chromeConfig"))
                    $root.perfetto.protos.ChromeConfig.encode(message.chromeConfig, writer.uint32(/* id 101, wireType 2 =*/810).fork()).ldelim();
                if (message.inodeFileConfig != null && Object.hasOwnProperty.call(message, "inodeFileConfig"))
                    $root.perfetto.protos.InodeFileConfig.encode(message.inodeFileConfig, writer.uint32(/* id 102, wireType 2 =*/818).fork()).ldelim();
                if (message.processStatsConfig != null && Object.hasOwnProperty.call(message, "processStatsConfig"))
                    $root.perfetto.protos.ProcessStatsConfig.encode(message.processStatsConfig, writer.uint32(/* id 103, wireType 2 =*/826).fork()).ldelim();
                if (message.sysStatsConfig != null && Object.hasOwnProperty.call(message, "sysStatsConfig"))
                    $root.perfetto.protos.SysStatsConfig.encode(message.sysStatsConfig, writer.uint32(/* id 104, wireType 2 =*/834).fork()).ldelim();
                if (message.heapprofdConfig != null && Object.hasOwnProperty.call(message, "heapprofdConfig"))
                    $root.perfetto.protos.HeapprofdConfig.encode(message.heapprofdConfig, writer.uint32(/* id 105, wireType 2 =*/842).fork()).ldelim();
                if (message.androidPowerConfig != null && Object.hasOwnProperty.call(message, "androidPowerConfig"))
                    $root.perfetto.protos.AndroidPowerConfig.encode(message.androidPowerConfig, writer.uint32(/* id 106, wireType 2 =*/850).fork()).ldelim();
                if (message.androidLogConfig != null && Object.hasOwnProperty.call(message, "androidLogConfig"))
                    $root.perfetto.protos.AndroidLogConfig.encode(message.androidLogConfig, writer.uint32(/* id 107, wireType 2 =*/858).fork()).ldelim();
                if (message.gpuCounterConfig != null && Object.hasOwnProperty.call(message, "gpuCounterConfig"))
                    $root.perfetto.protos.GpuCounterConfig.encode(message.gpuCounterConfig, writer.uint32(/* id 108, wireType 2 =*/866).fork()).ldelim();
                if (message.packagesListConfig != null && Object.hasOwnProperty.call(message, "packagesListConfig"))
                    $root.perfetto.protos.PackagesListConfig.encode(message.packagesListConfig, writer.uint32(/* id 109, wireType 2 =*/874).fork()).ldelim();
                if (message.javaHprofConfig != null && Object.hasOwnProperty.call(message, "javaHprofConfig"))
                    $root.perfetto.protos.JavaHprofConfig.encode(message.javaHprofConfig, writer.uint32(/* id 110, wireType 2 =*/882).fork()).ldelim();
                if (message.perfEventConfig != null && Object.hasOwnProperty.call(message, "perfEventConfig"))
                    $root.perfetto.protos.PerfEventConfig.encode(message.perfEventConfig, writer.uint32(/* id 111, wireType 2 =*/890).fork()).ldelim();
                if (message.vulkanMemoryConfig != null && Object.hasOwnProperty.call(message, "vulkanMemoryConfig"))
                    $root.perfetto.protos.VulkanMemoryConfig.encode(message.vulkanMemoryConfig, writer.uint32(/* id 112, wireType 2 =*/898).fork()).ldelim();
                if (message.trackEventConfig != null && Object.hasOwnProperty.call(message, "trackEventConfig"))
                    $root.perfetto.protos.TrackEventConfig.encode(message.trackEventConfig, writer.uint32(/* id 113, wireType 2 =*/906).fork()).ldelim();
                if (message.androidPolledStateConfig != null && Object.hasOwnProperty.call(message, "androidPolledStateConfig"))
                    $root.perfetto.protos.AndroidPolledStateConfig.encode(message.androidPolledStateConfig, writer.uint32(/* id 114, wireType 2 =*/914).fork()).ldelim();
                if (message.interceptorConfig != null && Object.hasOwnProperty.call(message, "interceptorConfig"))
                    $root.perfetto.protos.InterceptorConfig.encode(message.interceptorConfig, writer.uint32(/* id 115, wireType 2 =*/922).fork()).ldelim();
                if (message.legacyConfig != null && Object.hasOwnProperty.call(message, "legacyConfig"))
                    writer.uint32(/* id 1000, wireType 2 =*/8002).string(message.legacyConfig);
                if (message.forTesting != null && Object.hasOwnProperty.call(message, "forTesting"))
                    $root.perfetto.protos.TestConfig.encode(message.forTesting, writer.uint32(/* id 1001, wireType 2 =*/8010).fork()).ldelim();
                return writer;
            };

            /**
             * Encodes the specified DataSourceConfig message, length delimited. Does not implicitly {@link perfetto.protos.DataSourceConfig.verify|verify} messages.
             * @function encodeDelimited
             * @memberof perfetto.protos.DataSourceConfig
             * @static
             * @param {perfetto.protos.IDataSourceConfig} message DataSourceConfig message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            DataSourceConfig.encodeDelimited = function encodeDelimited(message, writer) {
                return this.encode(message, writer).ldelim();
            };

            /**
             * Decodes a DataSourceConfig message from the specified reader or buffer.
             * @function decode
             * @memberof perfetto.protos.DataSourceConfig
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @param {number} [length] Message length if known beforehand
             * @returns {perfetto.protos.DataSourceConfig} DataSourceConfig
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            DataSourceConfig.decode = function decode(reader, length) {
                if (!(reader instanceof $Reader))
                    reader = $Reader.create(reader);
                var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.DataSourceConfig();
                while (reader.pos < end) {
                    var tag = reader.uint32();
                    switch (tag >>> 3) {
                    case 1:
                        message.name = reader.string();
                        break;
                    case 2:
                        message.targetBuffer = reader.uint32();
                        break;
                    case 3:
                        message.traceDurationMs = reader.uint32();
                        break;
                    case 7:
                        message.stopTimeoutMs = reader.uint32();
                        break;
                    case 6:
                        message.enableExtraGuardrails = reader.bool();
                        break;
                    case 8:
                        message.sessionInitiator = reader.int32();
                        break;
                    case 4:
                        message.tracingSessionId = reader.uint64();
                        break;
                    case 100:
                        message.ftraceConfig = $root.perfetto.protos.FtraceConfig.decode(reader, reader.uint32());
                        break;
                    case 102:
                        message.inodeFileConfig = $root.perfetto.protos.InodeFileConfig.decode(reader, reader.uint32());
                        break;
                    case 103:
                        message.processStatsConfig = $root.perfetto.protos.ProcessStatsConfig.decode(reader, reader.uint32());
                        break;
                    case 104:
                        message.sysStatsConfig = $root.perfetto.protos.SysStatsConfig.decode(reader, reader.uint32());
                        break;
                    case 105:
                        message.heapprofdConfig = $root.perfetto.protos.HeapprofdConfig.decode(reader, reader.uint32());
                        break;
                    case 110:
                        message.javaHprofConfig = $root.perfetto.protos.JavaHprofConfig.decode(reader, reader.uint32());
                        break;
                    case 106:
                        message.androidPowerConfig = $root.perfetto.protos.AndroidPowerConfig.decode(reader, reader.uint32());
                        break;
                    case 107:
                        message.androidLogConfig = $root.perfetto.protos.AndroidLogConfig.decode(reader, reader.uint32());
                        break;
                    case 108:
                        message.gpuCounterConfig = $root.perfetto.protos.GpuCounterConfig.decode(reader, reader.uint32());
                        break;
                    case 109:
                        message.packagesListConfig = $root.perfetto.protos.PackagesListConfig.decode(reader, reader.uint32());
                        break;
                    case 111:
                        message.perfEventConfig = $root.perfetto.protos.PerfEventConfig.decode(reader, reader.uint32());
                        break;
                    case 112:
                        message.vulkanMemoryConfig = $root.perfetto.protos.VulkanMemoryConfig.decode(reader, reader.uint32());
                        break;
                    case 113:
                        message.trackEventConfig = $root.perfetto.protos.TrackEventConfig.decode(reader, reader.uint32());
                        break;
                    case 114:
                        message.androidPolledStateConfig = $root.perfetto.protos.AndroidPolledStateConfig.decode(reader, reader.uint32());
                        break;
                    case 101:
                        message.chromeConfig = $root.perfetto.protos.ChromeConfig.decode(reader, reader.uint32());
                        break;
                    case 115:
                        message.interceptorConfig = $root.perfetto.protos.InterceptorConfig.decode(reader, reader.uint32());
                        break;
                    case 1000:
                        message.legacyConfig = reader.string();
                        break;
                    case 1001:
                        message.forTesting = $root.perfetto.protos.TestConfig.decode(reader, reader.uint32());
                        break;
                    default:
                        reader.skipType(tag & 7);
                        break;
                    }
                }
                return message;
            };

            /**
             * Decodes a DataSourceConfig message from the specified reader or buffer, length delimited.
             * @function decodeDelimited
             * @memberof perfetto.protos.DataSourceConfig
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @returns {perfetto.protos.DataSourceConfig} DataSourceConfig
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            DataSourceConfig.decodeDelimited = function decodeDelimited(reader) {
                if (!(reader instanceof $Reader))
                    reader = new $Reader(reader);
                return this.decode(reader, reader.uint32());
            };

            /**
             * Verifies a DataSourceConfig message.
             * @function verify
             * @memberof perfetto.protos.DataSourceConfig
             * @static
             * @param {Object.<string,*>} message Plain object to verify
             * @returns {string|null} `null` if valid, otherwise the reason why it is not
             */
            DataSourceConfig.verify = function verify(message) {
                if (typeof message !== "object" || message === null)
                    return "object expected";
                if (message.name != null && message.hasOwnProperty("name"))
                    if (!$util.isString(message.name))
                        return "name: string expected";
                if (message.targetBuffer != null && message.hasOwnProperty("targetBuffer"))
                    if (!$util.isInteger(message.targetBuffer))
                        return "targetBuffer: integer expected";
                if (message.traceDurationMs != null && message.hasOwnProperty("traceDurationMs"))
                    if (!$util.isInteger(message.traceDurationMs))
                        return "traceDurationMs: integer expected";
                if (message.stopTimeoutMs != null && message.hasOwnProperty("stopTimeoutMs"))
                    if (!$util.isInteger(message.stopTimeoutMs))
                        return "stopTimeoutMs: integer expected";
                if (message.enableExtraGuardrails != null && message.hasOwnProperty("enableExtraGuardrails"))
                    if (typeof message.enableExtraGuardrails !== "boolean")
                        return "enableExtraGuardrails: boolean expected";
                if (message.sessionInitiator != null && message.hasOwnProperty("sessionInitiator"))
                    switch (message.sessionInitiator) {
                    default:
                        return "sessionInitiator: enum value expected";
                    case 0:
                    case 1:
                        break;
                    }
                if (message.tracingSessionId != null && message.hasOwnProperty("tracingSessionId"))
                    if (!$util.isInteger(message.tracingSessionId) && !(message.tracingSessionId && $util.isInteger(message.tracingSessionId.low) && $util.isInteger(message.tracingSessionId.high)))
                        return "tracingSessionId: integer|Long expected";
                if (message.ftraceConfig != null && message.hasOwnProperty("ftraceConfig")) {
                    var error = $root.perfetto.protos.FtraceConfig.verify(message.ftraceConfig);
                    if (error)
                        return "ftraceConfig." + error;
                }
                if (message.inodeFileConfig != null && message.hasOwnProperty("inodeFileConfig")) {
                    var error = $root.perfetto.protos.InodeFileConfig.verify(message.inodeFileConfig);
                    if (error)
                        return "inodeFileConfig." + error;
                }
                if (message.processStatsConfig != null && message.hasOwnProperty("processStatsConfig")) {
                    var error = $root.perfetto.protos.ProcessStatsConfig.verify(message.processStatsConfig);
                    if (error)
                        return "processStatsConfig." + error;
                }
                if (message.sysStatsConfig != null && message.hasOwnProperty("sysStatsConfig")) {
                    var error = $root.perfetto.protos.SysStatsConfig.verify(message.sysStatsConfig);
                    if (error)
                        return "sysStatsConfig." + error;
                }
                if (message.heapprofdConfig != null && message.hasOwnProperty("heapprofdConfig")) {
                    var error = $root.perfetto.protos.HeapprofdConfig.verify(message.heapprofdConfig);
                    if (error)
                        return "heapprofdConfig." + error;
                }
                if (message.javaHprofConfig != null && message.hasOwnProperty("javaHprofConfig")) {
                    var error = $root.perfetto.protos.JavaHprofConfig.verify(message.javaHprofConfig);
                    if (error)
                        return "javaHprofConfig." + error;
                }
                if (message.androidPowerConfig != null && message.hasOwnProperty("androidPowerConfig")) {
                    var error = $root.perfetto.protos.AndroidPowerConfig.verify(message.androidPowerConfig);
                    if (error)
                        return "androidPowerConfig." + error;
                }
                if (message.androidLogConfig != null && message.hasOwnProperty("androidLogConfig")) {
                    var error = $root.perfetto.protos.AndroidLogConfig.verify(message.androidLogConfig);
                    if (error)
                        return "androidLogConfig." + error;
                }
                if (message.gpuCounterConfig != null && message.hasOwnProperty("gpuCounterConfig")) {
                    var error = $root.perfetto.protos.GpuCounterConfig.verify(message.gpuCounterConfig);
                    if (error)
                        return "gpuCounterConfig." + error;
                }
                if (message.packagesListConfig != null && message.hasOwnProperty("packagesListConfig")) {
                    var error = $root.perfetto.protos.PackagesListConfig.verify(message.packagesListConfig);
                    if (error)
                        return "packagesListConfig." + error;
                }
                if (message.perfEventConfig != null && message.hasOwnProperty("perfEventConfig")) {
                    var error = $root.perfetto.protos.PerfEventConfig.verify(message.perfEventConfig);
                    if (error)
                        return "perfEventConfig." + error;
                }
                if (message.vulkanMemoryConfig != null && message.hasOwnProperty("vulkanMemoryConfig")) {
                    var error = $root.perfetto.protos.VulkanMemoryConfig.verify(message.vulkanMemoryConfig);
                    if (error)
                        return "vulkanMemoryConfig." + error;
                }
                if (message.trackEventConfig != null && message.hasOwnProperty("trackEventConfig")) {
                    var error = $root.perfetto.protos.TrackEventConfig.verify(message.trackEventConfig);
                    if (error)
                        return "trackEventConfig." + error;
                }
                if (message.androidPolledStateConfig != null && message.hasOwnProperty("androidPolledStateConfig")) {
                    var error = $root.perfetto.protos.AndroidPolledStateConfig.verify(message.androidPolledStateConfig);
                    if (error)
                        return "androidPolledStateConfig." + error;
                }
                if (message.chromeConfig != null && message.hasOwnProperty("chromeConfig")) {
                    var error = $root.perfetto.protos.ChromeConfig.verify(message.chromeConfig);
                    if (error)
                        return "chromeConfig." + error;
                }
                if (message.interceptorConfig != null && message.hasOwnProperty("interceptorConfig")) {
                    var error = $root.perfetto.protos.InterceptorConfig.verify(message.interceptorConfig);
                    if (error)
                        return "interceptorConfig." + error;
                }
                if (message.legacyConfig != null && message.hasOwnProperty("legacyConfig"))
                    if (!$util.isString(message.legacyConfig))
                        return "legacyConfig: string expected";
                if (message.forTesting != null && message.hasOwnProperty("forTesting")) {
                    var error = $root.perfetto.protos.TestConfig.verify(message.forTesting);
                    if (error)
                        return "forTesting." + error;
                }
                return null;
            };

            /**
             * Creates a DataSourceConfig message from a plain object. Also converts values to their respective internal types.
             * @function fromObject
             * @memberof perfetto.protos.DataSourceConfig
             * @static
             * @param {Object.<string,*>} object Plain object
             * @returns {perfetto.protos.DataSourceConfig} DataSourceConfig
             */
            DataSourceConfig.fromObject = function fromObject(object) {
                if (object instanceof $root.perfetto.protos.DataSourceConfig)
                    return object;
                var message = new $root.perfetto.protos.DataSourceConfig();
                if (object.name != null)
                    message.name = String(object.name);
                if (object.targetBuffer != null)
                    message.targetBuffer = object.targetBuffer >>> 0;
                if (object.traceDurationMs != null)
                    message.traceDurationMs = object.traceDurationMs >>> 0;
                if (object.stopTimeoutMs != null)
                    message.stopTimeoutMs = object.stopTimeoutMs >>> 0;
                if (object.enableExtraGuardrails != null)
                    message.enableExtraGuardrails = Boolean(object.enableExtraGuardrails);
                switch (object.sessionInitiator) {
                case "SESSION_INITIATOR_UNSPECIFIED":
                case 0:
                    message.sessionInitiator = 0;
                    break;
                case "SESSION_INITIATOR_TRUSTED_SYSTEM":
                case 1:
                    message.sessionInitiator = 1;
                    break;
                }
                if (object.tracingSessionId != null)
                    if ($util.Long)
                        (message.tracingSessionId = $util.Long.fromValue(object.tracingSessionId)).unsigned = true;
                    else if (typeof object.tracingSessionId === "string")
                        message.tracingSessionId = parseInt(object.tracingSessionId, 10);
                    else if (typeof object.tracingSessionId === "number")
                        message.tracingSessionId = object.tracingSessionId;
                    else if (typeof object.tracingSessionId === "object")
                        message.tracingSessionId = new $util.LongBits(object.tracingSessionId.low >>> 0, object.tracingSessionId.high >>> 0).toNumber(true);
                if (object.ftraceConfig != null) {
                    if (typeof object.ftraceConfig !== "object")
                        throw TypeError(".perfetto.protos.DataSourceConfig.ftraceConfig: object expected");
                    message.ftraceConfig = $root.perfetto.protos.FtraceConfig.fromObject(object.ftraceConfig);
                }
                if (object.inodeFileConfig != null) {
                    if (typeof object.inodeFileConfig !== "object")
                        throw TypeError(".perfetto.protos.DataSourceConfig.inodeFileConfig: object expected");
                    message.inodeFileConfig = $root.perfetto.protos.InodeFileConfig.fromObject(object.inodeFileConfig);
                }
                if (object.processStatsConfig != null) {
                    if (typeof object.processStatsConfig !== "object")
                        throw TypeError(".perfetto.protos.DataSourceConfig.processStatsConfig: object expected");
                    message.processStatsConfig = $root.perfetto.protos.ProcessStatsConfig.fromObject(object.processStatsConfig);
                }
                if (object.sysStatsConfig != null) {
                    if (typeof object.sysStatsConfig !== "object")
                        throw TypeError(".perfetto.protos.DataSourceConfig.sysStatsConfig: object expected");
                    message.sysStatsConfig = $root.perfetto.protos.SysStatsConfig.fromObject(object.sysStatsConfig);
                }
                if (object.heapprofdConfig != null) {
                    if (typeof object.heapprofdConfig !== "object")
                        throw TypeError(".perfetto.protos.DataSourceConfig.heapprofdConfig: object expected");
                    message.heapprofdConfig = $root.perfetto.protos.HeapprofdConfig.fromObject(object.heapprofdConfig);
                }
                if (object.javaHprofConfig != null) {
                    if (typeof object.javaHprofConfig !== "object")
                        throw TypeError(".perfetto.protos.DataSourceConfig.javaHprofConfig: object expected");
                    message.javaHprofConfig = $root.perfetto.protos.JavaHprofConfig.fromObject(object.javaHprofConfig);
                }
                if (object.androidPowerConfig != null) {
                    if (typeof object.androidPowerConfig !== "object")
                        throw TypeError(".perfetto.protos.DataSourceConfig.androidPowerConfig: object expected");
                    message.androidPowerConfig = $root.perfetto.protos.AndroidPowerConfig.fromObject(object.androidPowerConfig);
                }
                if (object.androidLogConfig != null) {
                    if (typeof object.androidLogConfig !== "object")
                        throw TypeError(".perfetto.protos.DataSourceConfig.androidLogConfig: object expected");
                    message.androidLogConfig = $root.perfetto.protos.AndroidLogConfig.fromObject(object.androidLogConfig);
                }
                if (object.gpuCounterConfig != null) {
                    if (typeof object.gpuCounterConfig !== "object")
                        throw TypeError(".perfetto.protos.DataSourceConfig.gpuCounterConfig: object expected");
                    message.gpuCounterConfig = $root.perfetto.protos.GpuCounterConfig.fromObject(object.gpuCounterConfig);
                }
                if (object.packagesListConfig != null) {
                    if (typeof object.packagesListConfig !== "object")
                        throw TypeError(".perfetto.protos.DataSourceConfig.packagesListConfig: object expected");
                    message.packagesListConfig = $root.perfetto.protos.PackagesListConfig.fromObject(object.packagesListConfig);
                }
                if (object.perfEventConfig != null) {
                    if (typeof object.perfEventConfig !== "object")
                        throw TypeError(".perfetto.protos.DataSourceConfig.perfEventConfig: object expected");
                    message.perfEventConfig = $root.perfetto.protos.PerfEventConfig.fromObject(object.perfEventConfig);
                }
                if (object.vulkanMemoryConfig != null) {
                    if (typeof object.vulkanMemoryConfig !== "object")
                        throw TypeError(".perfetto.protos.DataSourceConfig.vulkanMemoryConfig: object expected");
                    message.vulkanMemoryConfig = $root.perfetto.protos.VulkanMemoryConfig.fromObject(object.vulkanMemoryConfig);
                }
                if (object.trackEventConfig != null) {
                    if (typeof object.trackEventConfig !== "object")
                        throw TypeError(".perfetto.protos.DataSourceConfig.trackEventConfig: object expected");
                    message.trackEventConfig = $root.perfetto.protos.TrackEventConfig.fromObject(object.trackEventConfig);
                }
                if (object.androidPolledStateConfig != null) {
                    if (typeof object.androidPolledStateConfig !== "object")
                        throw TypeError(".perfetto.protos.DataSourceConfig.androidPolledStateConfig: object expected");
                    message.androidPolledStateConfig = $root.perfetto.protos.AndroidPolledStateConfig.fromObject(object.androidPolledStateConfig);
                }
                if (object.chromeConfig != null) {
                    if (typeof object.chromeConfig !== "object")
                        throw TypeError(".perfetto.protos.DataSourceConfig.chromeConfig: object expected");
                    message.chromeConfig = $root.perfetto.protos.ChromeConfig.fromObject(object.chromeConfig);
                }
                if (object.interceptorConfig != null) {
                    if (typeof object.interceptorConfig !== "object")
                        throw TypeError(".perfetto.protos.DataSourceConfig.interceptorConfig: object expected");
                    message.interceptorConfig = $root.perfetto.protos.InterceptorConfig.fromObject(object.interceptorConfig);
                }
                if (object.legacyConfig != null)
                    message.legacyConfig = String(object.legacyConfig);
                if (object.forTesting != null) {
                    if (typeof object.forTesting !== "object")
                        throw TypeError(".perfetto.protos.DataSourceConfig.forTesting: object expected");
                    message.forTesting = $root.perfetto.protos.TestConfig.fromObject(object.forTesting);
                }
                return message;
            };

            /**
             * Creates a plain object from a DataSourceConfig message. Also converts values to other types if specified.
             * @function toObject
             * @memberof perfetto.protos.DataSourceConfig
             * @static
             * @param {perfetto.protos.DataSourceConfig} message DataSourceConfig
             * @param {$protobuf.IConversionOptions} [options] Conversion options
             * @returns {Object.<string,*>} Plain object
             */
            DataSourceConfig.toObject = function toObject(message, options) {
                if (!options)
                    options = {};
                var object = {};
                if (options.defaults) {
                    object.name = "";
                    object.targetBuffer = 0;
                    object.traceDurationMs = 0;
                    if ($util.Long) {
                        var long = new $util.Long(0, 0, true);
                        object.tracingSessionId = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
                    } else
                        object.tracingSessionId = options.longs === String ? "0" : 0;
                    object.enableExtraGuardrails = false;
                    object.stopTimeoutMs = 0;
                    object.sessionInitiator = options.enums === String ? "SESSION_INITIATOR_UNSPECIFIED" : 0;
                    object.ftraceConfig = null;
                    object.chromeConfig = null;
                    object.inodeFileConfig = null;
                    object.processStatsConfig = null;
                    object.sysStatsConfig = null;
                    object.heapprofdConfig = null;
                    object.androidPowerConfig = null;
                    object.androidLogConfig = null;
                    object.gpuCounterConfig = null;
                    object.packagesListConfig = null;
                    object.javaHprofConfig = null;
                    object.perfEventConfig = null;
                    object.vulkanMemoryConfig = null;
                    object.trackEventConfig = null;
                    object.androidPolledStateConfig = null;
                    object.interceptorConfig = null;
                    object.legacyConfig = "";
                    object.forTesting = null;
                }
                if (message.name != null && message.hasOwnProperty("name"))
                    object.name = message.name;
                if (message.targetBuffer != null && message.hasOwnProperty("targetBuffer"))
                    object.targetBuffer = message.targetBuffer;
                if (message.traceDurationMs != null && message.hasOwnProperty("traceDurationMs"))
                    object.traceDurationMs = message.traceDurationMs;
                if (message.tracingSessionId != null && message.hasOwnProperty("tracingSessionId"))
                    if (typeof message.tracingSessionId === "number")
                        object.tracingSessionId = options.longs === String ? String(message.tracingSessionId) : message.tracingSessionId;
                    else
                        object.tracingSessionId = options.longs === String ? $util.Long.prototype.toString.call(message.tracingSessionId) : options.longs === Number ? new $util.LongBits(message.tracingSessionId.low >>> 0, message.tracingSessionId.high >>> 0).toNumber(true) : message.tracingSessionId;
                if (message.enableExtraGuardrails != null && message.hasOwnProperty("enableExtraGuardrails"))
                    object.enableExtraGuardrails = message.enableExtraGuardrails;
                if (message.stopTimeoutMs != null && message.hasOwnProperty("stopTimeoutMs"))
                    object.stopTimeoutMs = message.stopTimeoutMs;
                if (message.sessionInitiator != null && message.hasOwnProperty("sessionInitiator"))
                    object.sessionInitiator = options.enums === String ? $root.perfetto.protos.DataSourceConfig.SessionInitiator[message.sessionInitiator] : message.sessionInitiator;
                if (message.ftraceConfig != null && message.hasOwnProperty("ftraceConfig"))
                    object.ftraceConfig = $root.perfetto.protos.FtraceConfig.toObject(message.ftraceConfig, options);
                if (message.chromeConfig != null && message.hasOwnProperty("chromeConfig"))
                    object.chromeConfig = $root.perfetto.protos.ChromeConfig.toObject(message.chromeConfig, options);
                if (message.inodeFileConfig != null && message.hasOwnProperty("inodeFileConfig"))
                    object.inodeFileConfig = $root.perfetto.protos.InodeFileConfig.toObject(message.inodeFileConfig, options);
                if (message.processStatsConfig != null && message.hasOwnProperty("processStatsConfig"))
                    object.processStatsConfig = $root.perfetto.protos.ProcessStatsConfig.toObject(message.processStatsConfig, options);
                if (message.sysStatsConfig != null && message.hasOwnProperty("sysStatsConfig"))
                    object.sysStatsConfig = $root.perfetto.protos.SysStatsConfig.toObject(message.sysStatsConfig, options);
                if (message.heapprofdConfig != null && message.hasOwnProperty("heapprofdConfig"))
                    object.heapprofdConfig = $root.perfetto.protos.HeapprofdConfig.toObject(message.heapprofdConfig, options);
                if (message.androidPowerConfig != null && message.hasOwnProperty("androidPowerConfig"))
                    object.androidPowerConfig = $root.perfetto.protos.AndroidPowerConfig.toObject(message.androidPowerConfig, options);
                if (message.androidLogConfig != null && message.hasOwnProperty("androidLogConfig"))
                    object.androidLogConfig = $root.perfetto.protos.AndroidLogConfig.toObject(message.androidLogConfig, options);
                if (message.gpuCounterConfig != null && message.hasOwnProperty("gpuCounterConfig"))
                    object.gpuCounterConfig = $root.perfetto.protos.GpuCounterConfig.toObject(message.gpuCounterConfig, options);
                if (message.packagesListConfig != null && message.hasOwnProperty("packagesListConfig"))
                    object.packagesListConfig = $root.perfetto.protos.PackagesListConfig.toObject(message.packagesListConfig, options);
                if (message.javaHprofConfig != null && message.hasOwnProperty("javaHprofConfig"))
                    object.javaHprofConfig = $root.perfetto.protos.JavaHprofConfig.toObject(message.javaHprofConfig, options);
                if (message.perfEventConfig != null && message.hasOwnProperty("perfEventConfig"))
                    object.perfEventConfig = $root.perfetto.protos.PerfEventConfig.toObject(message.perfEventConfig, options);
                if (message.vulkanMemoryConfig != null && message.hasOwnProperty("vulkanMemoryConfig"))
                    object.vulkanMemoryConfig = $root.perfetto.protos.VulkanMemoryConfig.toObject(message.vulkanMemoryConfig, options);
                if (message.trackEventConfig != null && message.hasOwnProperty("trackEventConfig"))
                    object.trackEventConfig = $root.perfetto.protos.TrackEventConfig.toObject(message.trackEventConfig, options);
                if (message.androidPolledStateConfig != null && message.hasOwnProperty("androidPolledStateConfig"))
                    object.androidPolledStateConfig = $root.perfetto.protos.AndroidPolledStateConfig.toObject(message.androidPolledStateConfig, options);
                if (message.interceptorConfig != null && message.hasOwnProperty("interceptorConfig"))
                    object.interceptorConfig = $root.perfetto.protos.InterceptorConfig.toObject(message.interceptorConfig, options);
                if (message.legacyConfig != null && message.hasOwnProperty("legacyConfig"))
                    object.legacyConfig = message.legacyConfig;
                if (message.forTesting != null && message.hasOwnProperty("forTesting"))
                    object.forTesting = $root.perfetto.protos.TestConfig.toObject(message.forTesting, options);
                return object;
            };

            /**
             * Converts this DataSourceConfig to JSON.
             * @function toJSON
             * @memberof perfetto.protos.DataSourceConfig
             * @instance
             * @returns {Object.<string,*>} JSON object
             */
            DataSourceConfig.prototype.toJSON = function toJSON() {
                return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
            };

            /**
             * SessionInitiator enum.
             * @name perfetto.protos.DataSourceConfig.SessionInitiator
             * @enum {number}
             * @property {number} SESSION_INITIATOR_UNSPECIFIED=0 SESSION_INITIATOR_UNSPECIFIED value
             * @property {number} SESSION_INITIATOR_TRUSTED_SYSTEM=1 SESSION_INITIATOR_TRUSTED_SYSTEM value
             */
            DataSourceConfig.SessionInitiator = (function() {
                var valuesById = {}, values = Object.create(valuesById);
                values[valuesById[0] = "SESSION_INITIATOR_UNSPECIFIED"] = 0;
                values[valuesById[1] = "SESSION_INITIATOR_TRUSTED_SYSTEM"] = 1;
                return values;
            })();

            return DataSourceConfig;
        })();

        protos.TraceConfig = (function() {

            /**
             * Properties of a TraceConfig.
             * @memberof perfetto.protos
             * @interface ITraceConfig
             * @property {Array.<perfetto.protos.TraceConfig.IBufferConfig>|null} [buffers] TraceConfig buffers
             * @property {Array.<perfetto.protos.TraceConfig.IDataSource>|null} [dataSources] TraceConfig dataSources
             * @property {perfetto.protos.TraceConfig.IBuiltinDataSource|null} [builtinDataSources] TraceConfig builtinDataSources
             * @property {number|null} [durationMs] TraceConfig durationMs
             * @property {boolean|null} [enableExtraGuardrails] TraceConfig enableExtraGuardrails
             * @property {perfetto.protos.TraceConfig.LockdownModeOperation|null} [lockdownMode] TraceConfig lockdownMode
             * @property {Array.<perfetto.protos.TraceConfig.IProducerConfig>|null} [producers] TraceConfig producers
             * @property {perfetto.protos.TraceConfig.IStatsdMetadata|null} [statsdMetadata] TraceConfig statsdMetadata
             * @property {boolean|null} [writeIntoFile] TraceConfig writeIntoFile
             * @property {string|null} [outputPath] TraceConfig outputPath
             * @property {number|null} [fileWritePeriodMs] TraceConfig fileWritePeriodMs
             * @property {number|null} [maxFileSizeBytes] TraceConfig maxFileSizeBytes
             * @property {perfetto.protos.TraceConfig.IGuardrailOverrides|null} [guardrailOverrides] TraceConfig guardrailOverrides
             * @property {boolean|null} [deferredStart] TraceConfig deferredStart
             * @property {number|null} [flushPeriodMs] TraceConfig flushPeriodMs
             * @property {number|null} [flushTimeoutMs] TraceConfig flushTimeoutMs
             * @property {number|null} [dataSourceStopTimeoutMs] TraceConfig dataSourceStopTimeoutMs
             * @property {boolean|null} [notifyTraceur] TraceConfig notifyTraceur
             * @property {number|null} [bugreportScore] TraceConfig bugreportScore
             * @property {perfetto.protos.TraceConfig.ITriggerConfig|null} [triggerConfig] TraceConfig triggerConfig
             * @property {Array.<string>|null} [activateTriggers] TraceConfig activateTriggers
             * @property {perfetto.protos.TraceConfig.IIncrementalStateConfig|null} [incrementalStateConfig] TraceConfig incrementalStateConfig
             * @property {boolean|null} [allowUserBuildTracing] TraceConfig allowUserBuildTracing
             * @property {string|null} [uniqueSessionName] TraceConfig uniqueSessionName
             * @property {perfetto.protos.TraceConfig.CompressionType|null} [compressionType] TraceConfig compressionType
             * @property {perfetto.protos.TraceConfig.IIncidentReportConfig|null} [incidentReportConfig] TraceConfig incidentReportConfig
             * @property {perfetto.protos.TraceConfig.StatsdLogging|null} [statsdLogging] TraceConfig statsdLogging
             * @property {number|null} [traceUuidMsb] TraceConfig traceUuidMsb
             * @property {number|null} [traceUuidLsb] TraceConfig traceUuidLsb
             * @property {perfetto.protos.TraceConfig.ITraceFilter|null} [traceFilter] TraceConfig traceFilter
             */

            /**
             * Constructs a new TraceConfig.
             * @memberof perfetto.protos
             * @classdesc Represents a TraceConfig.
             * @implements ITraceConfig
             * @constructor
             * @param {perfetto.protos.ITraceConfig=} [properties] Properties to set
             */
            function TraceConfig(properties) {
                this.buffers = [];
                this.dataSources = [];
                this.producers = [];
                this.activateTriggers = [];
                if (properties)
                    for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                        if (properties[keys[i]] != null)
                            this[keys[i]] = properties[keys[i]];
            }

            /**
             * TraceConfig buffers.
             * @member {Array.<perfetto.protos.TraceConfig.IBufferConfig>} buffers
             * @memberof perfetto.protos.TraceConfig
             * @instance
             */
            TraceConfig.prototype.buffers = $util.emptyArray;

            /**
             * TraceConfig dataSources.
             * @member {Array.<perfetto.protos.TraceConfig.IDataSource>} dataSources
             * @memberof perfetto.protos.TraceConfig
             * @instance
             */
            TraceConfig.prototype.dataSources = $util.emptyArray;

            /**
             * TraceConfig builtinDataSources.
             * @member {perfetto.protos.TraceConfig.IBuiltinDataSource|null|undefined} builtinDataSources
             * @memberof perfetto.protos.TraceConfig
             * @instance
             */
            TraceConfig.prototype.builtinDataSources = null;

            /**
             * TraceConfig durationMs.
             * @member {number} durationMs
             * @memberof perfetto.protos.TraceConfig
             * @instance
             */
            TraceConfig.prototype.durationMs = 0;

            /**
             * TraceConfig enableExtraGuardrails.
             * @member {boolean} enableExtraGuardrails
             * @memberof perfetto.protos.TraceConfig
             * @instance
             */
            TraceConfig.prototype.enableExtraGuardrails = false;

            /**
             * TraceConfig lockdownMode.
             * @member {perfetto.protos.TraceConfig.LockdownModeOperation} lockdownMode
             * @memberof perfetto.protos.TraceConfig
             * @instance
             */
            TraceConfig.prototype.lockdownMode = 0;

            /**
             * TraceConfig producers.
             * @member {Array.<perfetto.protos.TraceConfig.IProducerConfig>} producers
             * @memberof perfetto.protos.TraceConfig
             * @instance
             */
            TraceConfig.prototype.producers = $util.emptyArray;

            /**
             * TraceConfig statsdMetadata.
             * @member {perfetto.protos.TraceConfig.IStatsdMetadata|null|undefined} statsdMetadata
             * @memberof perfetto.protos.TraceConfig
             * @instance
             */
            TraceConfig.prototype.statsdMetadata = null;

            /**
             * TraceConfig writeIntoFile.
             * @member {boolean} writeIntoFile
             * @memberof perfetto.protos.TraceConfig
             * @instance
             */
            TraceConfig.prototype.writeIntoFile = false;

            /**
             * TraceConfig outputPath.
             * @member {string} outputPath
             * @memberof perfetto.protos.TraceConfig
             * @instance
             */
            TraceConfig.prototype.outputPath = "";

            /**
             * TraceConfig fileWritePeriodMs.
             * @member {number} fileWritePeriodMs
             * @memberof perfetto.protos.TraceConfig
             * @instance
             */
            TraceConfig.prototype.fileWritePeriodMs = 0;

            /**
             * TraceConfig maxFileSizeBytes.
             * @member {number} maxFileSizeBytes
             * @memberof perfetto.protos.TraceConfig
             * @instance
             */
            TraceConfig.prototype.maxFileSizeBytes = $util.Long ? $util.Long.fromBits(0,0,true) : 0;

            /**
             * TraceConfig guardrailOverrides.
             * @member {perfetto.protos.TraceConfig.IGuardrailOverrides|null|undefined} guardrailOverrides
             * @memberof perfetto.protos.TraceConfig
             * @instance
             */
            TraceConfig.prototype.guardrailOverrides = null;

            /**
             * TraceConfig deferredStart.
             * @member {boolean} deferredStart
             * @memberof perfetto.protos.TraceConfig
             * @instance
             */
            TraceConfig.prototype.deferredStart = false;

            /**
             * TraceConfig flushPeriodMs.
             * @member {number} flushPeriodMs
             * @memberof perfetto.protos.TraceConfig
             * @instance
             */
            TraceConfig.prototype.flushPeriodMs = 0;

            /**
             * TraceConfig flushTimeoutMs.
             * @member {number} flushTimeoutMs
             * @memberof perfetto.protos.TraceConfig
             * @instance
             */
            TraceConfig.prototype.flushTimeoutMs = 0;

            /**
             * TraceConfig dataSourceStopTimeoutMs.
             * @member {number} dataSourceStopTimeoutMs
             * @memberof perfetto.protos.TraceConfig
             * @instance
             */
            TraceConfig.prototype.dataSourceStopTimeoutMs = 0;

            /**
             * TraceConfig notifyTraceur.
             * @member {boolean} notifyTraceur
             * @memberof perfetto.protos.TraceConfig
             * @instance
             */
            TraceConfig.prototype.notifyTraceur = false;

            /**
             * TraceConfig bugreportScore.
             * @member {number} bugreportScore
             * @memberof perfetto.protos.TraceConfig
             * @instance
             */
            TraceConfig.prototype.bugreportScore = 0;

            /**
             * TraceConfig triggerConfig.
             * @member {perfetto.protos.TraceConfig.ITriggerConfig|null|undefined} triggerConfig
             * @memberof perfetto.protos.TraceConfig
             * @instance
             */
            TraceConfig.prototype.triggerConfig = null;

            /**
             * TraceConfig activateTriggers.
             * @member {Array.<string>} activateTriggers
             * @memberof perfetto.protos.TraceConfig
             * @instance
             */
            TraceConfig.prototype.activateTriggers = $util.emptyArray;

            /**
             * TraceConfig incrementalStateConfig.
             * @member {perfetto.protos.TraceConfig.IIncrementalStateConfig|null|undefined} incrementalStateConfig
             * @memberof perfetto.protos.TraceConfig
             * @instance
             */
            TraceConfig.prototype.incrementalStateConfig = null;

            /**
             * TraceConfig allowUserBuildTracing.
             * @member {boolean} allowUserBuildTracing
             * @memberof perfetto.protos.TraceConfig
             * @instance
             */
            TraceConfig.prototype.allowUserBuildTracing = false;

            /**
             * TraceConfig uniqueSessionName.
             * @member {string} uniqueSessionName
             * @memberof perfetto.protos.TraceConfig
             * @instance
             */
            TraceConfig.prototype.uniqueSessionName = "";

            /**
             * TraceConfig compressionType.
             * @member {perfetto.protos.TraceConfig.CompressionType} compressionType
             * @memberof perfetto.protos.TraceConfig
             * @instance
             */
            TraceConfig.prototype.compressionType = 0;

            /**
             * TraceConfig incidentReportConfig.
             * @member {perfetto.protos.TraceConfig.IIncidentReportConfig|null|undefined} incidentReportConfig
             * @memberof perfetto.protos.TraceConfig
             * @instance
             */
            TraceConfig.prototype.incidentReportConfig = null;

            /**
             * TraceConfig statsdLogging.
             * @member {perfetto.protos.TraceConfig.StatsdLogging} statsdLogging
             * @memberof perfetto.protos.TraceConfig
             * @instance
             */
            TraceConfig.prototype.statsdLogging = 0;

            /**
             * TraceConfig traceUuidMsb.
             * @member {number} traceUuidMsb
             * @memberof perfetto.protos.TraceConfig
             * @instance
             */
            TraceConfig.prototype.traceUuidMsb = $util.Long ? $util.Long.fromBits(0,0,false) : 0;

            /**
             * TraceConfig traceUuidLsb.
             * @member {number} traceUuidLsb
             * @memberof perfetto.protos.TraceConfig
             * @instance
             */
            TraceConfig.prototype.traceUuidLsb = $util.Long ? $util.Long.fromBits(0,0,false) : 0;

            /**
             * TraceConfig traceFilter.
             * @member {perfetto.protos.TraceConfig.ITraceFilter|null|undefined} traceFilter
             * @memberof perfetto.protos.TraceConfig
             * @instance
             */
            TraceConfig.prototype.traceFilter = null;

            /**
             * Creates a new TraceConfig instance using the specified properties.
             * @function create
             * @memberof perfetto.protos.TraceConfig
             * @static
             * @param {perfetto.protos.ITraceConfig=} [properties] Properties to set
             * @returns {perfetto.protos.TraceConfig} TraceConfig instance
             */
            TraceConfig.create = function create(properties) {
                return new TraceConfig(properties);
            };

            /**
             * Encodes the specified TraceConfig message. Does not implicitly {@link perfetto.protos.TraceConfig.verify|verify} messages.
             * @function encode
             * @memberof perfetto.protos.TraceConfig
             * @static
             * @param {perfetto.protos.ITraceConfig} message TraceConfig message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            TraceConfig.encode = function encode(message, writer) {
                if (!writer)
                    writer = $Writer.create();
                if (message.buffers != null && message.buffers.length)
                    for (var i = 0; i < message.buffers.length; ++i)
                        $root.perfetto.protos.TraceConfig.BufferConfig.encode(message.buffers[i], writer.uint32(/* id 1, wireType 2 =*/10).fork()).ldelim();
                if (message.dataSources != null && message.dataSources.length)
                    for (var i = 0; i < message.dataSources.length; ++i)
                        $root.perfetto.protos.TraceConfig.DataSource.encode(message.dataSources[i], writer.uint32(/* id 2, wireType 2 =*/18).fork()).ldelim();
                if (message.durationMs != null && Object.hasOwnProperty.call(message, "durationMs"))
                    writer.uint32(/* id 3, wireType 0 =*/24).uint32(message.durationMs);
                if (message.enableExtraGuardrails != null && Object.hasOwnProperty.call(message, "enableExtraGuardrails"))
                    writer.uint32(/* id 4, wireType 0 =*/32).bool(message.enableExtraGuardrails);
                if (message.lockdownMode != null && Object.hasOwnProperty.call(message, "lockdownMode"))
                    writer.uint32(/* id 5, wireType 0 =*/40).int32(message.lockdownMode);
                if (message.producers != null && message.producers.length)
                    for (var i = 0; i < message.producers.length; ++i)
                        $root.perfetto.protos.TraceConfig.ProducerConfig.encode(message.producers[i], writer.uint32(/* id 6, wireType 2 =*/50).fork()).ldelim();
                if (message.statsdMetadata != null && Object.hasOwnProperty.call(message, "statsdMetadata"))
                    $root.perfetto.protos.TraceConfig.StatsdMetadata.encode(message.statsdMetadata, writer.uint32(/* id 7, wireType 2 =*/58).fork()).ldelim();
                if (message.writeIntoFile != null && Object.hasOwnProperty.call(message, "writeIntoFile"))
                    writer.uint32(/* id 8, wireType 0 =*/64).bool(message.writeIntoFile);
                if (message.fileWritePeriodMs != null && Object.hasOwnProperty.call(message, "fileWritePeriodMs"))
                    writer.uint32(/* id 9, wireType 0 =*/72).uint32(message.fileWritePeriodMs);
                if (message.maxFileSizeBytes != null && Object.hasOwnProperty.call(message, "maxFileSizeBytes"))
                    writer.uint32(/* id 10, wireType 0 =*/80).uint64(message.maxFileSizeBytes);
                if (message.guardrailOverrides != null && Object.hasOwnProperty.call(message, "guardrailOverrides"))
                    $root.perfetto.protos.TraceConfig.GuardrailOverrides.encode(message.guardrailOverrides, writer.uint32(/* id 11, wireType 2 =*/90).fork()).ldelim();
                if (message.deferredStart != null && Object.hasOwnProperty.call(message, "deferredStart"))
                    writer.uint32(/* id 12, wireType 0 =*/96).bool(message.deferredStart);
                if (message.flushPeriodMs != null && Object.hasOwnProperty.call(message, "flushPeriodMs"))
                    writer.uint32(/* id 13, wireType 0 =*/104).uint32(message.flushPeriodMs);
                if (message.flushTimeoutMs != null && Object.hasOwnProperty.call(message, "flushTimeoutMs"))
                    writer.uint32(/* id 14, wireType 0 =*/112).uint32(message.flushTimeoutMs);
                if (message.notifyTraceur != null && Object.hasOwnProperty.call(message, "notifyTraceur"))
                    writer.uint32(/* id 16, wireType 0 =*/128).bool(message.notifyTraceur);
                if (message.triggerConfig != null && Object.hasOwnProperty.call(message, "triggerConfig"))
                    $root.perfetto.protos.TraceConfig.TriggerConfig.encode(message.triggerConfig, writer.uint32(/* id 17, wireType 2 =*/138).fork()).ldelim();
                if (message.activateTriggers != null && message.activateTriggers.length)
                    for (var i = 0; i < message.activateTriggers.length; ++i)
                        writer.uint32(/* id 18, wireType 2 =*/146).string(message.activateTriggers[i]);
                if (message.allowUserBuildTracing != null && Object.hasOwnProperty.call(message, "allowUserBuildTracing"))
                    writer.uint32(/* id 19, wireType 0 =*/152).bool(message.allowUserBuildTracing);
                if (message.builtinDataSources != null && Object.hasOwnProperty.call(message, "builtinDataSources"))
                    $root.perfetto.protos.TraceConfig.BuiltinDataSource.encode(message.builtinDataSources, writer.uint32(/* id 20, wireType 2 =*/162).fork()).ldelim();
                if (message.incrementalStateConfig != null && Object.hasOwnProperty.call(message, "incrementalStateConfig"))
                    $root.perfetto.protos.TraceConfig.IncrementalStateConfig.encode(message.incrementalStateConfig, writer.uint32(/* id 21, wireType 2 =*/170).fork()).ldelim();
                if (message.uniqueSessionName != null && Object.hasOwnProperty.call(message, "uniqueSessionName"))
                    writer.uint32(/* id 22, wireType 2 =*/178).string(message.uniqueSessionName);
                if (message.dataSourceStopTimeoutMs != null && Object.hasOwnProperty.call(message, "dataSourceStopTimeoutMs"))
                    writer.uint32(/* id 23, wireType 0 =*/184).uint32(message.dataSourceStopTimeoutMs);
                if (message.compressionType != null && Object.hasOwnProperty.call(message, "compressionType"))
                    writer.uint32(/* id 24, wireType 0 =*/192).int32(message.compressionType);
                if (message.incidentReportConfig != null && Object.hasOwnProperty.call(message, "incidentReportConfig"))
                    $root.perfetto.protos.TraceConfig.IncidentReportConfig.encode(message.incidentReportConfig, writer.uint32(/* id 25, wireType 2 =*/202).fork()).ldelim();
                if (message.traceUuidMsb != null && Object.hasOwnProperty.call(message, "traceUuidMsb"))
                    writer.uint32(/* id 27, wireType 0 =*/216).int64(message.traceUuidMsb);
                if (message.traceUuidLsb != null && Object.hasOwnProperty.call(message, "traceUuidLsb"))
                    writer.uint32(/* id 28, wireType 0 =*/224).int64(message.traceUuidLsb);
                if (message.outputPath != null && Object.hasOwnProperty.call(message, "outputPath"))
                    writer.uint32(/* id 29, wireType 2 =*/234).string(message.outputPath);
                if (message.bugreportScore != null && Object.hasOwnProperty.call(message, "bugreportScore"))
                    writer.uint32(/* id 30, wireType 0 =*/240).int32(message.bugreportScore);
                if (message.statsdLogging != null && Object.hasOwnProperty.call(message, "statsdLogging"))
                    writer.uint32(/* id 31, wireType 0 =*/248).int32(message.statsdLogging);
                if (message.traceFilter != null && Object.hasOwnProperty.call(message, "traceFilter"))
                    $root.perfetto.protos.TraceConfig.TraceFilter.encode(message.traceFilter, writer.uint32(/* id 32, wireType 2 =*/258).fork()).ldelim();
                return writer;
            };

            /**
             * Encodes the specified TraceConfig message, length delimited. Does not implicitly {@link perfetto.protos.TraceConfig.verify|verify} messages.
             * @function encodeDelimited
             * @memberof perfetto.protos.TraceConfig
             * @static
             * @param {perfetto.protos.ITraceConfig} message TraceConfig message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            TraceConfig.encodeDelimited = function encodeDelimited(message, writer) {
                return this.encode(message, writer).ldelim();
            };

            /**
             * Decodes a TraceConfig message from the specified reader or buffer.
             * @function decode
             * @memberof perfetto.protos.TraceConfig
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @param {number} [length] Message length if known beforehand
             * @returns {perfetto.protos.TraceConfig} TraceConfig
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            TraceConfig.decode = function decode(reader, length) {
                if (!(reader instanceof $Reader))
                    reader = $Reader.create(reader);
                var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.TraceConfig();
                while (reader.pos < end) {
                    var tag = reader.uint32();
                    switch (tag >>> 3) {
                    case 1:
                        if (!(message.buffers && message.buffers.length))
                            message.buffers = [];
                        message.buffers.push($root.perfetto.protos.TraceConfig.BufferConfig.decode(reader, reader.uint32()));
                        break;
                    case 2:
                        if (!(message.dataSources && message.dataSources.length))
                            message.dataSources = [];
                        message.dataSources.push($root.perfetto.protos.TraceConfig.DataSource.decode(reader, reader.uint32()));
                        break;
                    case 20:
                        message.builtinDataSources = $root.perfetto.protos.TraceConfig.BuiltinDataSource.decode(reader, reader.uint32());
                        break;
                    case 3:
                        message.durationMs = reader.uint32();
                        break;
                    case 4:
                        message.enableExtraGuardrails = reader.bool();
                        break;
                    case 5:
                        message.lockdownMode = reader.int32();
                        break;
                    case 6:
                        if (!(message.producers && message.producers.length))
                            message.producers = [];
                        message.producers.push($root.perfetto.protos.TraceConfig.ProducerConfig.decode(reader, reader.uint32()));
                        break;
                    case 7:
                        message.statsdMetadata = $root.perfetto.protos.TraceConfig.StatsdMetadata.decode(reader, reader.uint32());
                        break;
                    case 8:
                        message.writeIntoFile = reader.bool();
                        break;
                    case 29:
                        message.outputPath = reader.string();
                        break;
                    case 9:
                        message.fileWritePeriodMs = reader.uint32();
                        break;
                    case 10:
                        message.maxFileSizeBytes = reader.uint64();
                        break;
                    case 11:
                        message.guardrailOverrides = $root.perfetto.protos.TraceConfig.GuardrailOverrides.decode(reader, reader.uint32());
                        break;
                    case 12:
                        message.deferredStart = reader.bool();
                        break;
                    case 13:
                        message.flushPeriodMs = reader.uint32();
                        break;
                    case 14:
                        message.flushTimeoutMs = reader.uint32();
                        break;
                    case 23:
                        message.dataSourceStopTimeoutMs = reader.uint32();
                        break;
                    case 16:
                        message.notifyTraceur = reader.bool();
                        break;
                    case 30:
                        message.bugreportScore = reader.int32();
                        break;
                    case 17:
                        message.triggerConfig = $root.perfetto.protos.TraceConfig.TriggerConfig.decode(reader, reader.uint32());
                        break;
                    case 18:
                        if (!(message.activateTriggers && message.activateTriggers.length))
                            message.activateTriggers = [];
                        message.activateTriggers.push(reader.string());
                        break;
                    case 21:
                        message.incrementalStateConfig = $root.perfetto.protos.TraceConfig.IncrementalStateConfig.decode(reader, reader.uint32());
                        break;
                    case 19:
                        message.allowUserBuildTracing = reader.bool();
                        break;
                    case 22:
                        message.uniqueSessionName = reader.string();
                        break;
                    case 24:
                        message.compressionType = reader.int32();
                        break;
                    case 25:
                        message.incidentReportConfig = $root.perfetto.protos.TraceConfig.IncidentReportConfig.decode(reader, reader.uint32());
                        break;
                    case 31:
                        message.statsdLogging = reader.int32();
                        break;
                    case 27:
                        message.traceUuidMsb = reader.int64();
                        break;
                    case 28:
                        message.traceUuidLsb = reader.int64();
                        break;
                    case 32:
                        message.traceFilter = $root.perfetto.protos.TraceConfig.TraceFilter.decode(reader, reader.uint32());
                        break;
                    default:
                        reader.skipType(tag & 7);
                        break;
                    }
                }
                return message;
            };

            /**
             * Decodes a TraceConfig message from the specified reader or buffer, length delimited.
             * @function decodeDelimited
             * @memberof perfetto.protos.TraceConfig
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @returns {perfetto.protos.TraceConfig} TraceConfig
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            TraceConfig.decodeDelimited = function decodeDelimited(reader) {
                if (!(reader instanceof $Reader))
                    reader = new $Reader(reader);
                return this.decode(reader, reader.uint32());
            };

            /**
             * Verifies a TraceConfig message.
             * @function verify
             * @memberof perfetto.protos.TraceConfig
             * @static
             * @param {Object.<string,*>} message Plain object to verify
             * @returns {string|null} `null` if valid, otherwise the reason why it is not
             */
            TraceConfig.verify = function verify(message) {
                if (typeof message !== "object" || message === null)
                    return "object expected";
                if (message.buffers != null && message.hasOwnProperty("buffers")) {
                    if (!Array.isArray(message.buffers))
                        return "buffers: array expected";
                    for (var i = 0; i < message.buffers.length; ++i) {
                        var error = $root.perfetto.protos.TraceConfig.BufferConfig.verify(message.buffers[i]);
                        if (error)
                            return "buffers." + error;
                    }
                }
                if (message.dataSources != null && message.hasOwnProperty("dataSources")) {
                    if (!Array.isArray(message.dataSources))
                        return "dataSources: array expected";
                    for (var i = 0; i < message.dataSources.length; ++i) {
                        var error = $root.perfetto.protos.TraceConfig.DataSource.verify(message.dataSources[i]);
                        if (error)
                            return "dataSources." + error;
                    }
                }
                if (message.builtinDataSources != null && message.hasOwnProperty("builtinDataSources")) {
                    var error = $root.perfetto.protos.TraceConfig.BuiltinDataSource.verify(message.builtinDataSources);
                    if (error)
                        return "builtinDataSources." + error;
                }
                if (message.durationMs != null && message.hasOwnProperty("durationMs"))
                    if (!$util.isInteger(message.durationMs))
                        return "durationMs: integer expected";
                if (message.enableExtraGuardrails != null && message.hasOwnProperty("enableExtraGuardrails"))
                    if (typeof message.enableExtraGuardrails !== "boolean")
                        return "enableExtraGuardrails: boolean expected";
                if (message.lockdownMode != null && message.hasOwnProperty("lockdownMode"))
                    switch (message.lockdownMode) {
                    default:
                        return "lockdownMode: enum value expected";
                    case 0:
                    case 1:
                    case 2:
                        break;
                    }
                if (message.producers != null && message.hasOwnProperty("producers")) {
                    if (!Array.isArray(message.producers))
                        return "producers: array expected";
                    for (var i = 0; i < message.producers.length; ++i) {
                        var error = $root.perfetto.protos.TraceConfig.ProducerConfig.verify(message.producers[i]);
                        if (error)
                            return "producers." + error;
                    }
                }
                if (message.statsdMetadata != null && message.hasOwnProperty("statsdMetadata")) {
                    var error = $root.perfetto.protos.TraceConfig.StatsdMetadata.verify(message.statsdMetadata);
                    if (error)
                        return "statsdMetadata." + error;
                }
                if (message.writeIntoFile != null && message.hasOwnProperty("writeIntoFile"))
                    if (typeof message.writeIntoFile !== "boolean")
                        return "writeIntoFile: boolean expected";
                if (message.outputPath != null && message.hasOwnProperty("outputPath"))
                    if (!$util.isString(message.outputPath))
                        return "outputPath: string expected";
                if (message.fileWritePeriodMs != null && message.hasOwnProperty("fileWritePeriodMs"))
                    if (!$util.isInteger(message.fileWritePeriodMs))
                        return "fileWritePeriodMs: integer expected";
                if (message.maxFileSizeBytes != null && message.hasOwnProperty("maxFileSizeBytes"))
                    if (!$util.isInteger(message.maxFileSizeBytes) && !(message.maxFileSizeBytes && $util.isInteger(message.maxFileSizeBytes.low) && $util.isInteger(message.maxFileSizeBytes.high)))
                        return "maxFileSizeBytes: integer|Long expected";
                if (message.guardrailOverrides != null && message.hasOwnProperty("guardrailOverrides")) {
                    var error = $root.perfetto.protos.TraceConfig.GuardrailOverrides.verify(message.guardrailOverrides);
                    if (error)
                        return "guardrailOverrides." + error;
                }
                if (message.deferredStart != null && message.hasOwnProperty("deferredStart"))
                    if (typeof message.deferredStart !== "boolean")
                        return "deferredStart: boolean expected";
                if (message.flushPeriodMs != null && message.hasOwnProperty("flushPeriodMs"))
                    if (!$util.isInteger(message.flushPeriodMs))
                        return "flushPeriodMs: integer expected";
                if (message.flushTimeoutMs != null && message.hasOwnProperty("flushTimeoutMs"))
                    if (!$util.isInteger(message.flushTimeoutMs))
                        return "flushTimeoutMs: integer expected";
                if (message.dataSourceStopTimeoutMs != null && message.hasOwnProperty("dataSourceStopTimeoutMs"))
                    if (!$util.isInteger(message.dataSourceStopTimeoutMs))
                        return "dataSourceStopTimeoutMs: integer expected";
                if (message.notifyTraceur != null && message.hasOwnProperty("notifyTraceur"))
                    if (typeof message.notifyTraceur !== "boolean")
                        return "notifyTraceur: boolean expected";
                if (message.bugreportScore != null && message.hasOwnProperty("bugreportScore"))
                    if (!$util.isInteger(message.bugreportScore))
                        return "bugreportScore: integer expected";
                if (message.triggerConfig != null && message.hasOwnProperty("triggerConfig")) {
                    var error = $root.perfetto.protos.TraceConfig.TriggerConfig.verify(message.triggerConfig);
                    if (error)
                        return "triggerConfig." + error;
                }
                if (message.activateTriggers != null && message.hasOwnProperty("activateTriggers")) {
                    if (!Array.isArray(message.activateTriggers))
                        return "activateTriggers: array expected";
                    for (var i = 0; i < message.activateTriggers.length; ++i)
                        if (!$util.isString(message.activateTriggers[i]))
                            return "activateTriggers: string[] expected";
                }
                if (message.incrementalStateConfig != null && message.hasOwnProperty("incrementalStateConfig")) {
                    var error = $root.perfetto.protos.TraceConfig.IncrementalStateConfig.verify(message.incrementalStateConfig);
                    if (error)
                        return "incrementalStateConfig." + error;
                }
                if (message.allowUserBuildTracing != null && message.hasOwnProperty("allowUserBuildTracing"))
                    if (typeof message.allowUserBuildTracing !== "boolean")
                        return "allowUserBuildTracing: boolean expected";
                if (message.uniqueSessionName != null && message.hasOwnProperty("uniqueSessionName"))
                    if (!$util.isString(message.uniqueSessionName))
                        return "uniqueSessionName: string expected";
                if (message.compressionType != null && message.hasOwnProperty("compressionType"))
                    switch (message.compressionType) {
                    default:
                        return "compressionType: enum value expected";
                    case 0:
                    case 1:
                        break;
                    }
                if (message.incidentReportConfig != null && message.hasOwnProperty("incidentReportConfig")) {
                    var error = $root.perfetto.protos.TraceConfig.IncidentReportConfig.verify(message.incidentReportConfig);
                    if (error)
                        return "incidentReportConfig." + error;
                }
                if (message.statsdLogging != null && message.hasOwnProperty("statsdLogging"))
                    switch (message.statsdLogging) {
                    default:
                        return "statsdLogging: enum value expected";
                    case 0:
                    case 1:
                    case 2:
                        break;
                    }
                if (message.traceUuidMsb != null && message.hasOwnProperty("traceUuidMsb"))
                    if (!$util.isInteger(message.traceUuidMsb) && !(message.traceUuidMsb && $util.isInteger(message.traceUuidMsb.low) && $util.isInteger(message.traceUuidMsb.high)))
                        return "traceUuidMsb: integer|Long expected";
                if (message.traceUuidLsb != null && message.hasOwnProperty("traceUuidLsb"))
                    if (!$util.isInteger(message.traceUuidLsb) && !(message.traceUuidLsb && $util.isInteger(message.traceUuidLsb.low) && $util.isInteger(message.traceUuidLsb.high)))
                        return "traceUuidLsb: integer|Long expected";
                if (message.traceFilter != null && message.hasOwnProperty("traceFilter")) {
                    var error = $root.perfetto.protos.TraceConfig.TraceFilter.verify(message.traceFilter);
                    if (error)
                        return "traceFilter." + error;
                }
                return null;
            };

            /**
             * Creates a TraceConfig message from a plain object. Also converts values to their respective internal types.
             * @function fromObject
             * @memberof perfetto.protos.TraceConfig
             * @static
             * @param {Object.<string,*>} object Plain object
             * @returns {perfetto.protos.TraceConfig} TraceConfig
             */
            TraceConfig.fromObject = function fromObject(object) {
                if (object instanceof $root.perfetto.protos.TraceConfig)
                    return object;
                var message = new $root.perfetto.protos.TraceConfig();
                if (object.buffers) {
                    if (!Array.isArray(object.buffers))
                        throw TypeError(".perfetto.protos.TraceConfig.buffers: array expected");
                    message.buffers = [];
                    for (var i = 0; i < object.buffers.length; ++i) {
                        if (typeof object.buffers[i] !== "object")
                            throw TypeError(".perfetto.protos.TraceConfig.buffers: object expected");
                        message.buffers[i] = $root.perfetto.protos.TraceConfig.BufferConfig.fromObject(object.buffers[i]);
                    }
                }
                if (object.dataSources) {
                    if (!Array.isArray(object.dataSources))
                        throw TypeError(".perfetto.protos.TraceConfig.dataSources: array expected");
                    message.dataSources = [];
                    for (var i = 0; i < object.dataSources.length; ++i) {
                        if (typeof object.dataSources[i] !== "object")
                            throw TypeError(".perfetto.protos.TraceConfig.dataSources: object expected");
                        message.dataSources[i] = $root.perfetto.protos.TraceConfig.DataSource.fromObject(object.dataSources[i]);
                    }
                }
                if (object.builtinDataSources != null) {
                    if (typeof object.builtinDataSources !== "object")
                        throw TypeError(".perfetto.protos.TraceConfig.builtinDataSources: object expected");
                    message.builtinDataSources = $root.perfetto.protos.TraceConfig.BuiltinDataSource.fromObject(object.builtinDataSources);
                }
                if (object.durationMs != null)
                    message.durationMs = object.durationMs >>> 0;
                if (object.enableExtraGuardrails != null)
                    message.enableExtraGuardrails = Boolean(object.enableExtraGuardrails);
                switch (object.lockdownMode) {
                case "LOCKDOWN_UNCHANGED":
                case 0:
                    message.lockdownMode = 0;
                    break;
                case "LOCKDOWN_CLEAR":
                case 1:
                    message.lockdownMode = 1;
                    break;
                case "LOCKDOWN_SET":
                case 2:
                    message.lockdownMode = 2;
                    break;
                }
                if (object.producers) {
                    if (!Array.isArray(object.producers))
                        throw TypeError(".perfetto.protos.TraceConfig.producers: array expected");
                    message.producers = [];
                    for (var i = 0; i < object.producers.length; ++i) {
                        if (typeof object.producers[i] !== "object")
                            throw TypeError(".perfetto.protos.TraceConfig.producers: object expected");
                        message.producers[i] = $root.perfetto.protos.TraceConfig.ProducerConfig.fromObject(object.producers[i]);
                    }
                }
                if (object.statsdMetadata != null) {
                    if (typeof object.statsdMetadata !== "object")
                        throw TypeError(".perfetto.protos.TraceConfig.statsdMetadata: object expected");
                    message.statsdMetadata = $root.perfetto.protos.TraceConfig.StatsdMetadata.fromObject(object.statsdMetadata);
                }
                if (object.writeIntoFile != null)
                    message.writeIntoFile = Boolean(object.writeIntoFile);
                if (object.outputPath != null)
                    message.outputPath = String(object.outputPath);
                if (object.fileWritePeriodMs != null)
                    message.fileWritePeriodMs = object.fileWritePeriodMs >>> 0;
                if (object.maxFileSizeBytes != null)
                    if ($util.Long)
                        (message.maxFileSizeBytes = $util.Long.fromValue(object.maxFileSizeBytes)).unsigned = true;
                    else if (typeof object.maxFileSizeBytes === "string")
                        message.maxFileSizeBytes = parseInt(object.maxFileSizeBytes, 10);
                    else if (typeof object.maxFileSizeBytes === "number")
                        message.maxFileSizeBytes = object.maxFileSizeBytes;
                    else if (typeof object.maxFileSizeBytes === "object")
                        message.maxFileSizeBytes = new $util.LongBits(object.maxFileSizeBytes.low >>> 0, object.maxFileSizeBytes.high >>> 0).toNumber(true);
                if (object.guardrailOverrides != null) {
                    if (typeof object.guardrailOverrides !== "object")
                        throw TypeError(".perfetto.protos.TraceConfig.guardrailOverrides: object expected");
                    message.guardrailOverrides = $root.perfetto.protos.TraceConfig.GuardrailOverrides.fromObject(object.guardrailOverrides);
                }
                if (object.deferredStart != null)
                    message.deferredStart = Boolean(object.deferredStart);
                if (object.flushPeriodMs != null)
                    message.flushPeriodMs = object.flushPeriodMs >>> 0;
                if (object.flushTimeoutMs != null)
                    message.flushTimeoutMs = object.flushTimeoutMs >>> 0;
                if (object.dataSourceStopTimeoutMs != null)
                    message.dataSourceStopTimeoutMs = object.dataSourceStopTimeoutMs >>> 0;
                if (object.notifyTraceur != null)
                    message.notifyTraceur = Boolean(object.notifyTraceur);
                if (object.bugreportScore != null)
                    message.bugreportScore = object.bugreportScore | 0;
                if (object.triggerConfig != null) {
                    if (typeof object.triggerConfig !== "object")
                        throw TypeError(".perfetto.protos.TraceConfig.triggerConfig: object expected");
                    message.triggerConfig = $root.perfetto.protos.TraceConfig.TriggerConfig.fromObject(object.triggerConfig);
                }
                if (object.activateTriggers) {
                    if (!Array.isArray(object.activateTriggers))
                        throw TypeError(".perfetto.protos.TraceConfig.activateTriggers: array expected");
                    message.activateTriggers = [];
                    for (var i = 0; i < object.activateTriggers.length; ++i)
                        message.activateTriggers[i] = String(object.activateTriggers[i]);
                }
                if (object.incrementalStateConfig != null) {
                    if (typeof object.incrementalStateConfig !== "object")
                        throw TypeError(".perfetto.protos.TraceConfig.incrementalStateConfig: object expected");
                    message.incrementalStateConfig = $root.perfetto.protos.TraceConfig.IncrementalStateConfig.fromObject(object.incrementalStateConfig);
                }
                if (object.allowUserBuildTracing != null)
                    message.allowUserBuildTracing = Boolean(object.allowUserBuildTracing);
                if (object.uniqueSessionName != null)
                    message.uniqueSessionName = String(object.uniqueSessionName);
                switch (object.compressionType) {
                case "COMPRESSION_TYPE_UNSPECIFIED":
                case 0:
                    message.compressionType = 0;
                    break;
                case "COMPRESSION_TYPE_DEFLATE":
                case 1:
                    message.compressionType = 1;
                    break;
                }
                if (object.incidentReportConfig != null) {
                    if (typeof object.incidentReportConfig !== "object")
                        throw TypeError(".perfetto.protos.TraceConfig.incidentReportConfig: object expected");
                    message.incidentReportConfig = $root.perfetto.protos.TraceConfig.IncidentReportConfig.fromObject(object.incidentReportConfig);
                }
                switch (object.statsdLogging) {
                case "STATSD_LOGGING_UNSPECIFIED":
                case 0:
                    message.statsdLogging = 0;
                    break;
                case "STATSD_LOGGING_ENABLED":
                case 1:
                    message.statsdLogging = 1;
                    break;
                case "STATSD_LOGGING_DISABLED":
                case 2:
                    message.statsdLogging = 2;
                    break;
                }
                if (object.traceUuidMsb != null)
                    if ($util.Long)
                        (message.traceUuidMsb = $util.Long.fromValue(object.traceUuidMsb)).unsigned = false;
                    else if (typeof object.traceUuidMsb === "string")
                        message.traceUuidMsb = parseInt(object.traceUuidMsb, 10);
                    else if (typeof object.traceUuidMsb === "number")
                        message.traceUuidMsb = object.traceUuidMsb;
                    else if (typeof object.traceUuidMsb === "object")
                        message.traceUuidMsb = new $util.LongBits(object.traceUuidMsb.low >>> 0, object.traceUuidMsb.high >>> 0).toNumber();
                if (object.traceUuidLsb != null)
                    if ($util.Long)
                        (message.traceUuidLsb = $util.Long.fromValue(object.traceUuidLsb)).unsigned = false;
                    else if (typeof object.traceUuidLsb === "string")
                        message.traceUuidLsb = parseInt(object.traceUuidLsb, 10);
                    else if (typeof object.traceUuidLsb === "number")
                        message.traceUuidLsb = object.traceUuidLsb;
                    else if (typeof object.traceUuidLsb === "object")
                        message.traceUuidLsb = new $util.LongBits(object.traceUuidLsb.low >>> 0, object.traceUuidLsb.high >>> 0).toNumber();
                if (object.traceFilter != null) {
                    if (typeof object.traceFilter !== "object")
                        throw TypeError(".perfetto.protos.TraceConfig.traceFilter: object expected");
                    message.traceFilter = $root.perfetto.protos.TraceConfig.TraceFilter.fromObject(object.traceFilter);
                }
                return message;
            };

            /**
             * Creates a plain object from a TraceConfig message. Also converts values to other types if specified.
             * @function toObject
             * @memberof perfetto.protos.TraceConfig
             * @static
             * @param {perfetto.protos.TraceConfig} message TraceConfig
             * @param {$protobuf.IConversionOptions} [options] Conversion options
             * @returns {Object.<string,*>} Plain object
             */
            TraceConfig.toObject = function toObject(message, options) {
                if (!options)
                    options = {};
                var object = {};
                if (options.arrays || options.defaults) {
                    object.buffers = [];
                    object.dataSources = [];
                    object.producers = [];
                    object.activateTriggers = [];
                }
                if (options.defaults) {
                    object.durationMs = 0;
                    object.enableExtraGuardrails = false;
                    object.lockdownMode = options.enums === String ? "LOCKDOWN_UNCHANGED" : 0;
                    object.statsdMetadata = null;
                    object.writeIntoFile = false;
                    object.fileWritePeriodMs = 0;
                    if ($util.Long) {
                        var long = new $util.Long(0, 0, true);
                        object.maxFileSizeBytes = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
                    } else
                        object.maxFileSizeBytes = options.longs === String ? "0" : 0;
                    object.guardrailOverrides = null;
                    object.deferredStart = false;
                    object.flushPeriodMs = 0;
                    object.flushTimeoutMs = 0;
                    object.notifyTraceur = false;
                    object.triggerConfig = null;
                    object.allowUserBuildTracing = false;
                    object.builtinDataSources = null;
                    object.incrementalStateConfig = null;
                    object.uniqueSessionName = "";
                    object.dataSourceStopTimeoutMs = 0;
                    object.compressionType = options.enums === String ? "COMPRESSION_TYPE_UNSPECIFIED" : 0;
                    object.incidentReportConfig = null;
                    if ($util.Long) {
                        var long = new $util.Long(0, 0, false);
                        object.traceUuidMsb = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
                    } else
                        object.traceUuidMsb = options.longs === String ? "0" : 0;
                    if ($util.Long) {
                        var long = new $util.Long(0, 0, false);
                        object.traceUuidLsb = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
                    } else
                        object.traceUuidLsb = options.longs === String ? "0" : 0;
                    object.outputPath = "";
                    object.bugreportScore = 0;
                    object.statsdLogging = options.enums === String ? "STATSD_LOGGING_UNSPECIFIED" : 0;
                    object.traceFilter = null;
                }
                if (message.buffers && message.buffers.length) {
                    object.buffers = [];
                    for (var j = 0; j < message.buffers.length; ++j)
                        object.buffers[j] = $root.perfetto.protos.TraceConfig.BufferConfig.toObject(message.buffers[j], options);
                }
                if (message.dataSources && message.dataSources.length) {
                    object.dataSources = [];
                    for (var j = 0; j < message.dataSources.length; ++j)
                        object.dataSources[j] = $root.perfetto.protos.TraceConfig.DataSource.toObject(message.dataSources[j], options);
                }
                if (message.durationMs != null && message.hasOwnProperty("durationMs"))
                    object.durationMs = message.durationMs;
                if (message.enableExtraGuardrails != null && message.hasOwnProperty("enableExtraGuardrails"))
                    object.enableExtraGuardrails = message.enableExtraGuardrails;
                if (message.lockdownMode != null && message.hasOwnProperty("lockdownMode"))
                    object.lockdownMode = options.enums === String ? $root.perfetto.protos.TraceConfig.LockdownModeOperation[message.lockdownMode] : message.lockdownMode;
                if (message.producers && message.producers.length) {
                    object.producers = [];
                    for (var j = 0; j < message.producers.length; ++j)
                        object.producers[j] = $root.perfetto.protos.TraceConfig.ProducerConfig.toObject(message.producers[j], options);
                }
                if (message.statsdMetadata != null && message.hasOwnProperty("statsdMetadata"))
                    object.statsdMetadata = $root.perfetto.protos.TraceConfig.StatsdMetadata.toObject(message.statsdMetadata, options);
                if (message.writeIntoFile != null && message.hasOwnProperty("writeIntoFile"))
                    object.writeIntoFile = message.writeIntoFile;
                if (message.fileWritePeriodMs != null && message.hasOwnProperty("fileWritePeriodMs"))
                    object.fileWritePeriodMs = message.fileWritePeriodMs;
                if (message.maxFileSizeBytes != null && message.hasOwnProperty("maxFileSizeBytes"))
                    if (typeof message.maxFileSizeBytes === "number")
                        object.maxFileSizeBytes = options.longs === String ? String(message.maxFileSizeBytes) : message.maxFileSizeBytes;
                    else
                        object.maxFileSizeBytes = options.longs === String ? $util.Long.prototype.toString.call(message.maxFileSizeBytes) : options.longs === Number ? new $util.LongBits(message.maxFileSizeBytes.low >>> 0, message.maxFileSizeBytes.high >>> 0).toNumber(true) : message.maxFileSizeBytes;
                if (message.guardrailOverrides != null && message.hasOwnProperty("guardrailOverrides"))
                    object.guardrailOverrides = $root.perfetto.protos.TraceConfig.GuardrailOverrides.toObject(message.guardrailOverrides, options);
                if (message.deferredStart != null && message.hasOwnProperty("deferredStart"))
                    object.deferredStart = message.deferredStart;
                if (message.flushPeriodMs != null && message.hasOwnProperty("flushPeriodMs"))
                    object.flushPeriodMs = message.flushPeriodMs;
                if (message.flushTimeoutMs != null && message.hasOwnProperty("flushTimeoutMs"))
                    object.flushTimeoutMs = message.flushTimeoutMs;
                if (message.notifyTraceur != null && message.hasOwnProperty("notifyTraceur"))
                    object.notifyTraceur = message.notifyTraceur;
                if (message.triggerConfig != null && message.hasOwnProperty("triggerConfig"))
                    object.triggerConfig = $root.perfetto.protos.TraceConfig.TriggerConfig.toObject(message.triggerConfig, options);
                if (message.activateTriggers && message.activateTriggers.length) {
                    object.activateTriggers = [];
                    for (var j = 0; j < message.activateTriggers.length; ++j)
                        object.activateTriggers[j] = message.activateTriggers[j];
                }
                if (message.allowUserBuildTracing != null && message.hasOwnProperty("allowUserBuildTracing"))
                    object.allowUserBuildTracing = message.allowUserBuildTracing;
                if (message.builtinDataSources != null && message.hasOwnProperty("builtinDataSources"))
                    object.builtinDataSources = $root.perfetto.protos.TraceConfig.BuiltinDataSource.toObject(message.builtinDataSources, options);
                if (message.incrementalStateConfig != null && message.hasOwnProperty("incrementalStateConfig"))
                    object.incrementalStateConfig = $root.perfetto.protos.TraceConfig.IncrementalStateConfig.toObject(message.incrementalStateConfig, options);
                if (message.uniqueSessionName != null && message.hasOwnProperty("uniqueSessionName"))
                    object.uniqueSessionName = message.uniqueSessionName;
                if (message.dataSourceStopTimeoutMs != null && message.hasOwnProperty("dataSourceStopTimeoutMs"))
                    object.dataSourceStopTimeoutMs = message.dataSourceStopTimeoutMs;
                if (message.compressionType != null && message.hasOwnProperty("compressionType"))
                    object.compressionType = options.enums === String ? $root.perfetto.protos.TraceConfig.CompressionType[message.compressionType] : message.compressionType;
                if (message.incidentReportConfig != null && message.hasOwnProperty("incidentReportConfig"))
                    object.incidentReportConfig = $root.perfetto.protos.TraceConfig.IncidentReportConfig.toObject(message.incidentReportConfig, options);
                if (message.traceUuidMsb != null && message.hasOwnProperty("traceUuidMsb"))
                    if (typeof message.traceUuidMsb === "number")
                        object.traceUuidMsb = options.longs === String ? String(message.traceUuidMsb) : message.traceUuidMsb;
                    else
                        object.traceUuidMsb = options.longs === String ? $util.Long.prototype.toString.call(message.traceUuidMsb) : options.longs === Number ? new $util.LongBits(message.traceUuidMsb.low >>> 0, message.traceUuidMsb.high >>> 0).toNumber() : message.traceUuidMsb;
                if (message.traceUuidLsb != null && message.hasOwnProperty("traceUuidLsb"))
                    if (typeof message.traceUuidLsb === "number")
                        object.traceUuidLsb = options.longs === String ? String(message.traceUuidLsb) : message.traceUuidLsb;
                    else
                        object.traceUuidLsb = options.longs === String ? $util.Long.prototype.toString.call(message.traceUuidLsb) : options.longs === Number ? new $util.LongBits(message.traceUuidLsb.low >>> 0, message.traceUuidLsb.high >>> 0).toNumber() : message.traceUuidLsb;
                if (message.outputPath != null && message.hasOwnProperty("outputPath"))
                    object.outputPath = message.outputPath;
                if (message.bugreportScore != null && message.hasOwnProperty("bugreportScore"))
                    object.bugreportScore = message.bugreportScore;
                if (message.statsdLogging != null && message.hasOwnProperty("statsdLogging"))
                    object.statsdLogging = options.enums === String ? $root.perfetto.protos.TraceConfig.StatsdLogging[message.statsdLogging] : message.statsdLogging;
                if (message.traceFilter != null && message.hasOwnProperty("traceFilter"))
                    object.traceFilter = $root.perfetto.protos.TraceConfig.TraceFilter.toObject(message.traceFilter, options);
                return object;
            };

            /**
             * Converts this TraceConfig to JSON.
             * @function toJSON
             * @memberof perfetto.protos.TraceConfig
             * @instance
             * @returns {Object.<string,*>} JSON object
             */
            TraceConfig.prototype.toJSON = function toJSON() {
                return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
            };

            TraceConfig.BufferConfig = (function() {

                /**
                 * Properties of a BufferConfig.
                 * @memberof perfetto.protos.TraceConfig
                 * @interface IBufferConfig
                 * @property {number|null} [sizeKb] BufferConfig sizeKb
                 * @property {perfetto.protos.TraceConfig.BufferConfig.FillPolicy|null} [fillPolicy] BufferConfig fillPolicy
                 */

                /**
                 * Constructs a new BufferConfig.
                 * @memberof perfetto.protos.TraceConfig
                 * @classdesc Represents a BufferConfig.
                 * @implements IBufferConfig
                 * @constructor
                 * @param {perfetto.protos.TraceConfig.IBufferConfig=} [properties] Properties to set
                 */
                function BufferConfig(properties) {
                    if (properties)
                        for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                            if (properties[keys[i]] != null)
                                this[keys[i]] = properties[keys[i]];
                }

                /**
                 * BufferConfig sizeKb.
                 * @member {number} sizeKb
                 * @memberof perfetto.protos.TraceConfig.BufferConfig
                 * @instance
                 */
                BufferConfig.prototype.sizeKb = 0;

                /**
                 * BufferConfig fillPolicy.
                 * @member {perfetto.protos.TraceConfig.BufferConfig.FillPolicy} fillPolicy
                 * @memberof perfetto.protos.TraceConfig.BufferConfig
                 * @instance
                 */
                BufferConfig.prototype.fillPolicy = 0;

                /**
                 * Creates a new BufferConfig instance using the specified properties.
                 * @function create
                 * @memberof perfetto.protos.TraceConfig.BufferConfig
                 * @static
                 * @param {perfetto.protos.TraceConfig.IBufferConfig=} [properties] Properties to set
                 * @returns {perfetto.protos.TraceConfig.BufferConfig} BufferConfig instance
                 */
                BufferConfig.create = function create(properties) {
                    return new BufferConfig(properties);
                };

                /**
                 * Encodes the specified BufferConfig message. Does not implicitly {@link perfetto.protos.TraceConfig.BufferConfig.verify|verify} messages.
                 * @function encode
                 * @memberof perfetto.protos.TraceConfig.BufferConfig
                 * @static
                 * @param {perfetto.protos.TraceConfig.IBufferConfig} message BufferConfig message or plain object to encode
                 * @param {$protobuf.Writer} [writer] Writer to encode to
                 * @returns {$protobuf.Writer} Writer
                 */
                BufferConfig.encode = function encode(message, writer) {
                    if (!writer)
                        writer = $Writer.create();
                    if (message.sizeKb != null && Object.hasOwnProperty.call(message, "sizeKb"))
                        writer.uint32(/* id 1, wireType 0 =*/8).uint32(message.sizeKb);
                    if (message.fillPolicy != null && Object.hasOwnProperty.call(message, "fillPolicy"))
                        writer.uint32(/* id 4, wireType 0 =*/32).int32(message.fillPolicy);
                    return writer;
                };

                /**
                 * Encodes the specified BufferConfig message, length delimited. Does not implicitly {@link perfetto.protos.TraceConfig.BufferConfig.verify|verify} messages.
                 * @function encodeDelimited
                 * @memberof perfetto.protos.TraceConfig.BufferConfig
                 * @static
                 * @param {perfetto.protos.TraceConfig.IBufferConfig} message BufferConfig message or plain object to encode
                 * @param {$protobuf.Writer} [writer] Writer to encode to
                 * @returns {$protobuf.Writer} Writer
                 */
                BufferConfig.encodeDelimited = function encodeDelimited(message, writer) {
                    return this.encode(message, writer).ldelim();
                };

                /**
                 * Decodes a BufferConfig message from the specified reader or buffer.
                 * @function decode
                 * @memberof perfetto.protos.TraceConfig.BufferConfig
                 * @static
                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                 * @param {number} [length] Message length if known beforehand
                 * @returns {perfetto.protos.TraceConfig.BufferConfig} BufferConfig
                 * @throws {Error} If the payload is not a reader or valid buffer
                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
                 */
                BufferConfig.decode = function decode(reader, length) {
                    if (!(reader instanceof $Reader))
                        reader = $Reader.create(reader);
                    var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.TraceConfig.BufferConfig();
                    while (reader.pos < end) {
                        var tag = reader.uint32();
                        switch (tag >>> 3) {
                        case 1:
                            message.sizeKb = reader.uint32();
                            break;
                        case 4:
                            message.fillPolicy = reader.int32();
                            break;
                        default:
                            reader.skipType(tag & 7);
                            break;
                        }
                    }
                    return message;
                };

                /**
                 * Decodes a BufferConfig message from the specified reader or buffer, length delimited.
                 * @function decodeDelimited
                 * @memberof perfetto.protos.TraceConfig.BufferConfig
                 * @static
                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                 * @returns {perfetto.protos.TraceConfig.BufferConfig} BufferConfig
                 * @throws {Error} If the payload is not a reader or valid buffer
                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
                 */
                BufferConfig.decodeDelimited = function decodeDelimited(reader) {
                    if (!(reader instanceof $Reader))
                        reader = new $Reader(reader);
                    return this.decode(reader, reader.uint32());
                };

                /**
                 * Verifies a BufferConfig message.
                 * @function verify
                 * @memberof perfetto.protos.TraceConfig.BufferConfig
                 * @static
                 * @param {Object.<string,*>} message Plain object to verify
                 * @returns {string|null} `null` if valid, otherwise the reason why it is not
                 */
                BufferConfig.verify = function verify(message) {
                    if (typeof message !== "object" || message === null)
                        return "object expected";
                    if (message.sizeKb != null && message.hasOwnProperty("sizeKb"))
                        if (!$util.isInteger(message.sizeKb))
                            return "sizeKb: integer expected";
                    if (message.fillPolicy != null && message.hasOwnProperty("fillPolicy"))
                        switch (message.fillPolicy) {
                        default:
                            return "fillPolicy: enum value expected";
                        case 0:
                        case 1:
                        case 2:
                            break;
                        }
                    return null;
                };

                /**
                 * Creates a BufferConfig message from a plain object. Also converts values to their respective internal types.
                 * @function fromObject
                 * @memberof perfetto.protos.TraceConfig.BufferConfig
                 * @static
                 * @param {Object.<string,*>} object Plain object
                 * @returns {perfetto.protos.TraceConfig.BufferConfig} BufferConfig
                 */
                BufferConfig.fromObject = function fromObject(object) {
                    if (object instanceof $root.perfetto.protos.TraceConfig.BufferConfig)
                        return object;
                    var message = new $root.perfetto.protos.TraceConfig.BufferConfig();
                    if (object.sizeKb != null)
                        message.sizeKb = object.sizeKb >>> 0;
                    switch (object.fillPolicy) {
                    case "UNSPECIFIED":
                    case 0:
                        message.fillPolicy = 0;
                        break;
                    case "RING_BUFFER":
                    case 1:
                        message.fillPolicy = 1;
                        break;
                    case "DISCARD":
                    case 2:
                        message.fillPolicy = 2;
                        break;
                    }
                    return message;
                };

                /**
                 * Creates a plain object from a BufferConfig message. Also converts values to other types if specified.
                 * @function toObject
                 * @memberof perfetto.protos.TraceConfig.BufferConfig
                 * @static
                 * @param {perfetto.protos.TraceConfig.BufferConfig} message BufferConfig
                 * @param {$protobuf.IConversionOptions} [options] Conversion options
                 * @returns {Object.<string,*>} Plain object
                 */
                BufferConfig.toObject = function toObject(message, options) {
                    if (!options)
                        options = {};
                    var object = {};
                    if (options.defaults) {
                        object.sizeKb = 0;
                        object.fillPolicy = options.enums === String ? "UNSPECIFIED" : 0;
                    }
                    if (message.sizeKb != null && message.hasOwnProperty("sizeKb"))
                        object.sizeKb = message.sizeKb;
                    if (message.fillPolicy != null && message.hasOwnProperty("fillPolicy"))
                        object.fillPolicy = options.enums === String ? $root.perfetto.protos.TraceConfig.BufferConfig.FillPolicy[message.fillPolicy] : message.fillPolicy;
                    return object;
                };

                /**
                 * Converts this BufferConfig to JSON.
                 * @function toJSON
                 * @memberof perfetto.protos.TraceConfig.BufferConfig
                 * @instance
                 * @returns {Object.<string,*>} JSON object
                 */
                BufferConfig.prototype.toJSON = function toJSON() {
                    return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
                };

                /**
                 * FillPolicy enum.
                 * @name perfetto.protos.TraceConfig.BufferConfig.FillPolicy
                 * @enum {number}
                 * @property {number} UNSPECIFIED=0 UNSPECIFIED value
                 * @property {number} RING_BUFFER=1 RING_BUFFER value
                 * @property {number} DISCARD=2 DISCARD value
                 */
                BufferConfig.FillPolicy = (function() {
                    var valuesById = {}, values = Object.create(valuesById);
                    values[valuesById[0] = "UNSPECIFIED"] = 0;
                    values[valuesById[1] = "RING_BUFFER"] = 1;
                    values[valuesById[2] = "DISCARD"] = 2;
                    return values;
                })();

                return BufferConfig;
            })();

            TraceConfig.DataSource = (function() {

                /**
                 * Properties of a DataSource.
                 * @memberof perfetto.protos.TraceConfig
                 * @interface IDataSource
                 * @property {perfetto.protos.IDataSourceConfig|null} [config] DataSource config
                 * @property {Array.<string>|null} [producerNameFilter] DataSource producerNameFilter
                 * @property {Array.<string>|null} [producerNameRegexFilter] DataSource producerNameRegexFilter
                 */

                /**
                 * Constructs a new DataSource.
                 * @memberof perfetto.protos.TraceConfig
                 * @classdesc Represents a DataSource.
                 * @implements IDataSource
                 * @constructor
                 * @param {perfetto.protos.TraceConfig.IDataSource=} [properties] Properties to set
                 */
                function DataSource(properties) {
                    this.producerNameFilter = [];
                    this.producerNameRegexFilter = [];
                    if (properties)
                        for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                            if (properties[keys[i]] != null)
                                this[keys[i]] = properties[keys[i]];
                }

                /**
                 * DataSource config.
                 * @member {perfetto.protos.IDataSourceConfig|null|undefined} config
                 * @memberof perfetto.protos.TraceConfig.DataSource
                 * @instance
                 */
                DataSource.prototype.config = null;

                /**
                 * DataSource producerNameFilter.
                 * @member {Array.<string>} producerNameFilter
                 * @memberof perfetto.protos.TraceConfig.DataSource
                 * @instance
                 */
                DataSource.prototype.producerNameFilter = $util.emptyArray;

                /**
                 * DataSource producerNameRegexFilter.
                 * @member {Array.<string>} producerNameRegexFilter
                 * @memberof perfetto.protos.TraceConfig.DataSource
                 * @instance
                 */
                DataSource.prototype.producerNameRegexFilter = $util.emptyArray;

                /**
                 * Creates a new DataSource instance using the specified properties.
                 * @function create
                 * @memberof perfetto.protos.TraceConfig.DataSource
                 * @static
                 * @param {perfetto.protos.TraceConfig.IDataSource=} [properties] Properties to set
                 * @returns {perfetto.protos.TraceConfig.DataSource} DataSource instance
                 */
                DataSource.create = function create(properties) {
                    return new DataSource(properties);
                };

                /**
                 * Encodes the specified DataSource message. Does not implicitly {@link perfetto.protos.TraceConfig.DataSource.verify|verify} messages.
                 * @function encode
                 * @memberof perfetto.protos.TraceConfig.DataSource
                 * @static
                 * @param {perfetto.protos.TraceConfig.IDataSource} message DataSource message or plain object to encode
                 * @param {$protobuf.Writer} [writer] Writer to encode to
                 * @returns {$protobuf.Writer} Writer
                 */
                DataSource.encode = function encode(message, writer) {
                    if (!writer)
                        writer = $Writer.create();
                    if (message.config != null && Object.hasOwnProperty.call(message, "config"))
                        $root.perfetto.protos.DataSourceConfig.encode(message.config, writer.uint32(/* id 1, wireType 2 =*/10).fork()).ldelim();
                    if (message.producerNameFilter != null && message.producerNameFilter.length)
                        for (var i = 0; i < message.producerNameFilter.length; ++i)
                            writer.uint32(/* id 2, wireType 2 =*/18).string(message.producerNameFilter[i]);
                    if (message.producerNameRegexFilter != null && message.producerNameRegexFilter.length)
                        for (var i = 0; i < message.producerNameRegexFilter.length; ++i)
                            writer.uint32(/* id 3, wireType 2 =*/26).string(message.producerNameRegexFilter[i]);
                    return writer;
                };

                /**
                 * Encodes the specified DataSource message, length delimited. Does not implicitly {@link perfetto.protos.TraceConfig.DataSource.verify|verify} messages.
                 * @function encodeDelimited
                 * @memberof perfetto.protos.TraceConfig.DataSource
                 * @static
                 * @param {perfetto.protos.TraceConfig.IDataSource} message DataSource message or plain object to encode
                 * @param {$protobuf.Writer} [writer] Writer to encode to
                 * @returns {$protobuf.Writer} Writer
                 */
                DataSource.encodeDelimited = function encodeDelimited(message, writer) {
                    return this.encode(message, writer).ldelim();
                };

                /**
                 * Decodes a DataSource message from the specified reader or buffer.
                 * @function decode
                 * @memberof perfetto.protos.TraceConfig.DataSource
                 * @static
                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                 * @param {number} [length] Message length if known beforehand
                 * @returns {perfetto.protos.TraceConfig.DataSource} DataSource
                 * @throws {Error} If the payload is not a reader or valid buffer
                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
                 */
                DataSource.decode = function decode(reader, length) {
                    if (!(reader instanceof $Reader))
                        reader = $Reader.create(reader);
                    var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.TraceConfig.DataSource();
                    while (reader.pos < end) {
                        var tag = reader.uint32();
                        switch (tag >>> 3) {
                        case 1:
                            message.config = $root.perfetto.protos.DataSourceConfig.decode(reader, reader.uint32());
                            break;
                        case 2:
                            if (!(message.producerNameFilter && message.producerNameFilter.length))
                                message.producerNameFilter = [];
                            message.producerNameFilter.push(reader.string());
                            break;
                        case 3:
                            if (!(message.producerNameRegexFilter && message.producerNameRegexFilter.length))
                                message.producerNameRegexFilter = [];
                            message.producerNameRegexFilter.push(reader.string());
                            break;
                        default:
                            reader.skipType(tag & 7);
                            break;
                        }
                    }
                    return message;
                };

                /**
                 * Decodes a DataSource message from the specified reader or buffer, length delimited.
                 * @function decodeDelimited
                 * @memberof perfetto.protos.TraceConfig.DataSource
                 * @static
                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                 * @returns {perfetto.protos.TraceConfig.DataSource} DataSource
                 * @throws {Error} If the payload is not a reader or valid buffer
                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
                 */
                DataSource.decodeDelimited = function decodeDelimited(reader) {
                    if (!(reader instanceof $Reader))
                        reader = new $Reader(reader);
                    return this.decode(reader, reader.uint32());
                };

                /**
                 * Verifies a DataSource message.
                 * @function verify
                 * @memberof perfetto.protos.TraceConfig.DataSource
                 * @static
                 * @param {Object.<string,*>} message Plain object to verify
                 * @returns {string|null} `null` if valid, otherwise the reason why it is not
                 */
                DataSource.verify = function verify(message) {
                    if (typeof message !== "object" || message === null)
                        return "object expected";
                    if (message.config != null && message.hasOwnProperty("config")) {
                        var error = $root.perfetto.protos.DataSourceConfig.verify(message.config);
                        if (error)
                            return "config." + error;
                    }
                    if (message.producerNameFilter != null && message.hasOwnProperty("producerNameFilter")) {
                        if (!Array.isArray(message.producerNameFilter))
                            return "producerNameFilter: array expected";
                        for (var i = 0; i < message.producerNameFilter.length; ++i)
                            if (!$util.isString(message.producerNameFilter[i]))
                                return "producerNameFilter: string[] expected";
                    }
                    if (message.producerNameRegexFilter != null && message.hasOwnProperty("producerNameRegexFilter")) {
                        if (!Array.isArray(message.producerNameRegexFilter))
                            return "producerNameRegexFilter: array expected";
                        for (var i = 0; i < message.producerNameRegexFilter.length; ++i)
                            if (!$util.isString(message.producerNameRegexFilter[i]))
                                return "producerNameRegexFilter: string[] expected";
                    }
                    return null;
                };

                /**
                 * Creates a DataSource message from a plain object. Also converts values to their respective internal types.
                 * @function fromObject
                 * @memberof perfetto.protos.TraceConfig.DataSource
                 * @static
                 * @param {Object.<string,*>} object Plain object
                 * @returns {perfetto.protos.TraceConfig.DataSource} DataSource
                 */
                DataSource.fromObject = function fromObject(object) {
                    if (object instanceof $root.perfetto.protos.TraceConfig.DataSource)
                        return object;
                    var message = new $root.perfetto.protos.TraceConfig.DataSource();
                    if (object.config != null) {
                        if (typeof object.config !== "object")
                            throw TypeError(".perfetto.protos.TraceConfig.DataSource.config: object expected");
                        message.config = $root.perfetto.protos.DataSourceConfig.fromObject(object.config);
                    }
                    if (object.producerNameFilter) {
                        if (!Array.isArray(object.producerNameFilter))
                            throw TypeError(".perfetto.protos.TraceConfig.DataSource.producerNameFilter: array expected");
                        message.producerNameFilter = [];
                        for (var i = 0; i < object.producerNameFilter.length; ++i)
                            message.producerNameFilter[i] = String(object.producerNameFilter[i]);
                    }
                    if (object.producerNameRegexFilter) {
                        if (!Array.isArray(object.producerNameRegexFilter))
                            throw TypeError(".perfetto.protos.TraceConfig.DataSource.producerNameRegexFilter: array expected");
                        message.producerNameRegexFilter = [];
                        for (var i = 0; i < object.producerNameRegexFilter.length; ++i)
                            message.producerNameRegexFilter[i] = String(object.producerNameRegexFilter[i]);
                    }
                    return message;
                };

                /**
                 * Creates a plain object from a DataSource message. Also converts values to other types if specified.
                 * @function toObject
                 * @memberof perfetto.protos.TraceConfig.DataSource
                 * @static
                 * @param {perfetto.protos.TraceConfig.DataSource} message DataSource
                 * @param {$protobuf.IConversionOptions} [options] Conversion options
                 * @returns {Object.<string,*>} Plain object
                 */
                DataSource.toObject = function toObject(message, options) {
                    if (!options)
                        options = {};
                    var object = {};
                    if (options.arrays || options.defaults) {
                        object.producerNameFilter = [];
                        object.producerNameRegexFilter = [];
                    }
                    if (options.defaults)
                        object.config = null;
                    if (message.config != null && message.hasOwnProperty("config"))
                        object.config = $root.perfetto.protos.DataSourceConfig.toObject(message.config, options);
                    if (message.producerNameFilter && message.producerNameFilter.length) {
                        object.producerNameFilter = [];
                        for (var j = 0; j < message.producerNameFilter.length; ++j)
                            object.producerNameFilter[j] = message.producerNameFilter[j];
                    }
                    if (message.producerNameRegexFilter && message.producerNameRegexFilter.length) {
                        object.producerNameRegexFilter = [];
                        for (var j = 0; j < message.producerNameRegexFilter.length; ++j)
                            object.producerNameRegexFilter[j] = message.producerNameRegexFilter[j];
                    }
                    return object;
                };

                /**
                 * Converts this DataSource to JSON.
                 * @function toJSON
                 * @memberof perfetto.protos.TraceConfig.DataSource
                 * @instance
                 * @returns {Object.<string,*>} JSON object
                 */
                DataSource.prototype.toJSON = function toJSON() {
                    return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
                };

                return DataSource;
            })();

            TraceConfig.BuiltinDataSource = (function() {

                /**
                 * Properties of a BuiltinDataSource.
                 * @memberof perfetto.protos.TraceConfig
                 * @interface IBuiltinDataSource
                 * @property {boolean|null} [disableClockSnapshotting] BuiltinDataSource disableClockSnapshotting
                 * @property {boolean|null} [disableTraceConfig] BuiltinDataSource disableTraceConfig
                 * @property {boolean|null} [disableSystemInfo] BuiltinDataSource disableSystemInfo
                 * @property {boolean|null} [disableServiceEvents] BuiltinDataSource disableServiceEvents
                 * @property {perfetto.protos.BuiltinClock|null} [primaryTraceClock] BuiltinDataSource primaryTraceClock
                 * @property {number|null} [snapshotIntervalMs] BuiltinDataSource snapshotIntervalMs
                 * @property {boolean|null} [preferSuspendClockForSnapshot] BuiltinDataSource preferSuspendClockForSnapshot
                 */

                /**
                 * Constructs a new BuiltinDataSource.
                 * @memberof perfetto.protos.TraceConfig
                 * @classdesc Represents a BuiltinDataSource.
                 * @implements IBuiltinDataSource
                 * @constructor
                 * @param {perfetto.protos.TraceConfig.IBuiltinDataSource=} [properties] Properties to set
                 */
                function BuiltinDataSource(properties) {
                    if (properties)
                        for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                            if (properties[keys[i]] != null)
                                this[keys[i]] = properties[keys[i]];
                }

                /**
                 * BuiltinDataSource disableClockSnapshotting.
                 * @member {boolean} disableClockSnapshotting
                 * @memberof perfetto.protos.TraceConfig.BuiltinDataSource
                 * @instance
                 */
                BuiltinDataSource.prototype.disableClockSnapshotting = false;

                /**
                 * BuiltinDataSource disableTraceConfig.
                 * @member {boolean} disableTraceConfig
                 * @memberof perfetto.protos.TraceConfig.BuiltinDataSource
                 * @instance
                 */
                BuiltinDataSource.prototype.disableTraceConfig = false;

                /**
                 * BuiltinDataSource disableSystemInfo.
                 * @member {boolean} disableSystemInfo
                 * @memberof perfetto.protos.TraceConfig.BuiltinDataSource
                 * @instance
                 */
                BuiltinDataSource.prototype.disableSystemInfo = false;

                /**
                 * BuiltinDataSource disableServiceEvents.
                 * @member {boolean} disableServiceEvents
                 * @memberof perfetto.protos.TraceConfig.BuiltinDataSource
                 * @instance
                 */
                BuiltinDataSource.prototype.disableServiceEvents = false;

                /**
                 * BuiltinDataSource primaryTraceClock.
                 * @member {perfetto.protos.BuiltinClock} primaryTraceClock
                 * @memberof perfetto.protos.TraceConfig.BuiltinDataSource
                 * @instance
                 */
                BuiltinDataSource.prototype.primaryTraceClock = 0;

                /**
                 * BuiltinDataSource snapshotIntervalMs.
                 * @member {number} snapshotIntervalMs
                 * @memberof perfetto.protos.TraceConfig.BuiltinDataSource
                 * @instance
                 */
                BuiltinDataSource.prototype.snapshotIntervalMs = 0;

                /**
                 * BuiltinDataSource preferSuspendClockForSnapshot.
                 * @member {boolean} preferSuspendClockForSnapshot
                 * @memberof perfetto.protos.TraceConfig.BuiltinDataSource
                 * @instance
                 */
                BuiltinDataSource.prototype.preferSuspendClockForSnapshot = false;

                /**
                 * Creates a new BuiltinDataSource instance using the specified properties.
                 * @function create
                 * @memberof perfetto.protos.TraceConfig.BuiltinDataSource
                 * @static
                 * @param {perfetto.protos.TraceConfig.IBuiltinDataSource=} [properties] Properties to set
                 * @returns {perfetto.protos.TraceConfig.BuiltinDataSource} BuiltinDataSource instance
                 */
                BuiltinDataSource.create = function create(properties) {
                    return new BuiltinDataSource(properties);
                };

                /**
                 * Encodes the specified BuiltinDataSource message. Does not implicitly {@link perfetto.protos.TraceConfig.BuiltinDataSource.verify|verify} messages.
                 * @function encode
                 * @memberof perfetto.protos.TraceConfig.BuiltinDataSource
                 * @static
                 * @param {perfetto.protos.TraceConfig.IBuiltinDataSource} message BuiltinDataSource message or plain object to encode
                 * @param {$protobuf.Writer} [writer] Writer to encode to
                 * @returns {$protobuf.Writer} Writer
                 */
                BuiltinDataSource.encode = function encode(message, writer) {
                    if (!writer)
                        writer = $Writer.create();
                    if (message.disableClockSnapshotting != null && Object.hasOwnProperty.call(message, "disableClockSnapshotting"))
                        writer.uint32(/* id 1, wireType 0 =*/8).bool(message.disableClockSnapshotting);
                    if (message.disableTraceConfig != null && Object.hasOwnProperty.call(message, "disableTraceConfig"))
                        writer.uint32(/* id 2, wireType 0 =*/16).bool(message.disableTraceConfig);
                    if (message.disableSystemInfo != null && Object.hasOwnProperty.call(message, "disableSystemInfo"))
                        writer.uint32(/* id 3, wireType 0 =*/24).bool(message.disableSystemInfo);
                    if (message.disableServiceEvents != null && Object.hasOwnProperty.call(message, "disableServiceEvents"))
                        writer.uint32(/* id 4, wireType 0 =*/32).bool(message.disableServiceEvents);
                    if (message.primaryTraceClock != null && Object.hasOwnProperty.call(message, "primaryTraceClock"))
                        writer.uint32(/* id 5, wireType 0 =*/40).int32(message.primaryTraceClock);
                    if (message.snapshotIntervalMs != null && Object.hasOwnProperty.call(message, "snapshotIntervalMs"))
                        writer.uint32(/* id 6, wireType 0 =*/48).uint32(message.snapshotIntervalMs);
                    if (message.preferSuspendClockForSnapshot != null && Object.hasOwnProperty.call(message, "preferSuspendClockForSnapshot"))
                        writer.uint32(/* id 7, wireType 0 =*/56).bool(message.preferSuspendClockForSnapshot);
                    return writer;
                };

                /**
                 * Encodes the specified BuiltinDataSource message, length delimited. Does not implicitly {@link perfetto.protos.TraceConfig.BuiltinDataSource.verify|verify} messages.
                 * @function encodeDelimited
                 * @memberof perfetto.protos.TraceConfig.BuiltinDataSource
                 * @static
                 * @param {perfetto.protos.TraceConfig.IBuiltinDataSource} message BuiltinDataSource message or plain object to encode
                 * @param {$protobuf.Writer} [writer] Writer to encode to
                 * @returns {$protobuf.Writer} Writer
                 */
                BuiltinDataSource.encodeDelimited = function encodeDelimited(message, writer) {
                    return this.encode(message, writer).ldelim();
                };

                /**
                 * Decodes a BuiltinDataSource message from the specified reader or buffer.
                 * @function decode
                 * @memberof perfetto.protos.TraceConfig.BuiltinDataSource
                 * @static
                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                 * @param {number} [length] Message length if known beforehand
                 * @returns {perfetto.protos.TraceConfig.BuiltinDataSource} BuiltinDataSource
                 * @throws {Error} If the payload is not a reader or valid buffer
                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
                 */
                BuiltinDataSource.decode = function decode(reader, length) {
                    if (!(reader instanceof $Reader))
                        reader = $Reader.create(reader);
                    var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.TraceConfig.BuiltinDataSource();
                    while (reader.pos < end) {
                        var tag = reader.uint32();
                        switch (tag >>> 3) {
                        case 1:
                            message.disableClockSnapshotting = reader.bool();
                            break;
                        case 2:
                            message.disableTraceConfig = reader.bool();
                            break;
                        case 3:
                            message.disableSystemInfo = reader.bool();
                            break;
                        case 4:
                            message.disableServiceEvents = reader.bool();
                            break;
                        case 5:
                            message.primaryTraceClock = reader.int32();
                            break;
                        case 6:
                            message.snapshotIntervalMs = reader.uint32();
                            break;
                        case 7:
                            message.preferSuspendClockForSnapshot = reader.bool();
                            break;
                        default:
                            reader.skipType(tag & 7);
                            break;
                        }
                    }
                    return message;
                };

                /**
                 * Decodes a BuiltinDataSource message from the specified reader or buffer, length delimited.
                 * @function decodeDelimited
                 * @memberof perfetto.protos.TraceConfig.BuiltinDataSource
                 * @static
                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                 * @returns {perfetto.protos.TraceConfig.BuiltinDataSource} BuiltinDataSource
                 * @throws {Error} If the payload is not a reader or valid buffer
                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
                 */
                BuiltinDataSource.decodeDelimited = function decodeDelimited(reader) {
                    if (!(reader instanceof $Reader))
                        reader = new $Reader(reader);
                    return this.decode(reader, reader.uint32());
                };

                /**
                 * Verifies a BuiltinDataSource message.
                 * @function verify
                 * @memberof perfetto.protos.TraceConfig.BuiltinDataSource
                 * @static
                 * @param {Object.<string,*>} message Plain object to verify
                 * @returns {string|null} `null` if valid, otherwise the reason why it is not
                 */
                BuiltinDataSource.verify = function verify(message) {
                    if (typeof message !== "object" || message === null)
                        return "object expected";
                    if (message.disableClockSnapshotting != null && message.hasOwnProperty("disableClockSnapshotting"))
                        if (typeof message.disableClockSnapshotting !== "boolean")
                            return "disableClockSnapshotting: boolean expected";
                    if (message.disableTraceConfig != null && message.hasOwnProperty("disableTraceConfig"))
                        if (typeof message.disableTraceConfig !== "boolean")
                            return "disableTraceConfig: boolean expected";
                    if (message.disableSystemInfo != null && message.hasOwnProperty("disableSystemInfo"))
                        if (typeof message.disableSystemInfo !== "boolean")
                            return "disableSystemInfo: boolean expected";
                    if (message.disableServiceEvents != null && message.hasOwnProperty("disableServiceEvents"))
                        if (typeof message.disableServiceEvents !== "boolean")
                            return "disableServiceEvents: boolean expected";
                    if (message.primaryTraceClock != null && message.hasOwnProperty("primaryTraceClock"))
                        switch (message.primaryTraceClock) {
                        default:
                            return "primaryTraceClock: enum value expected";
                        case 0:
                        case 1:
                        case 2:
                        case 3:
                        case 4:
                        case 5:
                        case 6:
                        case 63:
                            break;
                        }
                    if (message.snapshotIntervalMs != null && message.hasOwnProperty("snapshotIntervalMs"))
                        if (!$util.isInteger(message.snapshotIntervalMs))
                            return "snapshotIntervalMs: integer expected";
                    if (message.preferSuspendClockForSnapshot != null && message.hasOwnProperty("preferSuspendClockForSnapshot"))
                        if (typeof message.preferSuspendClockForSnapshot !== "boolean")
                            return "preferSuspendClockForSnapshot: boolean expected";
                    return null;
                };

                /**
                 * Creates a BuiltinDataSource message from a plain object. Also converts values to their respective internal types.
                 * @function fromObject
                 * @memberof perfetto.protos.TraceConfig.BuiltinDataSource
                 * @static
                 * @param {Object.<string,*>} object Plain object
                 * @returns {perfetto.protos.TraceConfig.BuiltinDataSource} BuiltinDataSource
                 */
                BuiltinDataSource.fromObject = function fromObject(object) {
                    if (object instanceof $root.perfetto.protos.TraceConfig.BuiltinDataSource)
                        return object;
                    var message = new $root.perfetto.protos.TraceConfig.BuiltinDataSource();
                    if (object.disableClockSnapshotting != null)
                        message.disableClockSnapshotting = Boolean(object.disableClockSnapshotting);
                    if (object.disableTraceConfig != null)
                        message.disableTraceConfig = Boolean(object.disableTraceConfig);
                    if (object.disableSystemInfo != null)
                        message.disableSystemInfo = Boolean(object.disableSystemInfo);
                    if (object.disableServiceEvents != null)
                        message.disableServiceEvents = Boolean(object.disableServiceEvents);
                    switch (object.primaryTraceClock) {
                    case "BUILTIN_CLOCK_UNKNOWN":
                    case 0:
                        message.primaryTraceClock = 0;
                        break;
                    case "BUILTIN_CLOCK_REALTIME":
                    case 1:
                        message.primaryTraceClock = 1;
                        break;
                    case "BUILTIN_CLOCK_REALTIME_COARSE":
                    case 2:
                        message.primaryTraceClock = 2;
                        break;
                    case "BUILTIN_CLOCK_MONOTONIC":
                    case 3:
                        message.primaryTraceClock = 3;
                        break;
                    case "BUILTIN_CLOCK_MONOTONIC_COARSE":
                    case 4:
                        message.primaryTraceClock = 4;
                        break;
                    case "BUILTIN_CLOCK_MONOTONIC_RAW":
                    case 5:
                        message.primaryTraceClock = 5;
                        break;
                    case "BUILTIN_CLOCK_BOOTTIME":
                    case 6:
                        message.primaryTraceClock = 6;
                        break;
                    case "BUILTIN_CLOCK_MAX_ID":
                    case 63:
                        message.primaryTraceClock = 63;
                        break;
                    }
                    if (object.snapshotIntervalMs != null)
                        message.snapshotIntervalMs = object.snapshotIntervalMs >>> 0;
                    if (object.preferSuspendClockForSnapshot != null)
                        message.preferSuspendClockForSnapshot = Boolean(object.preferSuspendClockForSnapshot);
                    return message;
                };

                /**
                 * Creates a plain object from a BuiltinDataSource message. Also converts values to other types if specified.
                 * @function toObject
                 * @memberof perfetto.protos.TraceConfig.BuiltinDataSource
                 * @static
                 * @param {perfetto.protos.TraceConfig.BuiltinDataSource} message BuiltinDataSource
                 * @param {$protobuf.IConversionOptions} [options] Conversion options
                 * @returns {Object.<string,*>} Plain object
                 */
                BuiltinDataSource.toObject = function toObject(message, options) {
                    if (!options)
                        options = {};
                    var object = {};
                    if (options.defaults) {
                        object.disableClockSnapshotting = false;
                        object.disableTraceConfig = false;
                        object.disableSystemInfo = false;
                        object.disableServiceEvents = false;
                        object.primaryTraceClock = options.enums === String ? "BUILTIN_CLOCK_UNKNOWN" : 0;
                        object.snapshotIntervalMs = 0;
                        object.preferSuspendClockForSnapshot = false;
                    }
                    if (message.disableClockSnapshotting != null && message.hasOwnProperty("disableClockSnapshotting"))
                        object.disableClockSnapshotting = message.disableClockSnapshotting;
                    if (message.disableTraceConfig != null && message.hasOwnProperty("disableTraceConfig"))
                        object.disableTraceConfig = message.disableTraceConfig;
                    if (message.disableSystemInfo != null && message.hasOwnProperty("disableSystemInfo"))
                        object.disableSystemInfo = message.disableSystemInfo;
                    if (message.disableServiceEvents != null && message.hasOwnProperty("disableServiceEvents"))
                        object.disableServiceEvents = message.disableServiceEvents;
                    if (message.primaryTraceClock != null && message.hasOwnProperty("primaryTraceClock"))
                        object.primaryTraceClock = options.enums === String ? $root.perfetto.protos.BuiltinClock[message.primaryTraceClock] : message.primaryTraceClock;
                    if (message.snapshotIntervalMs != null && message.hasOwnProperty("snapshotIntervalMs"))
                        object.snapshotIntervalMs = message.snapshotIntervalMs;
                    if (message.preferSuspendClockForSnapshot != null && message.hasOwnProperty("preferSuspendClockForSnapshot"))
                        object.preferSuspendClockForSnapshot = message.preferSuspendClockForSnapshot;
                    return object;
                };

                /**
                 * Converts this BuiltinDataSource to JSON.
                 * @function toJSON
                 * @memberof perfetto.protos.TraceConfig.BuiltinDataSource
                 * @instance
                 * @returns {Object.<string,*>} JSON object
                 */
                BuiltinDataSource.prototype.toJSON = function toJSON() {
                    return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
                };

                return BuiltinDataSource;
            })();

            /**
             * LockdownModeOperation enum.
             * @name perfetto.protos.TraceConfig.LockdownModeOperation
             * @enum {number}
             * @property {number} LOCKDOWN_UNCHANGED=0 LOCKDOWN_UNCHANGED value
             * @property {number} LOCKDOWN_CLEAR=1 LOCKDOWN_CLEAR value
             * @property {number} LOCKDOWN_SET=2 LOCKDOWN_SET value
             */
            TraceConfig.LockdownModeOperation = (function() {
                var valuesById = {}, values = Object.create(valuesById);
                values[valuesById[0] = "LOCKDOWN_UNCHANGED"] = 0;
                values[valuesById[1] = "LOCKDOWN_CLEAR"] = 1;
                values[valuesById[2] = "LOCKDOWN_SET"] = 2;
                return values;
            })();

            TraceConfig.ProducerConfig = (function() {

                /**
                 * Properties of a ProducerConfig.
                 * @memberof perfetto.protos.TraceConfig
                 * @interface IProducerConfig
                 * @property {string|null} [producerName] ProducerConfig producerName
                 * @property {number|null} [shmSizeKb] ProducerConfig shmSizeKb
                 * @property {number|null} [pageSizeKb] ProducerConfig pageSizeKb
                 */

                /**
                 * Constructs a new ProducerConfig.
                 * @memberof perfetto.protos.TraceConfig
                 * @classdesc Represents a ProducerConfig.
                 * @implements IProducerConfig
                 * @constructor
                 * @param {perfetto.protos.TraceConfig.IProducerConfig=} [properties] Properties to set
                 */
                function ProducerConfig(properties) {
                    if (properties)
                        for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                            if (properties[keys[i]] != null)
                                this[keys[i]] = properties[keys[i]];
                }

                /**
                 * ProducerConfig producerName.
                 * @member {string} producerName
                 * @memberof perfetto.protos.TraceConfig.ProducerConfig
                 * @instance
                 */
                ProducerConfig.prototype.producerName = "";

                /**
                 * ProducerConfig shmSizeKb.
                 * @member {number} shmSizeKb
                 * @memberof perfetto.protos.TraceConfig.ProducerConfig
                 * @instance
                 */
                ProducerConfig.prototype.shmSizeKb = 0;

                /**
                 * ProducerConfig pageSizeKb.
                 * @member {number} pageSizeKb
                 * @memberof perfetto.protos.TraceConfig.ProducerConfig
                 * @instance
                 */
                ProducerConfig.prototype.pageSizeKb = 0;

                /**
                 * Creates a new ProducerConfig instance using the specified properties.
                 * @function create
                 * @memberof perfetto.protos.TraceConfig.ProducerConfig
                 * @static
                 * @param {perfetto.protos.TraceConfig.IProducerConfig=} [properties] Properties to set
                 * @returns {perfetto.protos.TraceConfig.ProducerConfig} ProducerConfig instance
                 */
                ProducerConfig.create = function create(properties) {
                    return new ProducerConfig(properties);
                };

                /**
                 * Encodes the specified ProducerConfig message. Does not implicitly {@link perfetto.protos.TraceConfig.ProducerConfig.verify|verify} messages.
                 * @function encode
                 * @memberof perfetto.protos.TraceConfig.ProducerConfig
                 * @static
                 * @param {perfetto.protos.TraceConfig.IProducerConfig} message ProducerConfig message or plain object to encode
                 * @param {$protobuf.Writer} [writer] Writer to encode to
                 * @returns {$protobuf.Writer} Writer
                 */
                ProducerConfig.encode = function encode(message, writer) {
                    if (!writer)
                        writer = $Writer.create();
                    if (message.producerName != null && Object.hasOwnProperty.call(message, "producerName"))
                        writer.uint32(/* id 1, wireType 2 =*/10).string(message.producerName);
                    if (message.shmSizeKb != null && Object.hasOwnProperty.call(message, "shmSizeKb"))
                        writer.uint32(/* id 2, wireType 0 =*/16).uint32(message.shmSizeKb);
                    if (message.pageSizeKb != null && Object.hasOwnProperty.call(message, "pageSizeKb"))
                        writer.uint32(/* id 3, wireType 0 =*/24).uint32(message.pageSizeKb);
                    return writer;
                };

                /**
                 * Encodes the specified ProducerConfig message, length delimited. Does not implicitly {@link perfetto.protos.TraceConfig.ProducerConfig.verify|verify} messages.
                 * @function encodeDelimited
                 * @memberof perfetto.protos.TraceConfig.ProducerConfig
                 * @static
                 * @param {perfetto.protos.TraceConfig.IProducerConfig} message ProducerConfig message or plain object to encode
                 * @param {$protobuf.Writer} [writer] Writer to encode to
                 * @returns {$protobuf.Writer} Writer
                 */
                ProducerConfig.encodeDelimited = function encodeDelimited(message, writer) {
                    return this.encode(message, writer).ldelim();
                };

                /**
                 * Decodes a ProducerConfig message from the specified reader or buffer.
                 * @function decode
                 * @memberof perfetto.protos.TraceConfig.ProducerConfig
                 * @static
                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                 * @param {number} [length] Message length if known beforehand
                 * @returns {perfetto.protos.TraceConfig.ProducerConfig} ProducerConfig
                 * @throws {Error} If the payload is not a reader or valid buffer
                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
                 */
                ProducerConfig.decode = function decode(reader, length) {
                    if (!(reader instanceof $Reader))
                        reader = $Reader.create(reader);
                    var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.TraceConfig.ProducerConfig();
                    while (reader.pos < end) {
                        var tag = reader.uint32();
                        switch (tag >>> 3) {
                        case 1:
                            message.producerName = reader.string();
                            break;
                        case 2:
                            message.shmSizeKb = reader.uint32();
                            break;
                        case 3:
                            message.pageSizeKb = reader.uint32();
                            break;
                        default:
                            reader.skipType(tag & 7);
                            break;
                        }
                    }
                    return message;
                };

                /**
                 * Decodes a ProducerConfig message from the specified reader or buffer, length delimited.
                 * @function decodeDelimited
                 * @memberof perfetto.protos.TraceConfig.ProducerConfig
                 * @static
                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                 * @returns {perfetto.protos.TraceConfig.ProducerConfig} ProducerConfig
                 * @throws {Error} If the payload is not a reader or valid buffer
                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
                 */
                ProducerConfig.decodeDelimited = function decodeDelimited(reader) {
                    if (!(reader instanceof $Reader))
                        reader = new $Reader(reader);
                    return this.decode(reader, reader.uint32());
                };

                /**
                 * Verifies a ProducerConfig message.
                 * @function verify
                 * @memberof perfetto.protos.TraceConfig.ProducerConfig
                 * @static
                 * @param {Object.<string,*>} message Plain object to verify
                 * @returns {string|null} `null` if valid, otherwise the reason why it is not
                 */
                ProducerConfig.verify = function verify(message) {
                    if (typeof message !== "object" || message === null)
                        return "object expected";
                    if (message.producerName != null && message.hasOwnProperty("producerName"))
                        if (!$util.isString(message.producerName))
                            return "producerName: string expected";
                    if (message.shmSizeKb != null && message.hasOwnProperty("shmSizeKb"))
                        if (!$util.isInteger(message.shmSizeKb))
                            return "shmSizeKb: integer expected";
                    if (message.pageSizeKb != null && message.hasOwnProperty("pageSizeKb"))
                        if (!$util.isInteger(message.pageSizeKb))
                            return "pageSizeKb: integer expected";
                    return null;
                };

                /**
                 * Creates a ProducerConfig message from a plain object. Also converts values to their respective internal types.
                 * @function fromObject
                 * @memberof perfetto.protos.TraceConfig.ProducerConfig
                 * @static
                 * @param {Object.<string,*>} object Plain object
                 * @returns {perfetto.protos.TraceConfig.ProducerConfig} ProducerConfig
                 */
                ProducerConfig.fromObject = function fromObject(object) {
                    if (object instanceof $root.perfetto.protos.TraceConfig.ProducerConfig)
                        return object;
                    var message = new $root.perfetto.protos.TraceConfig.ProducerConfig();
                    if (object.producerName != null)
                        message.producerName = String(object.producerName);
                    if (object.shmSizeKb != null)
                        message.shmSizeKb = object.shmSizeKb >>> 0;
                    if (object.pageSizeKb != null)
                        message.pageSizeKb = object.pageSizeKb >>> 0;
                    return message;
                };

                /**
                 * Creates a plain object from a ProducerConfig message. Also converts values to other types if specified.
                 * @function toObject
                 * @memberof perfetto.protos.TraceConfig.ProducerConfig
                 * @static
                 * @param {perfetto.protos.TraceConfig.ProducerConfig} message ProducerConfig
                 * @param {$protobuf.IConversionOptions} [options] Conversion options
                 * @returns {Object.<string,*>} Plain object
                 */
                ProducerConfig.toObject = function toObject(message, options) {
                    if (!options)
                        options = {};
                    var object = {};
                    if (options.defaults) {
                        object.producerName = "";
                        object.shmSizeKb = 0;
                        object.pageSizeKb = 0;
                    }
                    if (message.producerName != null && message.hasOwnProperty("producerName"))
                        object.producerName = message.producerName;
                    if (message.shmSizeKb != null && message.hasOwnProperty("shmSizeKb"))
                        object.shmSizeKb = message.shmSizeKb;
                    if (message.pageSizeKb != null && message.hasOwnProperty("pageSizeKb"))
                        object.pageSizeKb = message.pageSizeKb;
                    return object;
                };

                /**
                 * Converts this ProducerConfig to JSON.
                 * @function toJSON
                 * @memberof perfetto.protos.TraceConfig.ProducerConfig
                 * @instance
                 * @returns {Object.<string,*>} JSON object
                 */
                ProducerConfig.prototype.toJSON = function toJSON() {
                    return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
                };

                return ProducerConfig;
            })();

            TraceConfig.StatsdMetadata = (function() {

                /**
                 * Properties of a StatsdMetadata.
                 * @memberof perfetto.protos.TraceConfig
                 * @interface IStatsdMetadata
                 * @property {number|null} [triggeringAlertId] StatsdMetadata triggeringAlertId
                 * @property {number|null} [triggeringConfigUid] StatsdMetadata triggeringConfigUid
                 * @property {number|null} [triggeringConfigId] StatsdMetadata triggeringConfigId
                 * @property {number|null} [triggeringSubscriptionId] StatsdMetadata triggeringSubscriptionId
                 */

                /**
                 * Constructs a new StatsdMetadata.
                 * @memberof perfetto.protos.TraceConfig
                 * @classdesc Represents a StatsdMetadata.
                 * @implements IStatsdMetadata
                 * @constructor
                 * @param {perfetto.protos.TraceConfig.IStatsdMetadata=} [properties] Properties to set
                 */
                function StatsdMetadata(properties) {
                    if (properties)
                        for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                            if (properties[keys[i]] != null)
                                this[keys[i]] = properties[keys[i]];
                }

                /**
                 * StatsdMetadata triggeringAlertId.
                 * @member {number} triggeringAlertId
                 * @memberof perfetto.protos.TraceConfig.StatsdMetadata
                 * @instance
                 */
                StatsdMetadata.prototype.triggeringAlertId = $util.Long ? $util.Long.fromBits(0,0,false) : 0;

                /**
                 * StatsdMetadata triggeringConfigUid.
                 * @member {number} triggeringConfigUid
                 * @memberof perfetto.protos.TraceConfig.StatsdMetadata
                 * @instance
                 */
                StatsdMetadata.prototype.triggeringConfigUid = 0;

                /**
                 * StatsdMetadata triggeringConfigId.
                 * @member {number} triggeringConfigId
                 * @memberof perfetto.protos.TraceConfig.StatsdMetadata
                 * @instance
                 */
                StatsdMetadata.prototype.triggeringConfigId = $util.Long ? $util.Long.fromBits(0,0,false) : 0;

                /**
                 * StatsdMetadata triggeringSubscriptionId.
                 * @member {number} triggeringSubscriptionId
                 * @memberof perfetto.protos.TraceConfig.StatsdMetadata
                 * @instance
                 */
                StatsdMetadata.prototype.triggeringSubscriptionId = $util.Long ? $util.Long.fromBits(0,0,false) : 0;

                /**
                 * Creates a new StatsdMetadata instance using the specified properties.
                 * @function create
                 * @memberof perfetto.protos.TraceConfig.StatsdMetadata
                 * @static
                 * @param {perfetto.protos.TraceConfig.IStatsdMetadata=} [properties] Properties to set
                 * @returns {perfetto.protos.TraceConfig.StatsdMetadata} StatsdMetadata instance
                 */
                StatsdMetadata.create = function create(properties) {
                    return new StatsdMetadata(properties);
                };

                /**
                 * Encodes the specified StatsdMetadata message. Does not implicitly {@link perfetto.protos.TraceConfig.StatsdMetadata.verify|verify} messages.
                 * @function encode
                 * @memberof perfetto.protos.TraceConfig.StatsdMetadata
                 * @static
                 * @param {perfetto.protos.TraceConfig.IStatsdMetadata} message StatsdMetadata message or plain object to encode
                 * @param {$protobuf.Writer} [writer] Writer to encode to
                 * @returns {$protobuf.Writer} Writer
                 */
                StatsdMetadata.encode = function encode(message, writer) {
                    if (!writer)
                        writer = $Writer.create();
                    if (message.triggeringAlertId != null && Object.hasOwnProperty.call(message, "triggeringAlertId"))
                        writer.uint32(/* id 1, wireType 0 =*/8).int64(message.triggeringAlertId);
                    if (message.triggeringConfigUid != null && Object.hasOwnProperty.call(message, "triggeringConfigUid"))
                        writer.uint32(/* id 2, wireType 0 =*/16).int32(message.triggeringConfigUid);
                    if (message.triggeringConfigId != null && Object.hasOwnProperty.call(message, "triggeringConfigId"))
                        writer.uint32(/* id 3, wireType 0 =*/24).int64(message.triggeringConfigId);
                    if (message.triggeringSubscriptionId != null && Object.hasOwnProperty.call(message, "triggeringSubscriptionId"))
                        writer.uint32(/* id 4, wireType 0 =*/32).int64(message.triggeringSubscriptionId);
                    return writer;
                };

                /**
                 * Encodes the specified StatsdMetadata message, length delimited. Does not implicitly {@link perfetto.protos.TraceConfig.StatsdMetadata.verify|verify} messages.
                 * @function encodeDelimited
                 * @memberof perfetto.protos.TraceConfig.StatsdMetadata
                 * @static
                 * @param {perfetto.protos.TraceConfig.IStatsdMetadata} message StatsdMetadata message or plain object to encode
                 * @param {$protobuf.Writer} [writer] Writer to encode to
                 * @returns {$protobuf.Writer} Writer
                 */
                StatsdMetadata.encodeDelimited = function encodeDelimited(message, writer) {
                    return this.encode(message, writer).ldelim();
                };

                /**
                 * Decodes a StatsdMetadata message from the specified reader or buffer.
                 * @function decode
                 * @memberof perfetto.protos.TraceConfig.StatsdMetadata
                 * @static
                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                 * @param {number} [length] Message length if known beforehand
                 * @returns {perfetto.protos.TraceConfig.StatsdMetadata} StatsdMetadata
                 * @throws {Error} If the payload is not a reader or valid buffer
                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
                 */
                StatsdMetadata.decode = function decode(reader, length) {
                    if (!(reader instanceof $Reader))
                        reader = $Reader.create(reader);
                    var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.TraceConfig.StatsdMetadata();
                    while (reader.pos < end) {
                        var tag = reader.uint32();
                        switch (tag >>> 3) {
                        case 1:
                            message.triggeringAlertId = reader.int64();
                            break;
                        case 2:
                            message.triggeringConfigUid = reader.int32();
                            break;
                        case 3:
                            message.triggeringConfigId = reader.int64();
                            break;
                        case 4:
                            message.triggeringSubscriptionId = reader.int64();
                            break;
                        default:
                            reader.skipType(tag & 7);
                            break;
                        }
                    }
                    return message;
                };

                /**
                 * Decodes a StatsdMetadata message from the specified reader or buffer, length delimited.
                 * @function decodeDelimited
                 * @memberof perfetto.protos.TraceConfig.StatsdMetadata
                 * @static
                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                 * @returns {perfetto.protos.TraceConfig.StatsdMetadata} StatsdMetadata
                 * @throws {Error} If the payload is not a reader or valid buffer
                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
                 */
                StatsdMetadata.decodeDelimited = function decodeDelimited(reader) {
                    if (!(reader instanceof $Reader))
                        reader = new $Reader(reader);
                    return this.decode(reader, reader.uint32());
                };

                /**
                 * Verifies a StatsdMetadata message.
                 * @function verify
                 * @memberof perfetto.protos.TraceConfig.StatsdMetadata
                 * @static
                 * @param {Object.<string,*>} message Plain object to verify
                 * @returns {string|null} `null` if valid, otherwise the reason why it is not
                 */
                StatsdMetadata.verify = function verify(message) {
                    if (typeof message !== "object" || message === null)
                        return "object expected";
                    if (message.triggeringAlertId != null && message.hasOwnProperty("triggeringAlertId"))
                        if (!$util.isInteger(message.triggeringAlertId) && !(message.triggeringAlertId && $util.isInteger(message.triggeringAlertId.low) && $util.isInteger(message.triggeringAlertId.high)))
                            return "triggeringAlertId: integer|Long expected";
                    if (message.triggeringConfigUid != null && message.hasOwnProperty("triggeringConfigUid"))
                        if (!$util.isInteger(message.triggeringConfigUid))
                            return "triggeringConfigUid: integer expected";
                    if (message.triggeringConfigId != null && message.hasOwnProperty("triggeringConfigId"))
                        if (!$util.isInteger(message.triggeringConfigId) && !(message.triggeringConfigId && $util.isInteger(message.triggeringConfigId.low) && $util.isInteger(message.triggeringConfigId.high)))
                            return "triggeringConfigId: integer|Long expected";
                    if (message.triggeringSubscriptionId != null && message.hasOwnProperty("triggeringSubscriptionId"))
                        if (!$util.isInteger(message.triggeringSubscriptionId) && !(message.triggeringSubscriptionId && $util.isInteger(message.triggeringSubscriptionId.low) && $util.isInteger(message.triggeringSubscriptionId.high)))
                            return "triggeringSubscriptionId: integer|Long expected";
                    return null;
                };

                /**
                 * Creates a StatsdMetadata message from a plain object. Also converts values to their respective internal types.
                 * @function fromObject
                 * @memberof perfetto.protos.TraceConfig.StatsdMetadata
                 * @static
                 * @param {Object.<string,*>} object Plain object
                 * @returns {perfetto.protos.TraceConfig.StatsdMetadata} StatsdMetadata
                 */
                StatsdMetadata.fromObject = function fromObject(object) {
                    if (object instanceof $root.perfetto.protos.TraceConfig.StatsdMetadata)
                        return object;
                    var message = new $root.perfetto.protos.TraceConfig.StatsdMetadata();
                    if (object.triggeringAlertId != null)
                        if ($util.Long)
                            (message.triggeringAlertId = $util.Long.fromValue(object.triggeringAlertId)).unsigned = false;
                        else if (typeof object.triggeringAlertId === "string")
                            message.triggeringAlertId = parseInt(object.triggeringAlertId, 10);
                        else if (typeof object.triggeringAlertId === "number")
                            message.triggeringAlertId = object.triggeringAlertId;
                        else if (typeof object.triggeringAlertId === "object")
                            message.triggeringAlertId = new $util.LongBits(object.triggeringAlertId.low >>> 0, object.triggeringAlertId.high >>> 0).toNumber();
                    if (object.triggeringConfigUid != null)
                        message.triggeringConfigUid = object.triggeringConfigUid | 0;
                    if (object.triggeringConfigId != null)
                        if ($util.Long)
                            (message.triggeringConfigId = $util.Long.fromValue(object.triggeringConfigId)).unsigned = false;
                        else if (typeof object.triggeringConfigId === "string")
                            message.triggeringConfigId = parseInt(object.triggeringConfigId, 10);
                        else if (typeof object.triggeringConfigId === "number")
                            message.triggeringConfigId = object.triggeringConfigId;
                        else if (typeof object.triggeringConfigId === "object")
                            message.triggeringConfigId = new $util.LongBits(object.triggeringConfigId.low >>> 0, object.triggeringConfigId.high >>> 0).toNumber();
                    if (object.triggeringSubscriptionId != null)
                        if ($util.Long)
                            (message.triggeringSubscriptionId = $util.Long.fromValue(object.triggeringSubscriptionId)).unsigned = false;
                        else if (typeof object.triggeringSubscriptionId === "string")
                            message.triggeringSubscriptionId = parseInt(object.triggeringSubscriptionId, 10);
                        else if (typeof object.triggeringSubscriptionId === "number")
                            message.triggeringSubscriptionId = object.triggeringSubscriptionId;
                        else if (typeof object.triggeringSubscriptionId === "object")
                            message.triggeringSubscriptionId = new $util.LongBits(object.triggeringSubscriptionId.low >>> 0, object.triggeringSubscriptionId.high >>> 0).toNumber();
                    return message;
                };

                /**
                 * Creates a plain object from a StatsdMetadata message. Also converts values to other types if specified.
                 * @function toObject
                 * @memberof perfetto.protos.TraceConfig.StatsdMetadata
                 * @static
                 * @param {perfetto.protos.TraceConfig.StatsdMetadata} message StatsdMetadata
                 * @param {$protobuf.IConversionOptions} [options] Conversion options
                 * @returns {Object.<string,*>} Plain object
                 */
                StatsdMetadata.toObject = function toObject(message, options) {
                    if (!options)
                        options = {};
                    var object = {};
                    if (options.defaults) {
                        if ($util.Long) {
                            var long = new $util.Long(0, 0, false);
                            object.triggeringAlertId = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
                        } else
                            object.triggeringAlertId = options.longs === String ? "0" : 0;
                        object.triggeringConfigUid = 0;
                        if ($util.Long) {
                            var long = new $util.Long(0, 0, false);
                            object.triggeringConfigId = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
                        } else
                            object.triggeringConfigId = options.longs === String ? "0" : 0;
                        if ($util.Long) {
                            var long = new $util.Long(0, 0, false);
                            object.triggeringSubscriptionId = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
                        } else
                            object.triggeringSubscriptionId = options.longs === String ? "0" : 0;
                    }
                    if (message.triggeringAlertId != null && message.hasOwnProperty("triggeringAlertId"))
                        if (typeof message.triggeringAlertId === "number")
                            object.triggeringAlertId = options.longs === String ? String(message.triggeringAlertId) : message.triggeringAlertId;
                        else
                            object.triggeringAlertId = options.longs === String ? $util.Long.prototype.toString.call(message.triggeringAlertId) : options.longs === Number ? new $util.LongBits(message.triggeringAlertId.low >>> 0, message.triggeringAlertId.high >>> 0).toNumber() : message.triggeringAlertId;
                    if (message.triggeringConfigUid != null && message.hasOwnProperty("triggeringConfigUid"))
                        object.triggeringConfigUid = message.triggeringConfigUid;
                    if (message.triggeringConfigId != null && message.hasOwnProperty("triggeringConfigId"))
                        if (typeof message.triggeringConfigId === "number")
                            object.triggeringConfigId = options.longs === String ? String(message.triggeringConfigId) : message.triggeringConfigId;
                        else
                            object.triggeringConfigId = options.longs === String ? $util.Long.prototype.toString.call(message.triggeringConfigId) : options.longs === Number ? new $util.LongBits(message.triggeringConfigId.low >>> 0, message.triggeringConfigId.high >>> 0).toNumber() : message.triggeringConfigId;
                    if (message.triggeringSubscriptionId != null && message.hasOwnProperty("triggeringSubscriptionId"))
                        if (typeof message.triggeringSubscriptionId === "number")
                            object.triggeringSubscriptionId = options.longs === String ? String(message.triggeringSubscriptionId) : message.triggeringSubscriptionId;
                        else
                            object.triggeringSubscriptionId = options.longs === String ? $util.Long.prototype.toString.call(message.triggeringSubscriptionId) : options.longs === Number ? new $util.LongBits(message.triggeringSubscriptionId.low >>> 0, message.triggeringSubscriptionId.high >>> 0).toNumber() : message.triggeringSubscriptionId;
                    return object;
                };

                /**
                 * Converts this StatsdMetadata to JSON.
                 * @function toJSON
                 * @memberof perfetto.protos.TraceConfig.StatsdMetadata
                 * @instance
                 * @returns {Object.<string,*>} JSON object
                 */
                StatsdMetadata.prototype.toJSON = function toJSON() {
                    return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
                };

                return StatsdMetadata;
            })();

            TraceConfig.GuardrailOverrides = (function() {

                /**
                 * Properties of a GuardrailOverrides.
                 * @memberof perfetto.protos.TraceConfig
                 * @interface IGuardrailOverrides
                 * @property {number|null} [maxUploadPerDayBytes] GuardrailOverrides maxUploadPerDayBytes
                 */

                /**
                 * Constructs a new GuardrailOverrides.
                 * @memberof perfetto.protos.TraceConfig
                 * @classdesc Represents a GuardrailOverrides.
                 * @implements IGuardrailOverrides
                 * @constructor
                 * @param {perfetto.protos.TraceConfig.IGuardrailOverrides=} [properties] Properties to set
                 */
                function GuardrailOverrides(properties) {
                    if (properties)
                        for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                            if (properties[keys[i]] != null)
                                this[keys[i]] = properties[keys[i]];
                }

                /**
                 * GuardrailOverrides maxUploadPerDayBytes.
                 * @member {number} maxUploadPerDayBytes
                 * @memberof perfetto.protos.TraceConfig.GuardrailOverrides
                 * @instance
                 */
                GuardrailOverrides.prototype.maxUploadPerDayBytes = $util.Long ? $util.Long.fromBits(0,0,true) : 0;

                /**
                 * Creates a new GuardrailOverrides instance using the specified properties.
                 * @function create
                 * @memberof perfetto.protos.TraceConfig.GuardrailOverrides
                 * @static
                 * @param {perfetto.protos.TraceConfig.IGuardrailOverrides=} [properties] Properties to set
                 * @returns {perfetto.protos.TraceConfig.GuardrailOverrides} GuardrailOverrides instance
                 */
                GuardrailOverrides.create = function create(properties) {
                    return new GuardrailOverrides(properties);
                };

                /**
                 * Encodes the specified GuardrailOverrides message. Does not implicitly {@link perfetto.protos.TraceConfig.GuardrailOverrides.verify|verify} messages.
                 * @function encode
                 * @memberof perfetto.protos.TraceConfig.GuardrailOverrides
                 * @static
                 * @param {perfetto.protos.TraceConfig.IGuardrailOverrides} message GuardrailOverrides message or plain object to encode
                 * @param {$protobuf.Writer} [writer] Writer to encode to
                 * @returns {$protobuf.Writer} Writer
                 */
                GuardrailOverrides.encode = function encode(message, writer) {
                    if (!writer)
                        writer = $Writer.create();
                    if (message.maxUploadPerDayBytes != null && Object.hasOwnProperty.call(message, "maxUploadPerDayBytes"))
                        writer.uint32(/* id 1, wireType 0 =*/8).uint64(message.maxUploadPerDayBytes);
                    return writer;
                };

                /**
                 * Encodes the specified GuardrailOverrides message, length delimited. Does not implicitly {@link perfetto.protos.TraceConfig.GuardrailOverrides.verify|verify} messages.
                 * @function encodeDelimited
                 * @memberof perfetto.protos.TraceConfig.GuardrailOverrides
                 * @static
                 * @param {perfetto.protos.TraceConfig.IGuardrailOverrides} message GuardrailOverrides message or plain object to encode
                 * @param {$protobuf.Writer} [writer] Writer to encode to
                 * @returns {$protobuf.Writer} Writer
                 */
                GuardrailOverrides.encodeDelimited = function encodeDelimited(message, writer) {
                    return this.encode(message, writer).ldelim();
                };

                /**
                 * Decodes a GuardrailOverrides message from the specified reader or buffer.
                 * @function decode
                 * @memberof perfetto.protos.TraceConfig.GuardrailOverrides
                 * @static
                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                 * @param {number} [length] Message length if known beforehand
                 * @returns {perfetto.protos.TraceConfig.GuardrailOverrides} GuardrailOverrides
                 * @throws {Error} If the payload is not a reader or valid buffer
                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
                 */
                GuardrailOverrides.decode = function decode(reader, length) {
                    if (!(reader instanceof $Reader))
                        reader = $Reader.create(reader);
                    var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.TraceConfig.GuardrailOverrides();
                    while (reader.pos < end) {
                        var tag = reader.uint32();
                        switch (tag >>> 3) {
                        case 1:
                            message.maxUploadPerDayBytes = reader.uint64();
                            break;
                        default:
                            reader.skipType(tag & 7);
                            break;
                        }
                    }
                    return message;
                };

                /**
                 * Decodes a GuardrailOverrides message from the specified reader or buffer, length delimited.
                 * @function decodeDelimited
                 * @memberof perfetto.protos.TraceConfig.GuardrailOverrides
                 * @static
                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                 * @returns {perfetto.protos.TraceConfig.GuardrailOverrides} GuardrailOverrides
                 * @throws {Error} If the payload is not a reader or valid buffer
                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
                 */
                GuardrailOverrides.decodeDelimited = function decodeDelimited(reader) {
                    if (!(reader instanceof $Reader))
                        reader = new $Reader(reader);
                    return this.decode(reader, reader.uint32());
                };

                /**
                 * Verifies a GuardrailOverrides message.
                 * @function verify
                 * @memberof perfetto.protos.TraceConfig.GuardrailOverrides
                 * @static
                 * @param {Object.<string,*>} message Plain object to verify
                 * @returns {string|null} `null` if valid, otherwise the reason why it is not
                 */
                GuardrailOverrides.verify = function verify(message) {
                    if (typeof message !== "object" || message === null)
                        return "object expected";
                    if (message.maxUploadPerDayBytes != null && message.hasOwnProperty("maxUploadPerDayBytes"))
                        if (!$util.isInteger(message.maxUploadPerDayBytes) && !(message.maxUploadPerDayBytes && $util.isInteger(message.maxUploadPerDayBytes.low) && $util.isInteger(message.maxUploadPerDayBytes.high)))
                            return "maxUploadPerDayBytes: integer|Long expected";
                    return null;
                };

                /**
                 * Creates a GuardrailOverrides message from a plain object. Also converts values to their respective internal types.
                 * @function fromObject
                 * @memberof perfetto.protos.TraceConfig.GuardrailOverrides
                 * @static
                 * @param {Object.<string,*>} object Plain object
                 * @returns {perfetto.protos.TraceConfig.GuardrailOverrides} GuardrailOverrides
                 */
                GuardrailOverrides.fromObject = function fromObject(object) {
                    if (object instanceof $root.perfetto.protos.TraceConfig.GuardrailOverrides)
                        return object;
                    var message = new $root.perfetto.protos.TraceConfig.GuardrailOverrides();
                    if (object.maxUploadPerDayBytes != null)
                        if ($util.Long)
                            (message.maxUploadPerDayBytes = $util.Long.fromValue(object.maxUploadPerDayBytes)).unsigned = true;
                        else if (typeof object.maxUploadPerDayBytes === "string")
                            message.maxUploadPerDayBytes = parseInt(object.maxUploadPerDayBytes, 10);
                        else if (typeof object.maxUploadPerDayBytes === "number")
                            message.maxUploadPerDayBytes = object.maxUploadPerDayBytes;
                        else if (typeof object.maxUploadPerDayBytes === "object")
                            message.maxUploadPerDayBytes = new $util.LongBits(object.maxUploadPerDayBytes.low >>> 0, object.maxUploadPerDayBytes.high >>> 0).toNumber(true);
                    return message;
                };

                /**
                 * Creates a plain object from a GuardrailOverrides message. Also converts values to other types if specified.
                 * @function toObject
                 * @memberof perfetto.protos.TraceConfig.GuardrailOverrides
                 * @static
                 * @param {perfetto.protos.TraceConfig.GuardrailOverrides} message GuardrailOverrides
                 * @param {$protobuf.IConversionOptions} [options] Conversion options
                 * @returns {Object.<string,*>} Plain object
                 */
                GuardrailOverrides.toObject = function toObject(message, options) {
                    if (!options)
                        options = {};
                    var object = {};
                    if (options.defaults)
                        if ($util.Long) {
                            var long = new $util.Long(0, 0, true);
                            object.maxUploadPerDayBytes = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
                        } else
                            object.maxUploadPerDayBytes = options.longs === String ? "0" : 0;
                    if (message.maxUploadPerDayBytes != null && message.hasOwnProperty("maxUploadPerDayBytes"))
                        if (typeof message.maxUploadPerDayBytes === "number")
                            object.maxUploadPerDayBytes = options.longs === String ? String(message.maxUploadPerDayBytes) : message.maxUploadPerDayBytes;
                        else
                            object.maxUploadPerDayBytes = options.longs === String ? $util.Long.prototype.toString.call(message.maxUploadPerDayBytes) : options.longs === Number ? new $util.LongBits(message.maxUploadPerDayBytes.low >>> 0, message.maxUploadPerDayBytes.high >>> 0).toNumber(true) : message.maxUploadPerDayBytes;
                    return object;
                };

                /**
                 * Converts this GuardrailOverrides to JSON.
                 * @function toJSON
                 * @memberof perfetto.protos.TraceConfig.GuardrailOverrides
                 * @instance
                 * @returns {Object.<string,*>} JSON object
                 */
                GuardrailOverrides.prototype.toJSON = function toJSON() {
                    return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
                };

                return GuardrailOverrides;
            })();

            TraceConfig.TriggerConfig = (function() {

                /**
                 * Properties of a TriggerConfig.
                 * @memberof perfetto.protos.TraceConfig
                 * @interface ITriggerConfig
                 * @property {perfetto.protos.TraceConfig.TriggerConfig.TriggerMode|null} [triggerMode] TriggerConfig triggerMode
                 * @property {Array.<perfetto.protos.TraceConfig.TriggerConfig.ITrigger>|null} [triggers] TriggerConfig triggers
                 * @property {number|null} [triggerTimeoutMs] TriggerConfig triggerTimeoutMs
                 */

                /**
                 * Constructs a new TriggerConfig.
                 * @memberof perfetto.protos.TraceConfig
                 * @classdesc Represents a TriggerConfig.
                 * @implements ITriggerConfig
                 * @constructor
                 * @param {perfetto.protos.TraceConfig.ITriggerConfig=} [properties] Properties to set
                 */
                function TriggerConfig(properties) {
                    this.triggers = [];
                    if (properties)
                        for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                            if (properties[keys[i]] != null)
                                this[keys[i]] = properties[keys[i]];
                }

                /**
                 * TriggerConfig triggerMode.
                 * @member {perfetto.protos.TraceConfig.TriggerConfig.TriggerMode} triggerMode
                 * @memberof perfetto.protos.TraceConfig.TriggerConfig
                 * @instance
                 */
                TriggerConfig.prototype.triggerMode = 0;

                /**
                 * TriggerConfig triggers.
                 * @member {Array.<perfetto.protos.TraceConfig.TriggerConfig.ITrigger>} triggers
                 * @memberof perfetto.protos.TraceConfig.TriggerConfig
                 * @instance
                 */
                TriggerConfig.prototype.triggers = $util.emptyArray;

                /**
                 * TriggerConfig triggerTimeoutMs.
                 * @member {number} triggerTimeoutMs
                 * @memberof perfetto.protos.TraceConfig.TriggerConfig
                 * @instance
                 */
                TriggerConfig.prototype.triggerTimeoutMs = 0;

                /**
                 * Creates a new TriggerConfig instance using the specified properties.
                 * @function create
                 * @memberof perfetto.protos.TraceConfig.TriggerConfig
                 * @static
                 * @param {perfetto.protos.TraceConfig.ITriggerConfig=} [properties] Properties to set
                 * @returns {perfetto.protos.TraceConfig.TriggerConfig} TriggerConfig instance
                 */
                TriggerConfig.create = function create(properties) {
                    return new TriggerConfig(properties);
                };

                /**
                 * Encodes the specified TriggerConfig message. Does not implicitly {@link perfetto.protos.TraceConfig.TriggerConfig.verify|verify} messages.
                 * @function encode
                 * @memberof perfetto.protos.TraceConfig.TriggerConfig
                 * @static
                 * @param {perfetto.protos.TraceConfig.ITriggerConfig} message TriggerConfig message or plain object to encode
                 * @param {$protobuf.Writer} [writer] Writer to encode to
                 * @returns {$protobuf.Writer} Writer
                 */
                TriggerConfig.encode = function encode(message, writer) {
                    if (!writer)
                        writer = $Writer.create();
                    if (message.triggerMode != null && Object.hasOwnProperty.call(message, "triggerMode"))
                        writer.uint32(/* id 1, wireType 0 =*/8).int32(message.triggerMode);
                    if (message.triggers != null && message.triggers.length)
                        for (var i = 0; i < message.triggers.length; ++i)
                            $root.perfetto.protos.TraceConfig.TriggerConfig.Trigger.encode(message.triggers[i], writer.uint32(/* id 2, wireType 2 =*/18).fork()).ldelim();
                    if (message.triggerTimeoutMs != null && Object.hasOwnProperty.call(message, "triggerTimeoutMs"))
                        writer.uint32(/* id 3, wireType 0 =*/24).uint32(message.triggerTimeoutMs);
                    return writer;
                };

                /**
                 * Encodes the specified TriggerConfig message, length delimited. Does not implicitly {@link perfetto.protos.TraceConfig.TriggerConfig.verify|verify} messages.
                 * @function encodeDelimited
                 * @memberof perfetto.protos.TraceConfig.TriggerConfig
                 * @static
                 * @param {perfetto.protos.TraceConfig.ITriggerConfig} message TriggerConfig message or plain object to encode
                 * @param {$protobuf.Writer} [writer] Writer to encode to
                 * @returns {$protobuf.Writer} Writer
                 */
                TriggerConfig.encodeDelimited = function encodeDelimited(message, writer) {
                    return this.encode(message, writer).ldelim();
                };

                /**
                 * Decodes a TriggerConfig message from the specified reader or buffer.
                 * @function decode
                 * @memberof perfetto.protos.TraceConfig.TriggerConfig
                 * @static
                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                 * @param {number} [length] Message length if known beforehand
                 * @returns {perfetto.protos.TraceConfig.TriggerConfig} TriggerConfig
                 * @throws {Error} If the payload is not a reader or valid buffer
                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
                 */
                TriggerConfig.decode = function decode(reader, length) {
                    if (!(reader instanceof $Reader))
                        reader = $Reader.create(reader);
                    var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.TraceConfig.TriggerConfig();
                    while (reader.pos < end) {
                        var tag = reader.uint32();
                        switch (tag >>> 3) {
                        case 1:
                            message.triggerMode = reader.int32();
                            break;
                        case 2:
                            if (!(message.triggers && message.triggers.length))
                                message.triggers = [];
                            message.triggers.push($root.perfetto.protos.TraceConfig.TriggerConfig.Trigger.decode(reader, reader.uint32()));
                            break;
                        case 3:
                            message.triggerTimeoutMs = reader.uint32();
                            break;
                        default:
                            reader.skipType(tag & 7);
                            break;
                        }
                    }
                    return message;
                };

                /**
                 * Decodes a TriggerConfig message from the specified reader or buffer, length delimited.
                 * @function decodeDelimited
                 * @memberof perfetto.protos.TraceConfig.TriggerConfig
                 * @static
                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                 * @returns {perfetto.protos.TraceConfig.TriggerConfig} TriggerConfig
                 * @throws {Error} If the payload is not a reader or valid buffer
                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
                 */
                TriggerConfig.decodeDelimited = function decodeDelimited(reader) {
                    if (!(reader instanceof $Reader))
                        reader = new $Reader(reader);
                    return this.decode(reader, reader.uint32());
                };

                /**
                 * Verifies a TriggerConfig message.
                 * @function verify
                 * @memberof perfetto.protos.TraceConfig.TriggerConfig
                 * @static
                 * @param {Object.<string,*>} message Plain object to verify
                 * @returns {string|null} `null` if valid, otherwise the reason why it is not
                 */
                TriggerConfig.verify = function verify(message) {
                    if (typeof message !== "object" || message === null)
                        return "object expected";
                    if (message.triggerMode != null && message.hasOwnProperty("triggerMode"))
                        switch (message.triggerMode) {
                        default:
                            return "triggerMode: enum value expected";
                        case 0:
                        case 1:
                        case 2:
                            break;
                        }
                    if (message.triggers != null && message.hasOwnProperty("triggers")) {
                        if (!Array.isArray(message.triggers))
                            return "triggers: array expected";
                        for (var i = 0; i < message.triggers.length; ++i) {
                            var error = $root.perfetto.protos.TraceConfig.TriggerConfig.Trigger.verify(message.triggers[i]);
                            if (error)
                                return "triggers." + error;
                        }
                    }
                    if (message.triggerTimeoutMs != null && message.hasOwnProperty("triggerTimeoutMs"))
                        if (!$util.isInteger(message.triggerTimeoutMs))
                            return "triggerTimeoutMs: integer expected";
                    return null;
                };

                /**
                 * Creates a TriggerConfig message from a plain object. Also converts values to their respective internal types.
                 * @function fromObject
                 * @memberof perfetto.protos.TraceConfig.TriggerConfig
                 * @static
                 * @param {Object.<string,*>} object Plain object
                 * @returns {perfetto.protos.TraceConfig.TriggerConfig} TriggerConfig
                 */
                TriggerConfig.fromObject = function fromObject(object) {
                    if (object instanceof $root.perfetto.protos.TraceConfig.TriggerConfig)
                        return object;
                    var message = new $root.perfetto.protos.TraceConfig.TriggerConfig();
                    switch (object.triggerMode) {
                    case "UNSPECIFIED":
                    case 0:
                        message.triggerMode = 0;
                        break;
                    case "START_TRACING":
                    case 1:
                        message.triggerMode = 1;
                        break;
                    case "STOP_TRACING":
                    case 2:
                        message.triggerMode = 2;
                        break;
                    }
                    if (object.triggers) {
                        if (!Array.isArray(object.triggers))
                            throw TypeError(".perfetto.protos.TraceConfig.TriggerConfig.triggers: array expected");
                        message.triggers = [];
                        for (var i = 0; i < object.triggers.length; ++i) {
                            if (typeof object.triggers[i] !== "object")
                                throw TypeError(".perfetto.protos.TraceConfig.TriggerConfig.triggers: object expected");
                            message.triggers[i] = $root.perfetto.protos.TraceConfig.TriggerConfig.Trigger.fromObject(object.triggers[i]);
                        }
                    }
                    if (object.triggerTimeoutMs != null)
                        message.triggerTimeoutMs = object.triggerTimeoutMs >>> 0;
                    return message;
                };

                /**
                 * Creates a plain object from a TriggerConfig message. Also converts values to other types if specified.
                 * @function toObject
                 * @memberof perfetto.protos.TraceConfig.TriggerConfig
                 * @static
                 * @param {perfetto.protos.TraceConfig.TriggerConfig} message TriggerConfig
                 * @param {$protobuf.IConversionOptions} [options] Conversion options
                 * @returns {Object.<string,*>} Plain object
                 */
                TriggerConfig.toObject = function toObject(message, options) {
                    if (!options)
                        options = {};
                    var object = {};
                    if (options.arrays || options.defaults)
                        object.triggers = [];
                    if (options.defaults) {
                        object.triggerMode = options.enums === String ? "UNSPECIFIED" : 0;
                        object.triggerTimeoutMs = 0;
                    }
                    if (message.triggerMode != null && message.hasOwnProperty("triggerMode"))
                        object.triggerMode = options.enums === String ? $root.perfetto.protos.TraceConfig.TriggerConfig.TriggerMode[message.triggerMode] : message.triggerMode;
                    if (message.triggers && message.triggers.length) {
                        object.triggers = [];
                        for (var j = 0; j < message.triggers.length; ++j)
                            object.triggers[j] = $root.perfetto.protos.TraceConfig.TriggerConfig.Trigger.toObject(message.triggers[j], options);
                    }
                    if (message.triggerTimeoutMs != null && message.hasOwnProperty("triggerTimeoutMs"))
                        object.triggerTimeoutMs = message.triggerTimeoutMs;
                    return object;
                };

                /**
                 * Converts this TriggerConfig to JSON.
                 * @function toJSON
                 * @memberof perfetto.protos.TraceConfig.TriggerConfig
                 * @instance
                 * @returns {Object.<string,*>} JSON object
                 */
                TriggerConfig.prototype.toJSON = function toJSON() {
                    return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
                };

                /**
                 * TriggerMode enum.
                 * @name perfetto.protos.TraceConfig.TriggerConfig.TriggerMode
                 * @enum {number}
                 * @property {number} UNSPECIFIED=0 UNSPECIFIED value
                 * @property {number} START_TRACING=1 START_TRACING value
                 * @property {number} STOP_TRACING=2 STOP_TRACING value
                 */
                TriggerConfig.TriggerMode = (function() {
                    var valuesById = {}, values = Object.create(valuesById);
                    values[valuesById[0] = "UNSPECIFIED"] = 0;
                    values[valuesById[1] = "START_TRACING"] = 1;
                    values[valuesById[2] = "STOP_TRACING"] = 2;
                    return values;
                })();

                TriggerConfig.Trigger = (function() {

                    /**
                     * Properties of a Trigger.
                     * @memberof perfetto.protos.TraceConfig.TriggerConfig
                     * @interface ITrigger
                     * @property {string|null} [name] Trigger name
                     * @property {string|null} [producerNameRegex] Trigger producerNameRegex
                     * @property {number|null} [stopDelayMs] Trigger stopDelayMs
                     * @property {number|null} [maxPer_24H] Trigger maxPer_24H
                     * @property {number|null} [skipProbability] Trigger skipProbability
                     */

                    /**
                     * Constructs a new Trigger.
                     * @memberof perfetto.protos.TraceConfig.TriggerConfig
                     * @classdesc Represents a Trigger.
                     * @implements ITrigger
                     * @constructor
                     * @param {perfetto.protos.TraceConfig.TriggerConfig.ITrigger=} [properties] Properties to set
                     */
                    function Trigger(properties) {
                        if (properties)
                            for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                                if (properties[keys[i]] != null)
                                    this[keys[i]] = properties[keys[i]];
                    }

                    /**
                     * Trigger name.
                     * @member {string} name
                     * @memberof perfetto.protos.TraceConfig.TriggerConfig.Trigger
                     * @instance
                     */
                    Trigger.prototype.name = "";

                    /**
                     * Trigger producerNameRegex.
                     * @member {string} producerNameRegex
                     * @memberof perfetto.protos.TraceConfig.TriggerConfig.Trigger
                     * @instance
                     */
                    Trigger.prototype.producerNameRegex = "";

                    /**
                     * Trigger stopDelayMs.
                     * @member {number} stopDelayMs
                     * @memberof perfetto.protos.TraceConfig.TriggerConfig.Trigger
                     * @instance
                     */
                    Trigger.prototype.stopDelayMs = 0;

                    /**
                     * Trigger maxPer_24H.
                     * @member {number} maxPer_24H
                     * @memberof perfetto.protos.TraceConfig.TriggerConfig.Trigger
                     * @instance
                     */
                    Trigger.prototype.maxPer_24H = 0;

                    /**
                     * Trigger skipProbability.
                     * @member {number} skipProbability
                     * @memberof perfetto.protos.TraceConfig.TriggerConfig.Trigger
                     * @instance
                     */
                    Trigger.prototype.skipProbability = 0;

                    /**
                     * Creates a new Trigger instance using the specified properties.
                     * @function create
                     * @memberof perfetto.protos.TraceConfig.TriggerConfig.Trigger
                     * @static
                     * @param {perfetto.protos.TraceConfig.TriggerConfig.ITrigger=} [properties] Properties to set
                     * @returns {perfetto.protos.TraceConfig.TriggerConfig.Trigger} Trigger instance
                     */
                    Trigger.create = function create(properties) {
                        return new Trigger(properties);
                    };

                    /**
                     * Encodes the specified Trigger message. Does not implicitly {@link perfetto.protos.TraceConfig.TriggerConfig.Trigger.verify|verify} messages.
                     * @function encode
                     * @memberof perfetto.protos.TraceConfig.TriggerConfig.Trigger
                     * @static
                     * @param {perfetto.protos.TraceConfig.TriggerConfig.ITrigger} message Trigger message or plain object to encode
                     * @param {$protobuf.Writer} [writer] Writer to encode to
                     * @returns {$protobuf.Writer} Writer
                     */
                    Trigger.encode = function encode(message, writer) {
                        if (!writer)
                            writer = $Writer.create();
                        if (message.name != null && Object.hasOwnProperty.call(message, "name"))
                            writer.uint32(/* id 1, wireType 2 =*/10).string(message.name);
                        if (message.producerNameRegex != null && Object.hasOwnProperty.call(message, "producerNameRegex"))
                            writer.uint32(/* id 2, wireType 2 =*/18).string(message.producerNameRegex);
                        if (message.stopDelayMs != null && Object.hasOwnProperty.call(message, "stopDelayMs"))
                            writer.uint32(/* id 3, wireType 0 =*/24).uint32(message.stopDelayMs);
                        if (message.maxPer_24H != null && Object.hasOwnProperty.call(message, "maxPer_24H"))
                            writer.uint32(/* id 4, wireType 0 =*/32).uint32(message.maxPer_24H);
                        if (message.skipProbability != null && Object.hasOwnProperty.call(message, "skipProbability"))
                            writer.uint32(/* id 5, wireType 1 =*/41).double(message.skipProbability);
                        return writer;
                    };

                    /**
                     * Encodes the specified Trigger message, length delimited. Does not implicitly {@link perfetto.protos.TraceConfig.TriggerConfig.Trigger.verify|verify} messages.
                     * @function encodeDelimited
                     * @memberof perfetto.protos.TraceConfig.TriggerConfig.Trigger
                     * @static
                     * @param {perfetto.protos.TraceConfig.TriggerConfig.ITrigger} message Trigger message or plain object to encode
                     * @param {$protobuf.Writer} [writer] Writer to encode to
                     * @returns {$protobuf.Writer} Writer
                     */
                    Trigger.encodeDelimited = function encodeDelimited(message, writer) {
                        return this.encode(message, writer).ldelim();
                    };

                    /**
                     * Decodes a Trigger message from the specified reader or buffer.
                     * @function decode
                     * @memberof perfetto.protos.TraceConfig.TriggerConfig.Trigger
                     * @static
                     * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                     * @param {number} [length] Message length if known beforehand
                     * @returns {perfetto.protos.TraceConfig.TriggerConfig.Trigger} Trigger
                     * @throws {Error} If the payload is not a reader or valid buffer
                     * @throws {$protobuf.util.ProtocolError} If required fields are missing
                     */
                    Trigger.decode = function decode(reader, length) {
                        if (!(reader instanceof $Reader))
                            reader = $Reader.create(reader);
                        var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.TraceConfig.TriggerConfig.Trigger();
                        while (reader.pos < end) {
                            var tag = reader.uint32();
                            switch (tag >>> 3) {
                            case 1:
                                message.name = reader.string();
                                break;
                            case 2:
                                message.producerNameRegex = reader.string();
                                break;
                            case 3:
                                message.stopDelayMs = reader.uint32();
                                break;
                            case 4:
                                message.maxPer_24H = reader.uint32();
                                break;
                            case 5:
                                message.skipProbability = reader.double();
                                break;
                            default:
                                reader.skipType(tag & 7);
                                break;
                            }
                        }
                        return message;
                    };

                    /**
                     * Decodes a Trigger message from the specified reader or buffer, length delimited.
                     * @function decodeDelimited
                     * @memberof perfetto.protos.TraceConfig.TriggerConfig.Trigger
                     * @static
                     * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                     * @returns {perfetto.protos.TraceConfig.TriggerConfig.Trigger} Trigger
                     * @throws {Error} If the payload is not a reader or valid buffer
                     * @throws {$protobuf.util.ProtocolError} If required fields are missing
                     */
                    Trigger.decodeDelimited = function decodeDelimited(reader) {
                        if (!(reader instanceof $Reader))
                            reader = new $Reader(reader);
                        return this.decode(reader, reader.uint32());
                    };

                    /**
                     * Verifies a Trigger message.
                     * @function verify
                     * @memberof perfetto.protos.TraceConfig.TriggerConfig.Trigger
                     * @static
                     * @param {Object.<string,*>} message Plain object to verify
                     * @returns {string|null} `null` if valid, otherwise the reason why it is not
                     */
                    Trigger.verify = function verify(message) {
                        if (typeof message !== "object" || message === null)
                            return "object expected";
                        if (message.name != null && message.hasOwnProperty("name"))
                            if (!$util.isString(message.name))
                                return "name: string expected";
                        if (message.producerNameRegex != null && message.hasOwnProperty("producerNameRegex"))
                            if (!$util.isString(message.producerNameRegex))
                                return "producerNameRegex: string expected";
                        if (message.stopDelayMs != null && message.hasOwnProperty("stopDelayMs"))
                            if (!$util.isInteger(message.stopDelayMs))
                                return "stopDelayMs: integer expected";
                        if (message.maxPer_24H != null && message.hasOwnProperty("maxPer_24H"))
                            if (!$util.isInteger(message.maxPer_24H))
                                return "maxPer_24H: integer expected";
                        if (message.skipProbability != null && message.hasOwnProperty("skipProbability"))
                            if (typeof message.skipProbability !== "number")
                                return "skipProbability: number expected";
                        return null;
                    };

                    /**
                     * Creates a Trigger message from a plain object. Also converts values to their respective internal types.
                     * @function fromObject
                     * @memberof perfetto.protos.TraceConfig.TriggerConfig.Trigger
                     * @static
                     * @param {Object.<string,*>} object Plain object
                     * @returns {perfetto.protos.TraceConfig.TriggerConfig.Trigger} Trigger
                     */
                    Trigger.fromObject = function fromObject(object) {
                        if (object instanceof $root.perfetto.protos.TraceConfig.TriggerConfig.Trigger)
                            return object;
                        var message = new $root.perfetto.protos.TraceConfig.TriggerConfig.Trigger();
                        if (object.name != null)
                            message.name = String(object.name);
                        if (object.producerNameRegex != null)
                            message.producerNameRegex = String(object.producerNameRegex);
                        if (object.stopDelayMs != null)
                            message.stopDelayMs = object.stopDelayMs >>> 0;
                        if (object.maxPer_24H != null)
                            message.maxPer_24H = object.maxPer_24H >>> 0;
                        if (object.skipProbability != null)
                            message.skipProbability = Number(object.skipProbability);
                        return message;
                    };

                    /**
                     * Creates a plain object from a Trigger message. Also converts values to other types if specified.
                     * @function toObject
                     * @memberof perfetto.protos.TraceConfig.TriggerConfig.Trigger
                     * @static
                     * @param {perfetto.protos.TraceConfig.TriggerConfig.Trigger} message Trigger
                     * @param {$protobuf.IConversionOptions} [options] Conversion options
                     * @returns {Object.<string,*>} Plain object
                     */
                    Trigger.toObject = function toObject(message, options) {
                        if (!options)
                            options = {};
                        var object = {};
                        if (options.defaults) {
                            object.name = "";
                            object.producerNameRegex = "";
                            object.stopDelayMs = 0;
                            object.maxPer_24H = 0;
                            object.skipProbability = 0;
                        }
                        if (message.name != null && message.hasOwnProperty("name"))
                            object.name = message.name;
                        if (message.producerNameRegex != null && message.hasOwnProperty("producerNameRegex"))
                            object.producerNameRegex = message.producerNameRegex;
                        if (message.stopDelayMs != null && message.hasOwnProperty("stopDelayMs"))
                            object.stopDelayMs = message.stopDelayMs;
                        if (message.maxPer_24H != null && message.hasOwnProperty("maxPer_24H"))
                            object.maxPer_24H = message.maxPer_24H;
                        if (message.skipProbability != null && message.hasOwnProperty("skipProbability"))
                            object.skipProbability = options.json && !isFinite(message.skipProbability) ? String(message.skipProbability) : message.skipProbability;
                        return object;
                    };

                    /**
                     * Converts this Trigger to JSON.
                     * @function toJSON
                     * @memberof perfetto.protos.TraceConfig.TriggerConfig.Trigger
                     * @instance
                     * @returns {Object.<string,*>} JSON object
                     */
                    Trigger.prototype.toJSON = function toJSON() {
                        return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
                    };

                    return Trigger;
                })();

                return TriggerConfig;
            })();

            TraceConfig.IncrementalStateConfig = (function() {

                /**
                 * Properties of an IncrementalStateConfig.
                 * @memberof perfetto.protos.TraceConfig
                 * @interface IIncrementalStateConfig
                 * @property {number|null} [clearPeriodMs] IncrementalStateConfig clearPeriodMs
                 */

                /**
                 * Constructs a new IncrementalStateConfig.
                 * @memberof perfetto.protos.TraceConfig
                 * @classdesc Represents an IncrementalStateConfig.
                 * @implements IIncrementalStateConfig
                 * @constructor
                 * @param {perfetto.protos.TraceConfig.IIncrementalStateConfig=} [properties] Properties to set
                 */
                function IncrementalStateConfig(properties) {
                    if (properties)
                        for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                            if (properties[keys[i]] != null)
                                this[keys[i]] = properties[keys[i]];
                }

                /**
                 * IncrementalStateConfig clearPeriodMs.
                 * @member {number} clearPeriodMs
                 * @memberof perfetto.protos.TraceConfig.IncrementalStateConfig
                 * @instance
                 */
                IncrementalStateConfig.prototype.clearPeriodMs = 0;

                /**
                 * Creates a new IncrementalStateConfig instance using the specified properties.
                 * @function create
                 * @memberof perfetto.protos.TraceConfig.IncrementalStateConfig
                 * @static
                 * @param {perfetto.protos.TraceConfig.IIncrementalStateConfig=} [properties] Properties to set
                 * @returns {perfetto.protos.TraceConfig.IncrementalStateConfig} IncrementalStateConfig instance
                 */
                IncrementalStateConfig.create = function create(properties) {
                    return new IncrementalStateConfig(properties);
                };

                /**
                 * Encodes the specified IncrementalStateConfig message. Does not implicitly {@link perfetto.protos.TraceConfig.IncrementalStateConfig.verify|verify} messages.
                 * @function encode
                 * @memberof perfetto.protos.TraceConfig.IncrementalStateConfig
                 * @static
                 * @param {perfetto.protos.TraceConfig.IIncrementalStateConfig} message IncrementalStateConfig message or plain object to encode
                 * @param {$protobuf.Writer} [writer] Writer to encode to
                 * @returns {$protobuf.Writer} Writer
                 */
                IncrementalStateConfig.encode = function encode(message, writer) {
                    if (!writer)
                        writer = $Writer.create();
                    if (message.clearPeriodMs != null && Object.hasOwnProperty.call(message, "clearPeriodMs"))
                        writer.uint32(/* id 1, wireType 0 =*/8).uint32(message.clearPeriodMs);
                    return writer;
                };

                /**
                 * Encodes the specified IncrementalStateConfig message, length delimited. Does not implicitly {@link perfetto.protos.TraceConfig.IncrementalStateConfig.verify|verify} messages.
                 * @function encodeDelimited
                 * @memberof perfetto.protos.TraceConfig.IncrementalStateConfig
                 * @static
                 * @param {perfetto.protos.TraceConfig.IIncrementalStateConfig} message IncrementalStateConfig message or plain object to encode
                 * @param {$protobuf.Writer} [writer] Writer to encode to
                 * @returns {$protobuf.Writer} Writer
                 */
                IncrementalStateConfig.encodeDelimited = function encodeDelimited(message, writer) {
                    return this.encode(message, writer).ldelim();
                };

                /**
                 * Decodes an IncrementalStateConfig message from the specified reader or buffer.
                 * @function decode
                 * @memberof perfetto.protos.TraceConfig.IncrementalStateConfig
                 * @static
                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                 * @param {number} [length] Message length if known beforehand
                 * @returns {perfetto.protos.TraceConfig.IncrementalStateConfig} IncrementalStateConfig
                 * @throws {Error} If the payload is not a reader or valid buffer
                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
                 */
                IncrementalStateConfig.decode = function decode(reader, length) {
                    if (!(reader instanceof $Reader))
                        reader = $Reader.create(reader);
                    var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.TraceConfig.IncrementalStateConfig();
                    while (reader.pos < end) {
                        var tag = reader.uint32();
                        switch (tag >>> 3) {
                        case 1:
                            message.clearPeriodMs = reader.uint32();
                            break;
                        default:
                            reader.skipType(tag & 7);
                            break;
                        }
                    }
                    return message;
                };

                /**
                 * Decodes an IncrementalStateConfig message from the specified reader or buffer, length delimited.
                 * @function decodeDelimited
                 * @memberof perfetto.protos.TraceConfig.IncrementalStateConfig
                 * @static
                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                 * @returns {perfetto.protos.TraceConfig.IncrementalStateConfig} IncrementalStateConfig
                 * @throws {Error} If the payload is not a reader or valid buffer
                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
                 */
                IncrementalStateConfig.decodeDelimited = function decodeDelimited(reader) {
                    if (!(reader instanceof $Reader))
                        reader = new $Reader(reader);
                    return this.decode(reader, reader.uint32());
                };

                /**
                 * Verifies an IncrementalStateConfig message.
                 * @function verify
                 * @memberof perfetto.protos.TraceConfig.IncrementalStateConfig
                 * @static
                 * @param {Object.<string,*>} message Plain object to verify
                 * @returns {string|null} `null` if valid, otherwise the reason why it is not
                 */
                IncrementalStateConfig.verify = function verify(message) {
                    if (typeof message !== "object" || message === null)
                        return "object expected";
                    if (message.clearPeriodMs != null && message.hasOwnProperty("clearPeriodMs"))
                        if (!$util.isInteger(message.clearPeriodMs))
                            return "clearPeriodMs: integer expected";
                    return null;
                };

                /**
                 * Creates an IncrementalStateConfig message from a plain object. Also converts values to their respective internal types.
                 * @function fromObject
                 * @memberof perfetto.protos.TraceConfig.IncrementalStateConfig
                 * @static
                 * @param {Object.<string,*>} object Plain object
                 * @returns {perfetto.protos.TraceConfig.IncrementalStateConfig} IncrementalStateConfig
                 */
                IncrementalStateConfig.fromObject = function fromObject(object) {
                    if (object instanceof $root.perfetto.protos.TraceConfig.IncrementalStateConfig)
                        return object;
                    var message = new $root.perfetto.protos.TraceConfig.IncrementalStateConfig();
                    if (object.clearPeriodMs != null)
                        message.clearPeriodMs = object.clearPeriodMs >>> 0;
                    return message;
                };

                /**
                 * Creates a plain object from an IncrementalStateConfig message. Also converts values to other types if specified.
                 * @function toObject
                 * @memberof perfetto.protos.TraceConfig.IncrementalStateConfig
                 * @static
                 * @param {perfetto.protos.TraceConfig.IncrementalStateConfig} message IncrementalStateConfig
                 * @param {$protobuf.IConversionOptions} [options] Conversion options
                 * @returns {Object.<string,*>} Plain object
                 */
                IncrementalStateConfig.toObject = function toObject(message, options) {
                    if (!options)
                        options = {};
                    var object = {};
                    if (options.defaults)
                        object.clearPeriodMs = 0;
                    if (message.clearPeriodMs != null && message.hasOwnProperty("clearPeriodMs"))
                        object.clearPeriodMs = message.clearPeriodMs;
                    return object;
                };

                /**
                 * Converts this IncrementalStateConfig to JSON.
                 * @function toJSON
                 * @memberof perfetto.protos.TraceConfig.IncrementalStateConfig
                 * @instance
                 * @returns {Object.<string,*>} JSON object
                 */
                IncrementalStateConfig.prototype.toJSON = function toJSON() {
                    return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
                };

                return IncrementalStateConfig;
            })();

            /**
             * CompressionType enum.
             * @name perfetto.protos.TraceConfig.CompressionType
             * @enum {number}
             * @property {number} COMPRESSION_TYPE_UNSPECIFIED=0 COMPRESSION_TYPE_UNSPECIFIED value
             * @property {number} COMPRESSION_TYPE_DEFLATE=1 COMPRESSION_TYPE_DEFLATE value
             */
            TraceConfig.CompressionType = (function() {
                var valuesById = {}, values = Object.create(valuesById);
                values[valuesById[0] = "COMPRESSION_TYPE_UNSPECIFIED"] = 0;
                values[valuesById[1] = "COMPRESSION_TYPE_DEFLATE"] = 1;
                return values;
            })();

            TraceConfig.IncidentReportConfig = (function() {

                /**
                 * Properties of an IncidentReportConfig.
                 * @memberof perfetto.protos.TraceConfig
                 * @interface IIncidentReportConfig
                 * @property {string|null} [destinationPackage] IncidentReportConfig destinationPackage
                 * @property {string|null} [destinationClass] IncidentReportConfig destinationClass
                 * @property {number|null} [privacyLevel] IncidentReportConfig privacyLevel
                 * @property {boolean|null} [skipIncidentd] IncidentReportConfig skipIncidentd
                 * @property {boolean|null} [skipDropbox] IncidentReportConfig skipDropbox
                 */

                /**
                 * Constructs a new IncidentReportConfig.
                 * @memberof perfetto.protos.TraceConfig
                 * @classdesc Represents an IncidentReportConfig.
                 * @implements IIncidentReportConfig
                 * @constructor
                 * @param {perfetto.protos.TraceConfig.IIncidentReportConfig=} [properties] Properties to set
                 */
                function IncidentReportConfig(properties) {
                    if (properties)
                        for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                            if (properties[keys[i]] != null)
                                this[keys[i]] = properties[keys[i]];
                }

                /**
                 * IncidentReportConfig destinationPackage.
                 * @member {string} destinationPackage
                 * @memberof perfetto.protos.TraceConfig.IncidentReportConfig
                 * @instance
                 */
                IncidentReportConfig.prototype.destinationPackage = "";

                /**
                 * IncidentReportConfig destinationClass.
                 * @member {string} destinationClass
                 * @memberof perfetto.protos.TraceConfig.IncidentReportConfig
                 * @instance
                 */
                IncidentReportConfig.prototype.destinationClass = "";

                /**
                 * IncidentReportConfig privacyLevel.
                 * @member {number} privacyLevel
                 * @memberof perfetto.protos.TraceConfig.IncidentReportConfig
                 * @instance
                 */
                IncidentReportConfig.prototype.privacyLevel = 0;

                /**
                 * IncidentReportConfig skipIncidentd.
                 * @member {boolean} skipIncidentd
                 * @memberof perfetto.protos.TraceConfig.IncidentReportConfig
                 * @instance
                 */
                IncidentReportConfig.prototype.skipIncidentd = false;

                /**
                 * IncidentReportConfig skipDropbox.
                 * @member {boolean} skipDropbox
                 * @memberof perfetto.protos.TraceConfig.IncidentReportConfig
                 * @instance
                 */
                IncidentReportConfig.prototype.skipDropbox = false;

                /**
                 * Creates a new IncidentReportConfig instance using the specified properties.
                 * @function create
                 * @memberof perfetto.protos.TraceConfig.IncidentReportConfig
                 * @static
                 * @param {perfetto.protos.TraceConfig.IIncidentReportConfig=} [properties] Properties to set
                 * @returns {perfetto.protos.TraceConfig.IncidentReportConfig} IncidentReportConfig instance
                 */
                IncidentReportConfig.create = function create(properties) {
                    return new IncidentReportConfig(properties);
                };

                /**
                 * Encodes the specified IncidentReportConfig message. Does not implicitly {@link perfetto.protos.TraceConfig.IncidentReportConfig.verify|verify} messages.
                 * @function encode
                 * @memberof perfetto.protos.TraceConfig.IncidentReportConfig
                 * @static
                 * @param {perfetto.protos.TraceConfig.IIncidentReportConfig} message IncidentReportConfig message or plain object to encode
                 * @param {$protobuf.Writer} [writer] Writer to encode to
                 * @returns {$protobuf.Writer} Writer
                 */
                IncidentReportConfig.encode = function encode(message, writer) {
                    if (!writer)
                        writer = $Writer.create();
                    if (message.destinationPackage != null && Object.hasOwnProperty.call(message, "destinationPackage"))
                        writer.uint32(/* id 1, wireType 2 =*/10).string(message.destinationPackage);
                    if (message.destinationClass != null && Object.hasOwnProperty.call(message, "destinationClass"))
                        writer.uint32(/* id 2, wireType 2 =*/18).string(message.destinationClass);
                    if (message.privacyLevel != null && Object.hasOwnProperty.call(message, "privacyLevel"))
                        writer.uint32(/* id 3, wireType 0 =*/24).int32(message.privacyLevel);
                    if (message.skipDropbox != null && Object.hasOwnProperty.call(message, "skipDropbox"))
                        writer.uint32(/* id 4, wireType 0 =*/32).bool(message.skipDropbox);
                    if (message.skipIncidentd != null && Object.hasOwnProperty.call(message, "skipIncidentd"))
                        writer.uint32(/* id 5, wireType 0 =*/40).bool(message.skipIncidentd);
                    return writer;
                };

                /**
                 * Encodes the specified IncidentReportConfig message, length delimited. Does not implicitly {@link perfetto.protos.TraceConfig.IncidentReportConfig.verify|verify} messages.
                 * @function encodeDelimited
                 * @memberof perfetto.protos.TraceConfig.IncidentReportConfig
                 * @static
                 * @param {perfetto.protos.TraceConfig.IIncidentReportConfig} message IncidentReportConfig message or plain object to encode
                 * @param {$protobuf.Writer} [writer] Writer to encode to
                 * @returns {$protobuf.Writer} Writer
                 */
                IncidentReportConfig.encodeDelimited = function encodeDelimited(message, writer) {
                    return this.encode(message, writer).ldelim();
                };

                /**
                 * Decodes an IncidentReportConfig message from the specified reader or buffer.
                 * @function decode
                 * @memberof perfetto.protos.TraceConfig.IncidentReportConfig
                 * @static
                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                 * @param {number} [length] Message length if known beforehand
                 * @returns {perfetto.protos.TraceConfig.IncidentReportConfig} IncidentReportConfig
                 * @throws {Error} If the payload is not a reader or valid buffer
                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
                 */
                IncidentReportConfig.decode = function decode(reader, length) {
                    if (!(reader instanceof $Reader))
                        reader = $Reader.create(reader);
                    var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.TraceConfig.IncidentReportConfig();
                    while (reader.pos < end) {
                        var tag = reader.uint32();
                        switch (tag >>> 3) {
                        case 1:
                            message.destinationPackage = reader.string();
                            break;
                        case 2:
                            message.destinationClass = reader.string();
                            break;
                        case 3:
                            message.privacyLevel = reader.int32();
                            break;
                        case 5:
                            message.skipIncidentd = reader.bool();
                            break;
                        case 4:
                            message.skipDropbox = reader.bool();
                            break;
                        default:
                            reader.skipType(tag & 7);
                            break;
                        }
                    }
                    return message;
                };

                /**
                 * Decodes an IncidentReportConfig message from the specified reader or buffer, length delimited.
                 * @function decodeDelimited
                 * @memberof perfetto.protos.TraceConfig.IncidentReportConfig
                 * @static
                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                 * @returns {perfetto.protos.TraceConfig.IncidentReportConfig} IncidentReportConfig
                 * @throws {Error} If the payload is not a reader or valid buffer
                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
                 */
                IncidentReportConfig.decodeDelimited = function decodeDelimited(reader) {
                    if (!(reader instanceof $Reader))
                        reader = new $Reader(reader);
                    return this.decode(reader, reader.uint32());
                };

                /**
                 * Verifies an IncidentReportConfig message.
                 * @function verify
                 * @memberof perfetto.protos.TraceConfig.IncidentReportConfig
                 * @static
                 * @param {Object.<string,*>} message Plain object to verify
                 * @returns {string|null} `null` if valid, otherwise the reason why it is not
                 */
                IncidentReportConfig.verify = function verify(message) {
                    if (typeof message !== "object" || message === null)
                        return "object expected";
                    if (message.destinationPackage != null && message.hasOwnProperty("destinationPackage"))
                        if (!$util.isString(message.destinationPackage))
                            return "destinationPackage: string expected";
                    if (message.destinationClass != null && message.hasOwnProperty("destinationClass"))
                        if (!$util.isString(message.destinationClass))
                            return "destinationClass: string expected";
                    if (message.privacyLevel != null && message.hasOwnProperty("privacyLevel"))
                        if (!$util.isInteger(message.privacyLevel))
                            return "privacyLevel: integer expected";
                    if (message.skipIncidentd != null && message.hasOwnProperty("skipIncidentd"))
                        if (typeof message.skipIncidentd !== "boolean")
                            return "skipIncidentd: boolean expected";
                    if (message.skipDropbox != null && message.hasOwnProperty("skipDropbox"))
                        if (typeof message.skipDropbox !== "boolean")
                            return "skipDropbox: boolean expected";
                    return null;
                };

                /**
                 * Creates an IncidentReportConfig message from a plain object. Also converts values to their respective internal types.
                 * @function fromObject
                 * @memberof perfetto.protos.TraceConfig.IncidentReportConfig
                 * @static
                 * @param {Object.<string,*>} object Plain object
                 * @returns {perfetto.protos.TraceConfig.IncidentReportConfig} IncidentReportConfig
                 */
                IncidentReportConfig.fromObject = function fromObject(object) {
                    if (object instanceof $root.perfetto.protos.TraceConfig.IncidentReportConfig)
                        return object;
                    var message = new $root.perfetto.protos.TraceConfig.IncidentReportConfig();
                    if (object.destinationPackage != null)
                        message.destinationPackage = String(object.destinationPackage);
                    if (object.destinationClass != null)
                        message.destinationClass = String(object.destinationClass);
                    if (object.privacyLevel != null)
                        message.privacyLevel = object.privacyLevel | 0;
                    if (object.skipIncidentd != null)
                        message.skipIncidentd = Boolean(object.skipIncidentd);
                    if (object.skipDropbox != null)
                        message.skipDropbox = Boolean(object.skipDropbox);
                    return message;
                };

                /**
                 * Creates a plain object from an IncidentReportConfig message. Also converts values to other types if specified.
                 * @function toObject
                 * @memberof perfetto.protos.TraceConfig.IncidentReportConfig
                 * @static
                 * @param {perfetto.protos.TraceConfig.IncidentReportConfig} message IncidentReportConfig
                 * @param {$protobuf.IConversionOptions} [options] Conversion options
                 * @returns {Object.<string,*>} Plain object
                 */
                IncidentReportConfig.toObject = function toObject(message, options) {
                    if (!options)
                        options = {};
                    var object = {};
                    if (options.defaults) {
                        object.destinationPackage = "";
                        object.destinationClass = "";
                        object.privacyLevel = 0;
                        object.skipDropbox = false;
                        object.skipIncidentd = false;
                    }
                    if (message.destinationPackage != null && message.hasOwnProperty("destinationPackage"))
                        object.destinationPackage = message.destinationPackage;
                    if (message.destinationClass != null && message.hasOwnProperty("destinationClass"))
                        object.destinationClass = message.destinationClass;
                    if (message.privacyLevel != null && message.hasOwnProperty("privacyLevel"))
                        object.privacyLevel = message.privacyLevel;
                    if (message.skipDropbox != null && message.hasOwnProperty("skipDropbox"))
                        object.skipDropbox = message.skipDropbox;
                    if (message.skipIncidentd != null && message.hasOwnProperty("skipIncidentd"))
                        object.skipIncidentd = message.skipIncidentd;
                    return object;
                };

                /**
                 * Converts this IncidentReportConfig to JSON.
                 * @function toJSON
                 * @memberof perfetto.protos.TraceConfig.IncidentReportConfig
                 * @instance
                 * @returns {Object.<string,*>} JSON object
                 */
                IncidentReportConfig.prototype.toJSON = function toJSON() {
                    return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
                };

                return IncidentReportConfig;
            })();

            /**
             * StatsdLogging enum.
             * @name perfetto.protos.TraceConfig.StatsdLogging
             * @enum {number}
             * @property {number} STATSD_LOGGING_UNSPECIFIED=0 STATSD_LOGGING_UNSPECIFIED value
             * @property {number} STATSD_LOGGING_ENABLED=1 STATSD_LOGGING_ENABLED value
             * @property {number} STATSD_LOGGING_DISABLED=2 STATSD_LOGGING_DISABLED value
             */
            TraceConfig.StatsdLogging = (function() {
                var valuesById = {}, values = Object.create(valuesById);
                values[valuesById[0] = "STATSD_LOGGING_UNSPECIFIED"] = 0;
                values[valuesById[1] = "STATSD_LOGGING_ENABLED"] = 1;
                values[valuesById[2] = "STATSD_LOGGING_DISABLED"] = 2;
                return values;
            })();

            TraceConfig.TraceFilter = (function() {

                /**
                 * Properties of a TraceFilter.
                 * @memberof perfetto.protos.TraceConfig
                 * @interface ITraceFilter
                 * @property {Uint8Array|null} [bytecode] TraceFilter bytecode
                 */

                /**
                 * Constructs a new TraceFilter.
                 * @memberof perfetto.protos.TraceConfig
                 * @classdesc Represents a TraceFilter.
                 * @implements ITraceFilter
                 * @constructor
                 * @param {perfetto.protos.TraceConfig.ITraceFilter=} [properties] Properties to set
                 */
                function TraceFilter(properties) {
                    if (properties)
                        for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                            if (properties[keys[i]] != null)
                                this[keys[i]] = properties[keys[i]];
                }

                /**
                 * TraceFilter bytecode.
                 * @member {Uint8Array} bytecode
                 * @memberof perfetto.protos.TraceConfig.TraceFilter
                 * @instance
                 */
                TraceFilter.prototype.bytecode = $util.newBuffer([]);

                /**
                 * Creates a new TraceFilter instance using the specified properties.
                 * @function create
                 * @memberof perfetto.protos.TraceConfig.TraceFilter
                 * @static
                 * @param {perfetto.protos.TraceConfig.ITraceFilter=} [properties] Properties to set
                 * @returns {perfetto.protos.TraceConfig.TraceFilter} TraceFilter instance
                 */
                TraceFilter.create = function create(properties) {
                    return new TraceFilter(properties);
                };

                /**
                 * Encodes the specified TraceFilter message. Does not implicitly {@link perfetto.protos.TraceConfig.TraceFilter.verify|verify} messages.
                 * @function encode
                 * @memberof perfetto.protos.TraceConfig.TraceFilter
                 * @static
                 * @param {perfetto.protos.TraceConfig.ITraceFilter} message TraceFilter message or plain object to encode
                 * @param {$protobuf.Writer} [writer] Writer to encode to
                 * @returns {$protobuf.Writer} Writer
                 */
                TraceFilter.encode = function encode(message, writer) {
                    if (!writer)
                        writer = $Writer.create();
                    if (message.bytecode != null && Object.hasOwnProperty.call(message, "bytecode"))
                        writer.uint32(/* id 1, wireType 2 =*/10).bytes(message.bytecode);
                    return writer;
                };

                /**
                 * Encodes the specified TraceFilter message, length delimited. Does not implicitly {@link perfetto.protos.TraceConfig.TraceFilter.verify|verify} messages.
                 * @function encodeDelimited
                 * @memberof perfetto.protos.TraceConfig.TraceFilter
                 * @static
                 * @param {perfetto.protos.TraceConfig.ITraceFilter} message TraceFilter message or plain object to encode
                 * @param {$protobuf.Writer} [writer] Writer to encode to
                 * @returns {$protobuf.Writer} Writer
                 */
                TraceFilter.encodeDelimited = function encodeDelimited(message, writer) {
                    return this.encode(message, writer).ldelim();
                };

                /**
                 * Decodes a TraceFilter message from the specified reader or buffer.
                 * @function decode
                 * @memberof perfetto.protos.TraceConfig.TraceFilter
                 * @static
                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                 * @param {number} [length] Message length if known beforehand
                 * @returns {perfetto.protos.TraceConfig.TraceFilter} TraceFilter
                 * @throws {Error} If the payload is not a reader or valid buffer
                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
                 */
                TraceFilter.decode = function decode(reader, length) {
                    if (!(reader instanceof $Reader))
                        reader = $Reader.create(reader);
                    var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.TraceConfig.TraceFilter();
                    while (reader.pos < end) {
                        var tag = reader.uint32();
                        switch (tag >>> 3) {
                        case 1:
                            message.bytecode = reader.bytes();
                            break;
                        default:
                            reader.skipType(tag & 7);
                            break;
                        }
                    }
                    return message;
                };

                /**
                 * Decodes a TraceFilter message from the specified reader or buffer, length delimited.
                 * @function decodeDelimited
                 * @memberof perfetto.protos.TraceConfig.TraceFilter
                 * @static
                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                 * @returns {perfetto.protos.TraceConfig.TraceFilter} TraceFilter
                 * @throws {Error} If the payload is not a reader or valid buffer
                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
                 */
                TraceFilter.decodeDelimited = function decodeDelimited(reader) {
                    if (!(reader instanceof $Reader))
                        reader = new $Reader(reader);
                    return this.decode(reader, reader.uint32());
                };

                /**
                 * Verifies a TraceFilter message.
                 * @function verify
                 * @memberof perfetto.protos.TraceConfig.TraceFilter
                 * @static
                 * @param {Object.<string,*>} message Plain object to verify
                 * @returns {string|null} `null` if valid, otherwise the reason why it is not
                 */
                TraceFilter.verify = function verify(message) {
                    if (typeof message !== "object" || message === null)
                        return "object expected";
                    if (message.bytecode != null && message.hasOwnProperty("bytecode"))
                        if (!(message.bytecode && typeof message.bytecode.length === "number" || $util.isString(message.bytecode)))
                            return "bytecode: buffer expected";
                    return null;
                };

                /**
                 * Creates a TraceFilter message from a plain object. Also converts values to their respective internal types.
                 * @function fromObject
                 * @memberof perfetto.protos.TraceConfig.TraceFilter
                 * @static
                 * @param {Object.<string,*>} object Plain object
                 * @returns {perfetto.protos.TraceConfig.TraceFilter} TraceFilter
                 */
                TraceFilter.fromObject = function fromObject(object) {
                    if (object instanceof $root.perfetto.protos.TraceConfig.TraceFilter)
                        return object;
                    var message = new $root.perfetto.protos.TraceConfig.TraceFilter();
                    if (object.bytecode != null)
                        if (typeof object.bytecode === "string")
                            $util.base64.decode(object.bytecode, message.bytecode = $util.newBuffer($util.base64.length(object.bytecode)), 0);
                        else if (object.bytecode.length)
                            message.bytecode = object.bytecode;
                    return message;
                };

                /**
                 * Creates a plain object from a TraceFilter message. Also converts values to other types if specified.
                 * @function toObject
                 * @memberof perfetto.protos.TraceConfig.TraceFilter
                 * @static
                 * @param {perfetto.protos.TraceConfig.TraceFilter} message TraceFilter
                 * @param {$protobuf.IConversionOptions} [options] Conversion options
                 * @returns {Object.<string,*>} Plain object
                 */
                TraceFilter.toObject = function toObject(message, options) {
                    if (!options)
                        options = {};
                    var object = {};
                    if (options.defaults)
                        if (options.bytes === String)
                            object.bytecode = "";
                        else {
                            object.bytecode = [];
                            if (options.bytes !== Array)
                                object.bytecode = $util.newBuffer(object.bytecode);
                        }
                    if (message.bytecode != null && message.hasOwnProperty("bytecode"))
                        object.bytecode = options.bytes === String ? $util.base64.encode(message.bytecode, 0, message.bytecode.length) : options.bytes === Array ? Array.prototype.slice.call(message.bytecode) : message.bytecode;
                    return object;
                };

                /**
                 * Converts this TraceFilter to JSON.
                 * @function toJSON
                 * @memberof perfetto.protos.TraceConfig.TraceFilter
                 * @instance
                 * @returns {Object.<string,*>} JSON object
                 */
                TraceFilter.prototype.toJSON = function toJSON() {
                    return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
                };

                return TraceFilter;
            })();

            return TraceConfig;
        })();

        protos.ConsumerPort = (function() {

            /**
             * Constructs a new ConsumerPort service.
             * @memberof perfetto.protos
             * @classdesc Represents a ConsumerPort
             * @extends $protobuf.rpc.Service
             * @constructor
             * @param {$protobuf.RPCImpl} rpcImpl RPC implementation
             * @param {boolean} [requestDelimited=false] Whether requests are length-delimited
             * @param {boolean} [responseDelimited=false] Whether responses are length-delimited
             */
            function ConsumerPort(rpcImpl, requestDelimited, responseDelimited) {
                minimal$1.rpc.Service.call(this, rpcImpl, requestDelimited, responseDelimited);
            }

            (ConsumerPort.prototype = Object.create(minimal$1.rpc.Service.prototype)).constructor = ConsumerPort;

            /**
             * Creates new ConsumerPort service using the specified rpc implementation.
             * @function create
             * @memberof perfetto.protos.ConsumerPort
             * @static
             * @param {$protobuf.RPCImpl} rpcImpl RPC implementation
             * @param {boolean} [requestDelimited=false] Whether requests are length-delimited
             * @param {boolean} [responseDelimited=false] Whether responses are length-delimited
             * @returns {ConsumerPort} RPC service. Useful where requests and/or responses are streamed.
             */
            ConsumerPort.create = function create(rpcImpl, requestDelimited, responseDelimited) {
                return new this(rpcImpl, requestDelimited, responseDelimited);
            };

            /**
             * Callback as used by {@link perfetto.protos.ConsumerPort#enableTracing}.
             * @memberof perfetto.protos.ConsumerPort
             * @typedef EnableTracingCallback
             * @type {function}
             * @param {Error|null} error Error, if any
             * @param {perfetto.protos.EnableTracingResponse} [response] EnableTracingResponse
             */

            /**
             * Calls EnableTracing.
             * @function enableTracing
             * @memberof perfetto.protos.ConsumerPort
             * @instance
             * @param {perfetto.protos.IEnableTracingRequest} request EnableTracingRequest message or plain object
             * @param {perfetto.protos.ConsumerPort.EnableTracingCallback} callback Node-style callback called with the error, if any, and EnableTracingResponse
             * @returns {undefined}
             * @variation 1
             */
            Object.defineProperty(ConsumerPort.prototype.enableTracing = function enableTracing(request, callback) {
                return this.rpcCall(enableTracing, $root.perfetto.protos.EnableTracingRequest, $root.perfetto.protos.EnableTracingResponse, request, callback);
            }, "name", { value: "EnableTracing" });

            /**
             * Calls EnableTracing.
             * @function enableTracing
             * @memberof perfetto.protos.ConsumerPort
             * @instance
             * @param {perfetto.protos.IEnableTracingRequest} request EnableTracingRequest message or plain object
             * @returns {Promise<perfetto.protos.EnableTracingResponse>} Promise
             * @variation 2
             */

            /**
             * Callback as used by {@link perfetto.protos.ConsumerPort#disableTracing}.
             * @memberof perfetto.protos.ConsumerPort
             * @typedef DisableTracingCallback
             * @type {function}
             * @param {Error|null} error Error, if any
             * @param {perfetto.protos.DisableTracingResponse} [response] DisableTracingResponse
             */

            /**
             * Calls DisableTracing.
             * @function disableTracing
             * @memberof perfetto.protos.ConsumerPort
             * @instance
             * @param {perfetto.protos.IDisableTracingRequest} request DisableTracingRequest message or plain object
             * @param {perfetto.protos.ConsumerPort.DisableTracingCallback} callback Node-style callback called with the error, if any, and DisableTracingResponse
             * @returns {undefined}
             * @variation 1
             */
            Object.defineProperty(ConsumerPort.prototype.disableTracing = function disableTracing(request, callback) {
                return this.rpcCall(disableTracing, $root.perfetto.protos.DisableTracingRequest, $root.perfetto.protos.DisableTracingResponse, request, callback);
            }, "name", { value: "DisableTracing" });

            /**
             * Calls DisableTracing.
             * @function disableTracing
             * @memberof perfetto.protos.ConsumerPort
             * @instance
             * @param {perfetto.protos.IDisableTracingRequest} request DisableTracingRequest message or plain object
             * @returns {Promise<perfetto.protos.DisableTracingResponse>} Promise
             * @variation 2
             */

            /**
             * Callback as used by {@link perfetto.protos.ConsumerPort#readBuffers}.
             * @memberof perfetto.protos.ConsumerPort
             * @typedef ReadBuffersCallback
             * @type {function}
             * @param {Error|null} error Error, if any
             * @param {perfetto.protos.ReadBuffersResponse} [response] ReadBuffersResponse
             */

            /**
             * Calls ReadBuffers.
             * @function readBuffers
             * @memberof perfetto.protos.ConsumerPort
             * @instance
             * @param {perfetto.protos.IReadBuffersRequest} request ReadBuffersRequest message or plain object
             * @param {perfetto.protos.ConsumerPort.ReadBuffersCallback} callback Node-style callback called with the error, if any, and ReadBuffersResponse
             * @returns {undefined}
             * @variation 1
             */
            Object.defineProperty(ConsumerPort.prototype.readBuffers = function readBuffers(request, callback) {
                return this.rpcCall(readBuffers, $root.perfetto.protos.ReadBuffersRequest, $root.perfetto.protos.ReadBuffersResponse, request, callback);
            }, "name", { value: "ReadBuffers" });

            /**
             * Calls ReadBuffers.
             * @function readBuffers
             * @memberof perfetto.protos.ConsumerPort
             * @instance
             * @param {perfetto.protos.IReadBuffersRequest} request ReadBuffersRequest message or plain object
             * @returns {Promise<perfetto.protos.ReadBuffersResponse>} Promise
             * @variation 2
             */

            /**
             * Callback as used by {@link perfetto.protos.ConsumerPort#freeBuffers}.
             * @memberof perfetto.protos.ConsumerPort
             * @typedef FreeBuffersCallback
             * @type {function}
             * @param {Error|null} error Error, if any
             * @param {perfetto.protos.FreeBuffersResponse} [response] FreeBuffersResponse
             */

            /**
             * Calls FreeBuffers.
             * @function freeBuffers
             * @memberof perfetto.protos.ConsumerPort
             * @instance
             * @param {perfetto.protos.IFreeBuffersRequest} request FreeBuffersRequest message or plain object
             * @param {perfetto.protos.ConsumerPort.FreeBuffersCallback} callback Node-style callback called with the error, if any, and FreeBuffersResponse
             * @returns {undefined}
             * @variation 1
             */
            Object.defineProperty(ConsumerPort.prototype.freeBuffers = function freeBuffers(request, callback) {
                return this.rpcCall(freeBuffers, $root.perfetto.protos.FreeBuffersRequest, $root.perfetto.protos.FreeBuffersResponse, request, callback);
            }, "name", { value: "FreeBuffers" });

            /**
             * Calls FreeBuffers.
             * @function freeBuffers
             * @memberof perfetto.protos.ConsumerPort
             * @instance
             * @param {perfetto.protos.IFreeBuffersRequest} request FreeBuffersRequest message or plain object
             * @returns {Promise<perfetto.protos.FreeBuffersResponse>} Promise
             * @variation 2
             */

            /**
             * Callback as used by {@link perfetto.protos.ConsumerPort#flush}.
             * @memberof perfetto.protos.ConsumerPort
             * @typedef FlushCallback
             * @type {function}
             * @param {Error|null} error Error, if any
             * @param {perfetto.protos.FlushResponse} [response] FlushResponse
             */

            /**
             * Calls Flush.
             * @function flush
             * @memberof perfetto.protos.ConsumerPort
             * @instance
             * @param {perfetto.protos.IFlushRequest} request FlushRequest message or plain object
             * @param {perfetto.protos.ConsumerPort.FlushCallback} callback Node-style callback called with the error, if any, and FlushResponse
             * @returns {undefined}
             * @variation 1
             */
            Object.defineProperty(ConsumerPort.prototype.flush = function flush(request, callback) {
                return this.rpcCall(flush, $root.perfetto.protos.FlushRequest, $root.perfetto.protos.FlushResponse, request, callback);
            }, "name", { value: "Flush" });

            /**
             * Calls Flush.
             * @function flush
             * @memberof perfetto.protos.ConsumerPort
             * @instance
             * @param {perfetto.protos.IFlushRequest} request FlushRequest message or plain object
             * @returns {Promise<perfetto.protos.FlushResponse>} Promise
             * @variation 2
             */

            /**
             * Callback as used by {@link perfetto.protos.ConsumerPort#startTracing}.
             * @memberof perfetto.protos.ConsumerPort
             * @typedef StartTracingCallback
             * @type {function}
             * @param {Error|null} error Error, if any
             * @param {perfetto.protos.StartTracingResponse} [response] StartTracingResponse
             */

            /**
             * Calls StartTracing.
             * @function startTracing
             * @memberof perfetto.protos.ConsumerPort
             * @instance
             * @param {perfetto.protos.IStartTracingRequest} request StartTracingRequest message or plain object
             * @param {perfetto.protos.ConsumerPort.StartTracingCallback} callback Node-style callback called with the error, if any, and StartTracingResponse
             * @returns {undefined}
             * @variation 1
             */
            Object.defineProperty(ConsumerPort.prototype.startTracing = function startTracing(request, callback) {
                return this.rpcCall(startTracing, $root.perfetto.protos.StartTracingRequest, $root.perfetto.protos.StartTracingResponse, request, callback);
            }, "name", { value: "StartTracing" });

            /**
             * Calls StartTracing.
             * @function startTracing
             * @memberof perfetto.protos.ConsumerPort
             * @instance
             * @param {perfetto.protos.IStartTracingRequest} request StartTracingRequest message or plain object
             * @returns {Promise<perfetto.protos.StartTracingResponse>} Promise
             * @variation 2
             */

            /**
             * Callback as used by {@link perfetto.protos.ConsumerPort#changeTraceConfig}.
             * @memberof perfetto.protos.ConsumerPort
             * @typedef ChangeTraceConfigCallback
             * @type {function}
             * @param {Error|null} error Error, if any
             * @param {perfetto.protos.ChangeTraceConfigResponse} [response] ChangeTraceConfigResponse
             */

            /**
             * Calls ChangeTraceConfig.
             * @function changeTraceConfig
             * @memberof perfetto.protos.ConsumerPort
             * @instance
             * @param {perfetto.protos.IChangeTraceConfigRequest} request ChangeTraceConfigRequest message or plain object
             * @param {perfetto.protos.ConsumerPort.ChangeTraceConfigCallback} callback Node-style callback called with the error, if any, and ChangeTraceConfigResponse
             * @returns {undefined}
             * @variation 1
             */
            Object.defineProperty(ConsumerPort.prototype.changeTraceConfig = function changeTraceConfig(request, callback) {
                return this.rpcCall(changeTraceConfig, $root.perfetto.protos.ChangeTraceConfigRequest, $root.perfetto.protos.ChangeTraceConfigResponse, request, callback);
            }, "name", { value: "ChangeTraceConfig" });

            /**
             * Calls ChangeTraceConfig.
             * @function changeTraceConfig
             * @memberof perfetto.protos.ConsumerPort
             * @instance
             * @param {perfetto.protos.IChangeTraceConfigRequest} request ChangeTraceConfigRequest message or plain object
             * @returns {Promise<perfetto.protos.ChangeTraceConfigResponse>} Promise
             * @variation 2
             */

            /**
             * Callback as used by {@link perfetto.protos.ConsumerPort#detach}.
             * @memberof perfetto.protos.ConsumerPort
             * @typedef DetachCallback
             * @type {function}
             * @param {Error|null} error Error, if any
             * @param {perfetto.protos.DetachResponse} [response] DetachResponse
             */

            /**
             * Calls Detach.
             * @function detach
             * @memberof perfetto.protos.ConsumerPort
             * @instance
             * @param {perfetto.protos.IDetachRequest} request DetachRequest message or plain object
             * @param {perfetto.protos.ConsumerPort.DetachCallback} callback Node-style callback called with the error, if any, and DetachResponse
             * @returns {undefined}
             * @variation 1
             */
            Object.defineProperty(ConsumerPort.prototype.detach = function detach(request, callback) {
                return this.rpcCall(detach, $root.perfetto.protos.DetachRequest, $root.perfetto.protos.DetachResponse, request, callback);
            }, "name", { value: "Detach" });

            /**
             * Calls Detach.
             * @function detach
             * @memberof perfetto.protos.ConsumerPort
             * @instance
             * @param {perfetto.protos.IDetachRequest} request DetachRequest message or plain object
             * @returns {Promise<perfetto.protos.DetachResponse>} Promise
             * @variation 2
             */

            /**
             * Callback as used by {@link perfetto.protos.ConsumerPort#attach}.
             * @memberof perfetto.protos.ConsumerPort
             * @typedef AttachCallback
             * @type {function}
             * @param {Error|null} error Error, if any
             * @param {perfetto.protos.AttachResponse} [response] AttachResponse
             */

            /**
             * Calls Attach.
             * @function attach
             * @memberof perfetto.protos.ConsumerPort
             * @instance
             * @param {perfetto.protos.IAttachRequest} request AttachRequest message or plain object
             * @param {perfetto.protos.ConsumerPort.AttachCallback} callback Node-style callback called with the error, if any, and AttachResponse
             * @returns {undefined}
             * @variation 1
             */
            Object.defineProperty(ConsumerPort.prototype.attach = function attach(request, callback) {
                return this.rpcCall(attach, $root.perfetto.protos.AttachRequest, $root.perfetto.protos.AttachResponse, request, callback);
            }, "name", { value: "Attach" });

            /**
             * Calls Attach.
             * @function attach
             * @memberof perfetto.protos.ConsumerPort
             * @instance
             * @param {perfetto.protos.IAttachRequest} request AttachRequest message or plain object
             * @returns {Promise<perfetto.protos.AttachResponse>} Promise
             * @variation 2
             */

            /**
             * Callback as used by {@link perfetto.protos.ConsumerPort#getTraceStats}.
             * @memberof perfetto.protos.ConsumerPort
             * @typedef GetTraceStatsCallback
             * @type {function}
             * @param {Error|null} error Error, if any
             * @param {perfetto.protos.GetTraceStatsResponse} [response] GetTraceStatsResponse
             */

            /**
             * Calls GetTraceStats.
             * @function getTraceStats
             * @memberof perfetto.protos.ConsumerPort
             * @instance
             * @param {perfetto.protos.IGetTraceStatsRequest} request GetTraceStatsRequest message or plain object
             * @param {perfetto.protos.ConsumerPort.GetTraceStatsCallback} callback Node-style callback called with the error, if any, and GetTraceStatsResponse
             * @returns {undefined}
             * @variation 1
             */
            Object.defineProperty(ConsumerPort.prototype.getTraceStats = function getTraceStats(request, callback) {
                return this.rpcCall(getTraceStats, $root.perfetto.protos.GetTraceStatsRequest, $root.perfetto.protos.GetTraceStatsResponse, request, callback);
            }, "name", { value: "GetTraceStats" });

            /**
             * Calls GetTraceStats.
             * @function getTraceStats
             * @memberof perfetto.protos.ConsumerPort
             * @instance
             * @param {perfetto.protos.IGetTraceStatsRequest} request GetTraceStatsRequest message or plain object
             * @returns {Promise<perfetto.protos.GetTraceStatsResponse>} Promise
             * @variation 2
             */

            /**
             * Callback as used by {@link perfetto.protos.ConsumerPort#observeEvents}.
             * @memberof perfetto.protos.ConsumerPort
             * @typedef ObserveEventsCallback
             * @type {function}
             * @param {Error|null} error Error, if any
             * @param {perfetto.protos.ObserveEventsResponse} [response] ObserveEventsResponse
             */

            /**
             * Calls ObserveEvents.
             * @function observeEvents
             * @memberof perfetto.protos.ConsumerPort
             * @instance
             * @param {perfetto.protos.IObserveEventsRequest} request ObserveEventsRequest message or plain object
             * @param {perfetto.protos.ConsumerPort.ObserveEventsCallback} callback Node-style callback called with the error, if any, and ObserveEventsResponse
             * @returns {undefined}
             * @variation 1
             */
            Object.defineProperty(ConsumerPort.prototype.observeEvents = function observeEvents(request, callback) {
                return this.rpcCall(observeEvents, $root.perfetto.protos.ObserveEventsRequest, $root.perfetto.protos.ObserveEventsResponse, request, callback);
            }, "name", { value: "ObserveEvents" });

            /**
             * Calls ObserveEvents.
             * @function observeEvents
             * @memberof perfetto.protos.ConsumerPort
             * @instance
             * @param {perfetto.protos.IObserveEventsRequest} request ObserveEventsRequest message or plain object
             * @returns {Promise<perfetto.protos.ObserveEventsResponse>} Promise
             * @variation 2
             */

            /**
             * Callback as used by {@link perfetto.protos.ConsumerPort#queryServiceState}.
             * @memberof perfetto.protos.ConsumerPort
             * @typedef QueryServiceStateCallback
             * @type {function}
             * @param {Error|null} error Error, if any
             * @param {perfetto.protos.QueryServiceStateResponse} [response] QueryServiceStateResponse
             */

            /**
             * Calls QueryServiceState.
             * @function queryServiceState
             * @memberof perfetto.protos.ConsumerPort
             * @instance
             * @param {perfetto.protos.IQueryServiceStateRequest} request QueryServiceStateRequest message or plain object
             * @param {perfetto.protos.ConsumerPort.QueryServiceStateCallback} callback Node-style callback called with the error, if any, and QueryServiceStateResponse
             * @returns {undefined}
             * @variation 1
             */
            Object.defineProperty(ConsumerPort.prototype.queryServiceState = function queryServiceState(request, callback) {
                return this.rpcCall(queryServiceState, $root.perfetto.protos.QueryServiceStateRequest, $root.perfetto.protos.QueryServiceStateResponse, request, callback);
            }, "name", { value: "QueryServiceState" });

            /**
             * Calls QueryServiceState.
             * @function queryServiceState
             * @memberof perfetto.protos.ConsumerPort
             * @instance
             * @param {perfetto.protos.IQueryServiceStateRequest} request QueryServiceStateRequest message or plain object
             * @returns {Promise<perfetto.protos.QueryServiceStateResponse>} Promise
             * @variation 2
             */

            /**
             * Callback as used by {@link perfetto.protos.ConsumerPort#queryCapabilities}.
             * @memberof perfetto.protos.ConsumerPort
             * @typedef QueryCapabilitiesCallback
             * @type {function}
             * @param {Error|null} error Error, if any
             * @param {perfetto.protos.QueryCapabilitiesResponse} [response] QueryCapabilitiesResponse
             */

            /**
             * Calls QueryCapabilities.
             * @function queryCapabilities
             * @memberof perfetto.protos.ConsumerPort
             * @instance
             * @param {perfetto.protos.IQueryCapabilitiesRequest} request QueryCapabilitiesRequest message or plain object
             * @param {perfetto.protos.ConsumerPort.QueryCapabilitiesCallback} callback Node-style callback called with the error, if any, and QueryCapabilitiesResponse
             * @returns {undefined}
             * @variation 1
             */
            Object.defineProperty(ConsumerPort.prototype.queryCapabilities = function queryCapabilities(request, callback) {
                return this.rpcCall(queryCapabilities, $root.perfetto.protos.QueryCapabilitiesRequest, $root.perfetto.protos.QueryCapabilitiesResponse, request, callback);
            }, "name", { value: "QueryCapabilities" });

            /**
             * Calls QueryCapabilities.
             * @function queryCapabilities
             * @memberof perfetto.protos.ConsumerPort
             * @instance
             * @param {perfetto.protos.IQueryCapabilitiesRequest} request QueryCapabilitiesRequest message or plain object
             * @returns {Promise<perfetto.protos.QueryCapabilitiesResponse>} Promise
             * @variation 2
             */

            /**
             * Callback as used by {@link perfetto.protos.ConsumerPort#saveTraceForBugreport}.
             * @memberof perfetto.protos.ConsumerPort
             * @typedef SaveTraceForBugreportCallback
             * @type {function}
             * @param {Error|null} error Error, if any
             * @param {perfetto.protos.SaveTraceForBugreportResponse} [response] SaveTraceForBugreportResponse
             */

            /**
             * Calls SaveTraceForBugreport.
             * @function saveTraceForBugreport
             * @memberof perfetto.protos.ConsumerPort
             * @instance
             * @param {perfetto.protos.ISaveTraceForBugreportRequest} request SaveTraceForBugreportRequest message or plain object
             * @param {perfetto.protos.ConsumerPort.SaveTraceForBugreportCallback} callback Node-style callback called with the error, if any, and SaveTraceForBugreportResponse
             * @returns {undefined}
             * @variation 1
             */
            Object.defineProperty(ConsumerPort.prototype.saveTraceForBugreport = function saveTraceForBugreport(request, callback) {
                return this.rpcCall(saveTraceForBugreport, $root.perfetto.protos.SaveTraceForBugreportRequest, $root.perfetto.protos.SaveTraceForBugreportResponse, request, callback);
            }, "name", { value: "SaveTraceForBugreport" });

            /**
             * Calls SaveTraceForBugreport.
             * @function saveTraceForBugreport
             * @memberof perfetto.protos.ConsumerPort
             * @instance
             * @param {perfetto.protos.ISaveTraceForBugreportRequest} request SaveTraceForBugreportRequest message or plain object
             * @returns {Promise<perfetto.protos.SaveTraceForBugreportResponse>} Promise
             * @variation 2
             */

            return ConsumerPort;
        })();

        protos.EnableTracingRequest = (function() {

            /**
             * Properties of an EnableTracingRequest.
             * @memberof perfetto.protos
             * @interface IEnableTracingRequest
             * @property {perfetto.protos.ITraceConfig|null} [traceConfig] EnableTracingRequest traceConfig
             * @property {boolean|null} [attachNotificationOnly] EnableTracingRequest attachNotificationOnly
             */

            /**
             * Constructs a new EnableTracingRequest.
             * @memberof perfetto.protos
             * @classdesc Represents an EnableTracingRequest.
             * @implements IEnableTracingRequest
             * @constructor
             * @param {perfetto.protos.IEnableTracingRequest=} [properties] Properties to set
             */
            function EnableTracingRequest(properties) {
                if (properties)
                    for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                        if (properties[keys[i]] != null)
                            this[keys[i]] = properties[keys[i]];
            }

            /**
             * EnableTracingRequest traceConfig.
             * @member {perfetto.protos.ITraceConfig|null|undefined} traceConfig
             * @memberof perfetto.protos.EnableTracingRequest
             * @instance
             */
            EnableTracingRequest.prototype.traceConfig = null;

            /**
             * EnableTracingRequest attachNotificationOnly.
             * @member {boolean} attachNotificationOnly
             * @memberof perfetto.protos.EnableTracingRequest
             * @instance
             */
            EnableTracingRequest.prototype.attachNotificationOnly = false;

            /**
             * Creates a new EnableTracingRequest instance using the specified properties.
             * @function create
             * @memberof perfetto.protos.EnableTracingRequest
             * @static
             * @param {perfetto.protos.IEnableTracingRequest=} [properties] Properties to set
             * @returns {perfetto.protos.EnableTracingRequest} EnableTracingRequest instance
             */
            EnableTracingRequest.create = function create(properties) {
                return new EnableTracingRequest(properties);
            };

            /**
             * Encodes the specified EnableTracingRequest message. Does not implicitly {@link perfetto.protos.EnableTracingRequest.verify|verify} messages.
             * @function encode
             * @memberof perfetto.protos.EnableTracingRequest
             * @static
             * @param {perfetto.protos.IEnableTracingRequest} message EnableTracingRequest message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            EnableTracingRequest.encode = function encode(message, writer) {
                if (!writer)
                    writer = $Writer.create();
                if (message.traceConfig != null && Object.hasOwnProperty.call(message, "traceConfig"))
                    $root.perfetto.protos.TraceConfig.encode(message.traceConfig, writer.uint32(/* id 1, wireType 2 =*/10).fork()).ldelim();
                if (message.attachNotificationOnly != null && Object.hasOwnProperty.call(message, "attachNotificationOnly"))
                    writer.uint32(/* id 2, wireType 0 =*/16).bool(message.attachNotificationOnly);
                return writer;
            };

            /**
             * Encodes the specified EnableTracingRequest message, length delimited. Does not implicitly {@link perfetto.protos.EnableTracingRequest.verify|verify} messages.
             * @function encodeDelimited
             * @memberof perfetto.protos.EnableTracingRequest
             * @static
             * @param {perfetto.protos.IEnableTracingRequest} message EnableTracingRequest message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            EnableTracingRequest.encodeDelimited = function encodeDelimited(message, writer) {
                return this.encode(message, writer).ldelim();
            };

            /**
             * Decodes an EnableTracingRequest message from the specified reader or buffer.
             * @function decode
             * @memberof perfetto.protos.EnableTracingRequest
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @param {number} [length] Message length if known beforehand
             * @returns {perfetto.protos.EnableTracingRequest} EnableTracingRequest
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            EnableTracingRequest.decode = function decode(reader, length) {
                if (!(reader instanceof $Reader))
                    reader = $Reader.create(reader);
                var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.EnableTracingRequest();
                while (reader.pos < end) {
                    var tag = reader.uint32();
                    switch (tag >>> 3) {
                    case 1:
                        message.traceConfig = $root.perfetto.protos.TraceConfig.decode(reader, reader.uint32());
                        break;
                    case 2:
                        message.attachNotificationOnly = reader.bool();
                        break;
                    default:
                        reader.skipType(tag & 7);
                        break;
                    }
                }
                return message;
            };

            /**
             * Decodes an EnableTracingRequest message from the specified reader or buffer, length delimited.
             * @function decodeDelimited
             * @memberof perfetto.protos.EnableTracingRequest
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @returns {perfetto.protos.EnableTracingRequest} EnableTracingRequest
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            EnableTracingRequest.decodeDelimited = function decodeDelimited(reader) {
                if (!(reader instanceof $Reader))
                    reader = new $Reader(reader);
                return this.decode(reader, reader.uint32());
            };

            /**
             * Verifies an EnableTracingRequest message.
             * @function verify
             * @memberof perfetto.protos.EnableTracingRequest
             * @static
             * @param {Object.<string,*>} message Plain object to verify
             * @returns {string|null} `null` if valid, otherwise the reason why it is not
             */
            EnableTracingRequest.verify = function verify(message) {
                if (typeof message !== "object" || message === null)
                    return "object expected";
                if (message.traceConfig != null && message.hasOwnProperty("traceConfig")) {
                    var error = $root.perfetto.protos.TraceConfig.verify(message.traceConfig);
                    if (error)
                        return "traceConfig." + error;
                }
                if (message.attachNotificationOnly != null && message.hasOwnProperty("attachNotificationOnly"))
                    if (typeof message.attachNotificationOnly !== "boolean")
                        return "attachNotificationOnly: boolean expected";
                return null;
            };

            /**
             * Creates an EnableTracingRequest message from a plain object. Also converts values to their respective internal types.
             * @function fromObject
             * @memberof perfetto.protos.EnableTracingRequest
             * @static
             * @param {Object.<string,*>} object Plain object
             * @returns {perfetto.protos.EnableTracingRequest} EnableTracingRequest
             */
            EnableTracingRequest.fromObject = function fromObject(object) {
                if (object instanceof $root.perfetto.protos.EnableTracingRequest)
                    return object;
                var message = new $root.perfetto.protos.EnableTracingRequest();
                if (object.traceConfig != null) {
                    if (typeof object.traceConfig !== "object")
                        throw TypeError(".perfetto.protos.EnableTracingRequest.traceConfig: object expected");
                    message.traceConfig = $root.perfetto.protos.TraceConfig.fromObject(object.traceConfig);
                }
                if (object.attachNotificationOnly != null)
                    message.attachNotificationOnly = Boolean(object.attachNotificationOnly);
                return message;
            };

            /**
             * Creates a plain object from an EnableTracingRequest message. Also converts values to other types if specified.
             * @function toObject
             * @memberof perfetto.protos.EnableTracingRequest
             * @static
             * @param {perfetto.protos.EnableTracingRequest} message EnableTracingRequest
             * @param {$protobuf.IConversionOptions} [options] Conversion options
             * @returns {Object.<string,*>} Plain object
             */
            EnableTracingRequest.toObject = function toObject(message, options) {
                if (!options)
                    options = {};
                var object = {};
                if (options.defaults) {
                    object.traceConfig = null;
                    object.attachNotificationOnly = false;
                }
                if (message.traceConfig != null && message.hasOwnProperty("traceConfig"))
                    object.traceConfig = $root.perfetto.protos.TraceConfig.toObject(message.traceConfig, options);
                if (message.attachNotificationOnly != null && message.hasOwnProperty("attachNotificationOnly"))
                    object.attachNotificationOnly = message.attachNotificationOnly;
                return object;
            };

            /**
             * Converts this EnableTracingRequest to JSON.
             * @function toJSON
             * @memberof perfetto.protos.EnableTracingRequest
             * @instance
             * @returns {Object.<string,*>} JSON object
             */
            EnableTracingRequest.prototype.toJSON = function toJSON() {
                return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
            };

            return EnableTracingRequest;
        })();

        protos.EnableTracingResponse = (function() {

            /**
             * Properties of an EnableTracingResponse.
             * @memberof perfetto.protos
             * @interface IEnableTracingResponse
             * @property {boolean|null} [disabled] EnableTracingResponse disabled
             * @property {string|null} [error] EnableTracingResponse error
             */

            /**
             * Constructs a new EnableTracingResponse.
             * @memberof perfetto.protos
             * @classdesc Represents an EnableTracingResponse.
             * @implements IEnableTracingResponse
             * @constructor
             * @param {perfetto.protos.IEnableTracingResponse=} [properties] Properties to set
             */
            function EnableTracingResponse(properties) {
                if (properties)
                    for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                        if (properties[keys[i]] != null)
                            this[keys[i]] = properties[keys[i]];
            }

            /**
             * EnableTracingResponse disabled.
             * @member {boolean} disabled
             * @memberof perfetto.protos.EnableTracingResponse
             * @instance
             */
            EnableTracingResponse.prototype.disabled = false;

            /**
             * EnableTracingResponse error.
             * @member {string} error
             * @memberof perfetto.protos.EnableTracingResponse
             * @instance
             */
            EnableTracingResponse.prototype.error = "";

            // OneOf field names bound to virtual getters and setters
            var $oneOfFields;

            /**
             * EnableTracingResponse state.
             * @member {"disabled"|undefined} state
             * @memberof perfetto.protos.EnableTracingResponse
             * @instance
             */
            Object.defineProperty(EnableTracingResponse.prototype, "state", {
                get: $util.oneOfGetter($oneOfFields = ["disabled"]),
                set: $util.oneOfSetter($oneOfFields)
            });

            /**
             * Creates a new EnableTracingResponse instance using the specified properties.
             * @function create
             * @memberof perfetto.protos.EnableTracingResponse
             * @static
             * @param {perfetto.protos.IEnableTracingResponse=} [properties] Properties to set
             * @returns {perfetto.protos.EnableTracingResponse} EnableTracingResponse instance
             */
            EnableTracingResponse.create = function create(properties) {
                return new EnableTracingResponse(properties);
            };

            /**
             * Encodes the specified EnableTracingResponse message. Does not implicitly {@link perfetto.protos.EnableTracingResponse.verify|verify} messages.
             * @function encode
             * @memberof perfetto.protos.EnableTracingResponse
             * @static
             * @param {perfetto.protos.IEnableTracingResponse} message EnableTracingResponse message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            EnableTracingResponse.encode = function encode(message, writer) {
                if (!writer)
                    writer = $Writer.create();
                if (message.disabled != null && Object.hasOwnProperty.call(message, "disabled"))
                    writer.uint32(/* id 1, wireType 0 =*/8).bool(message.disabled);
                if (message.error != null && Object.hasOwnProperty.call(message, "error"))
                    writer.uint32(/* id 3, wireType 2 =*/26).string(message.error);
                return writer;
            };

            /**
             * Encodes the specified EnableTracingResponse message, length delimited. Does not implicitly {@link perfetto.protos.EnableTracingResponse.verify|verify} messages.
             * @function encodeDelimited
             * @memberof perfetto.protos.EnableTracingResponse
             * @static
             * @param {perfetto.protos.IEnableTracingResponse} message EnableTracingResponse message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            EnableTracingResponse.encodeDelimited = function encodeDelimited(message, writer) {
                return this.encode(message, writer).ldelim();
            };

            /**
             * Decodes an EnableTracingResponse message from the specified reader or buffer.
             * @function decode
             * @memberof perfetto.protos.EnableTracingResponse
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @param {number} [length] Message length if known beforehand
             * @returns {perfetto.protos.EnableTracingResponse} EnableTracingResponse
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            EnableTracingResponse.decode = function decode(reader, length) {
                if (!(reader instanceof $Reader))
                    reader = $Reader.create(reader);
                var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.EnableTracingResponse();
                while (reader.pos < end) {
                    var tag = reader.uint32();
                    switch (tag >>> 3) {
                    case 1:
                        message.disabled = reader.bool();
                        break;
                    case 3:
                        message.error = reader.string();
                        break;
                    default:
                        reader.skipType(tag & 7);
                        break;
                    }
                }
                return message;
            };

            /**
             * Decodes an EnableTracingResponse message from the specified reader or buffer, length delimited.
             * @function decodeDelimited
             * @memberof perfetto.protos.EnableTracingResponse
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @returns {perfetto.protos.EnableTracingResponse} EnableTracingResponse
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            EnableTracingResponse.decodeDelimited = function decodeDelimited(reader) {
                if (!(reader instanceof $Reader))
                    reader = new $Reader(reader);
                return this.decode(reader, reader.uint32());
            };

            /**
             * Verifies an EnableTracingResponse message.
             * @function verify
             * @memberof perfetto.protos.EnableTracingResponse
             * @static
             * @param {Object.<string,*>} message Plain object to verify
             * @returns {string|null} `null` if valid, otherwise the reason why it is not
             */
            EnableTracingResponse.verify = function verify(message) {
                if (typeof message !== "object" || message === null)
                    return "object expected";
                if (message.disabled != null && message.hasOwnProperty("disabled")) {
                    if (typeof message.disabled !== "boolean")
                        return "disabled: boolean expected";
                }
                if (message.error != null && message.hasOwnProperty("error"))
                    if (!$util.isString(message.error))
                        return "error: string expected";
                return null;
            };

            /**
             * Creates an EnableTracingResponse message from a plain object. Also converts values to their respective internal types.
             * @function fromObject
             * @memberof perfetto.protos.EnableTracingResponse
             * @static
             * @param {Object.<string,*>} object Plain object
             * @returns {perfetto.protos.EnableTracingResponse} EnableTracingResponse
             */
            EnableTracingResponse.fromObject = function fromObject(object) {
                if (object instanceof $root.perfetto.protos.EnableTracingResponse)
                    return object;
                var message = new $root.perfetto.protos.EnableTracingResponse();
                if (object.disabled != null)
                    message.disabled = Boolean(object.disabled);
                if (object.error != null)
                    message.error = String(object.error);
                return message;
            };

            /**
             * Creates a plain object from an EnableTracingResponse message. Also converts values to other types if specified.
             * @function toObject
             * @memberof perfetto.protos.EnableTracingResponse
             * @static
             * @param {perfetto.protos.EnableTracingResponse} message EnableTracingResponse
             * @param {$protobuf.IConversionOptions} [options] Conversion options
             * @returns {Object.<string,*>} Plain object
             */
            EnableTracingResponse.toObject = function toObject(message, options) {
                if (!options)
                    options = {};
                var object = {};
                if (options.defaults)
                    object.error = "";
                if (message.disabled != null && message.hasOwnProperty("disabled")) {
                    object.disabled = message.disabled;
                    if (options.oneofs)
                        object.state = "disabled";
                }
                if (message.error != null && message.hasOwnProperty("error"))
                    object.error = message.error;
                return object;
            };

            /**
             * Converts this EnableTracingResponse to JSON.
             * @function toJSON
             * @memberof perfetto.protos.EnableTracingResponse
             * @instance
             * @returns {Object.<string,*>} JSON object
             */
            EnableTracingResponse.prototype.toJSON = function toJSON() {
                return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
            };

            return EnableTracingResponse;
        })();

        protos.StartTracingRequest = (function() {

            /**
             * Properties of a StartTracingRequest.
             * @memberof perfetto.protos
             * @interface IStartTracingRequest
             */

            /**
             * Constructs a new StartTracingRequest.
             * @memberof perfetto.protos
             * @classdesc Represents a StartTracingRequest.
             * @implements IStartTracingRequest
             * @constructor
             * @param {perfetto.protos.IStartTracingRequest=} [properties] Properties to set
             */
            function StartTracingRequest(properties) {
                if (properties)
                    for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                        if (properties[keys[i]] != null)
                            this[keys[i]] = properties[keys[i]];
            }

            /**
             * Creates a new StartTracingRequest instance using the specified properties.
             * @function create
             * @memberof perfetto.protos.StartTracingRequest
             * @static
             * @param {perfetto.protos.IStartTracingRequest=} [properties] Properties to set
             * @returns {perfetto.protos.StartTracingRequest} StartTracingRequest instance
             */
            StartTracingRequest.create = function create(properties) {
                return new StartTracingRequest(properties);
            };

            /**
             * Encodes the specified StartTracingRequest message. Does not implicitly {@link perfetto.protos.StartTracingRequest.verify|verify} messages.
             * @function encode
             * @memberof perfetto.protos.StartTracingRequest
             * @static
             * @param {perfetto.protos.IStartTracingRequest} message StartTracingRequest message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            StartTracingRequest.encode = function encode(message, writer) {
                if (!writer)
                    writer = $Writer.create();
                return writer;
            };

            /**
             * Encodes the specified StartTracingRequest message, length delimited. Does not implicitly {@link perfetto.protos.StartTracingRequest.verify|verify} messages.
             * @function encodeDelimited
             * @memberof perfetto.protos.StartTracingRequest
             * @static
             * @param {perfetto.protos.IStartTracingRequest} message StartTracingRequest message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            StartTracingRequest.encodeDelimited = function encodeDelimited(message, writer) {
                return this.encode(message, writer).ldelim();
            };

            /**
             * Decodes a StartTracingRequest message from the specified reader or buffer.
             * @function decode
             * @memberof perfetto.protos.StartTracingRequest
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @param {number} [length] Message length if known beforehand
             * @returns {perfetto.protos.StartTracingRequest} StartTracingRequest
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            StartTracingRequest.decode = function decode(reader, length) {
                if (!(reader instanceof $Reader))
                    reader = $Reader.create(reader);
                var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.StartTracingRequest();
                while (reader.pos < end) {
                    var tag = reader.uint32();
                    switch (tag >>> 3) {
                    default:
                        reader.skipType(tag & 7);
                        break;
                    }
                }
                return message;
            };

            /**
             * Decodes a StartTracingRequest message from the specified reader or buffer, length delimited.
             * @function decodeDelimited
             * @memberof perfetto.protos.StartTracingRequest
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @returns {perfetto.protos.StartTracingRequest} StartTracingRequest
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            StartTracingRequest.decodeDelimited = function decodeDelimited(reader) {
                if (!(reader instanceof $Reader))
                    reader = new $Reader(reader);
                return this.decode(reader, reader.uint32());
            };

            /**
             * Verifies a StartTracingRequest message.
             * @function verify
             * @memberof perfetto.protos.StartTracingRequest
             * @static
             * @param {Object.<string,*>} message Plain object to verify
             * @returns {string|null} `null` if valid, otherwise the reason why it is not
             */
            StartTracingRequest.verify = function verify(message) {
                if (typeof message !== "object" || message === null)
                    return "object expected";
                return null;
            };

            /**
             * Creates a StartTracingRequest message from a plain object. Also converts values to their respective internal types.
             * @function fromObject
             * @memberof perfetto.protos.StartTracingRequest
             * @static
             * @param {Object.<string,*>} object Plain object
             * @returns {perfetto.protos.StartTracingRequest} StartTracingRequest
             */
            StartTracingRequest.fromObject = function fromObject(object) {
                if (object instanceof $root.perfetto.protos.StartTracingRequest)
                    return object;
                return new $root.perfetto.protos.StartTracingRequest();
            };

            /**
             * Creates a plain object from a StartTracingRequest message. Also converts values to other types if specified.
             * @function toObject
             * @memberof perfetto.protos.StartTracingRequest
             * @static
             * @param {perfetto.protos.StartTracingRequest} message StartTracingRequest
             * @param {$protobuf.IConversionOptions} [options] Conversion options
             * @returns {Object.<string,*>} Plain object
             */
            StartTracingRequest.toObject = function toObject() {
                return {};
            };

            /**
             * Converts this StartTracingRequest to JSON.
             * @function toJSON
             * @memberof perfetto.protos.StartTracingRequest
             * @instance
             * @returns {Object.<string,*>} JSON object
             */
            StartTracingRequest.prototype.toJSON = function toJSON() {
                return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
            };

            return StartTracingRequest;
        })();

        protos.StartTracingResponse = (function() {

            /**
             * Properties of a StartTracingResponse.
             * @memberof perfetto.protos
             * @interface IStartTracingResponse
             */

            /**
             * Constructs a new StartTracingResponse.
             * @memberof perfetto.protos
             * @classdesc Represents a StartTracingResponse.
             * @implements IStartTracingResponse
             * @constructor
             * @param {perfetto.protos.IStartTracingResponse=} [properties] Properties to set
             */
            function StartTracingResponse(properties) {
                if (properties)
                    for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                        if (properties[keys[i]] != null)
                            this[keys[i]] = properties[keys[i]];
            }

            /**
             * Creates a new StartTracingResponse instance using the specified properties.
             * @function create
             * @memberof perfetto.protos.StartTracingResponse
             * @static
             * @param {perfetto.protos.IStartTracingResponse=} [properties] Properties to set
             * @returns {perfetto.protos.StartTracingResponse} StartTracingResponse instance
             */
            StartTracingResponse.create = function create(properties) {
                return new StartTracingResponse(properties);
            };

            /**
             * Encodes the specified StartTracingResponse message. Does not implicitly {@link perfetto.protos.StartTracingResponse.verify|verify} messages.
             * @function encode
             * @memberof perfetto.protos.StartTracingResponse
             * @static
             * @param {perfetto.protos.IStartTracingResponse} message StartTracingResponse message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            StartTracingResponse.encode = function encode(message, writer) {
                if (!writer)
                    writer = $Writer.create();
                return writer;
            };

            /**
             * Encodes the specified StartTracingResponse message, length delimited. Does not implicitly {@link perfetto.protos.StartTracingResponse.verify|verify} messages.
             * @function encodeDelimited
             * @memberof perfetto.protos.StartTracingResponse
             * @static
             * @param {perfetto.protos.IStartTracingResponse} message StartTracingResponse message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            StartTracingResponse.encodeDelimited = function encodeDelimited(message, writer) {
                return this.encode(message, writer).ldelim();
            };

            /**
             * Decodes a StartTracingResponse message from the specified reader or buffer.
             * @function decode
             * @memberof perfetto.protos.StartTracingResponse
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @param {number} [length] Message length if known beforehand
             * @returns {perfetto.protos.StartTracingResponse} StartTracingResponse
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            StartTracingResponse.decode = function decode(reader, length) {
                if (!(reader instanceof $Reader))
                    reader = $Reader.create(reader);
                var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.StartTracingResponse();
                while (reader.pos < end) {
                    var tag = reader.uint32();
                    switch (tag >>> 3) {
                    default:
                        reader.skipType(tag & 7);
                        break;
                    }
                }
                return message;
            };

            /**
             * Decodes a StartTracingResponse message from the specified reader or buffer, length delimited.
             * @function decodeDelimited
             * @memberof perfetto.protos.StartTracingResponse
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @returns {perfetto.protos.StartTracingResponse} StartTracingResponse
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            StartTracingResponse.decodeDelimited = function decodeDelimited(reader) {
                if (!(reader instanceof $Reader))
                    reader = new $Reader(reader);
                return this.decode(reader, reader.uint32());
            };

            /**
             * Verifies a StartTracingResponse message.
             * @function verify
             * @memberof perfetto.protos.StartTracingResponse
             * @static
             * @param {Object.<string,*>} message Plain object to verify
             * @returns {string|null} `null` if valid, otherwise the reason why it is not
             */
            StartTracingResponse.verify = function verify(message) {
                if (typeof message !== "object" || message === null)
                    return "object expected";
                return null;
            };

            /**
             * Creates a StartTracingResponse message from a plain object. Also converts values to their respective internal types.
             * @function fromObject
             * @memberof perfetto.protos.StartTracingResponse
             * @static
             * @param {Object.<string,*>} object Plain object
             * @returns {perfetto.protos.StartTracingResponse} StartTracingResponse
             */
            StartTracingResponse.fromObject = function fromObject(object) {
                if (object instanceof $root.perfetto.protos.StartTracingResponse)
                    return object;
                return new $root.perfetto.protos.StartTracingResponse();
            };

            /**
             * Creates a plain object from a StartTracingResponse message. Also converts values to other types if specified.
             * @function toObject
             * @memberof perfetto.protos.StartTracingResponse
             * @static
             * @param {perfetto.protos.StartTracingResponse} message StartTracingResponse
             * @param {$protobuf.IConversionOptions} [options] Conversion options
             * @returns {Object.<string,*>} Plain object
             */
            StartTracingResponse.toObject = function toObject() {
                return {};
            };

            /**
             * Converts this StartTracingResponse to JSON.
             * @function toJSON
             * @memberof perfetto.protos.StartTracingResponse
             * @instance
             * @returns {Object.<string,*>} JSON object
             */
            StartTracingResponse.prototype.toJSON = function toJSON() {
                return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
            };

            return StartTracingResponse;
        })();

        protos.ChangeTraceConfigRequest = (function() {

            /**
             * Properties of a ChangeTraceConfigRequest.
             * @memberof perfetto.protos
             * @interface IChangeTraceConfigRequest
             * @property {perfetto.protos.ITraceConfig|null} [traceConfig] ChangeTraceConfigRequest traceConfig
             */

            /**
             * Constructs a new ChangeTraceConfigRequest.
             * @memberof perfetto.protos
             * @classdesc Represents a ChangeTraceConfigRequest.
             * @implements IChangeTraceConfigRequest
             * @constructor
             * @param {perfetto.protos.IChangeTraceConfigRequest=} [properties] Properties to set
             */
            function ChangeTraceConfigRequest(properties) {
                if (properties)
                    for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                        if (properties[keys[i]] != null)
                            this[keys[i]] = properties[keys[i]];
            }

            /**
             * ChangeTraceConfigRequest traceConfig.
             * @member {perfetto.protos.ITraceConfig|null|undefined} traceConfig
             * @memberof perfetto.protos.ChangeTraceConfigRequest
             * @instance
             */
            ChangeTraceConfigRequest.prototype.traceConfig = null;

            /**
             * Creates a new ChangeTraceConfigRequest instance using the specified properties.
             * @function create
             * @memberof perfetto.protos.ChangeTraceConfigRequest
             * @static
             * @param {perfetto.protos.IChangeTraceConfigRequest=} [properties] Properties to set
             * @returns {perfetto.protos.ChangeTraceConfigRequest} ChangeTraceConfigRequest instance
             */
            ChangeTraceConfigRequest.create = function create(properties) {
                return new ChangeTraceConfigRequest(properties);
            };

            /**
             * Encodes the specified ChangeTraceConfigRequest message. Does not implicitly {@link perfetto.protos.ChangeTraceConfigRequest.verify|verify} messages.
             * @function encode
             * @memberof perfetto.protos.ChangeTraceConfigRequest
             * @static
             * @param {perfetto.protos.IChangeTraceConfigRequest} message ChangeTraceConfigRequest message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            ChangeTraceConfigRequest.encode = function encode(message, writer) {
                if (!writer)
                    writer = $Writer.create();
                if (message.traceConfig != null && Object.hasOwnProperty.call(message, "traceConfig"))
                    $root.perfetto.protos.TraceConfig.encode(message.traceConfig, writer.uint32(/* id 1, wireType 2 =*/10).fork()).ldelim();
                return writer;
            };

            /**
             * Encodes the specified ChangeTraceConfigRequest message, length delimited. Does not implicitly {@link perfetto.protos.ChangeTraceConfigRequest.verify|verify} messages.
             * @function encodeDelimited
             * @memberof perfetto.protos.ChangeTraceConfigRequest
             * @static
             * @param {perfetto.protos.IChangeTraceConfigRequest} message ChangeTraceConfigRequest message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            ChangeTraceConfigRequest.encodeDelimited = function encodeDelimited(message, writer) {
                return this.encode(message, writer).ldelim();
            };

            /**
             * Decodes a ChangeTraceConfigRequest message from the specified reader or buffer.
             * @function decode
             * @memberof perfetto.protos.ChangeTraceConfigRequest
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @param {number} [length] Message length if known beforehand
             * @returns {perfetto.protos.ChangeTraceConfigRequest} ChangeTraceConfigRequest
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            ChangeTraceConfigRequest.decode = function decode(reader, length) {
                if (!(reader instanceof $Reader))
                    reader = $Reader.create(reader);
                var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.ChangeTraceConfigRequest();
                while (reader.pos < end) {
                    var tag = reader.uint32();
                    switch (tag >>> 3) {
                    case 1:
                        message.traceConfig = $root.perfetto.protos.TraceConfig.decode(reader, reader.uint32());
                        break;
                    default:
                        reader.skipType(tag & 7);
                        break;
                    }
                }
                return message;
            };

            /**
             * Decodes a ChangeTraceConfigRequest message from the specified reader or buffer, length delimited.
             * @function decodeDelimited
             * @memberof perfetto.protos.ChangeTraceConfigRequest
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @returns {perfetto.protos.ChangeTraceConfigRequest} ChangeTraceConfigRequest
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            ChangeTraceConfigRequest.decodeDelimited = function decodeDelimited(reader) {
                if (!(reader instanceof $Reader))
                    reader = new $Reader(reader);
                return this.decode(reader, reader.uint32());
            };

            /**
             * Verifies a ChangeTraceConfigRequest message.
             * @function verify
             * @memberof perfetto.protos.ChangeTraceConfigRequest
             * @static
             * @param {Object.<string,*>} message Plain object to verify
             * @returns {string|null} `null` if valid, otherwise the reason why it is not
             */
            ChangeTraceConfigRequest.verify = function verify(message) {
                if (typeof message !== "object" || message === null)
                    return "object expected";
                if (message.traceConfig != null && message.hasOwnProperty("traceConfig")) {
                    var error = $root.perfetto.protos.TraceConfig.verify(message.traceConfig);
                    if (error)
                        return "traceConfig." + error;
                }
                return null;
            };

            /**
             * Creates a ChangeTraceConfigRequest message from a plain object. Also converts values to their respective internal types.
             * @function fromObject
             * @memberof perfetto.protos.ChangeTraceConfigRequest
             * @static
             * @param {Object.<string,*>} object Plain object
             * @returns {perfetto.protos.ChangeTraceConfigRequest} ChangeTraceConfigRequest
             */
            ChangeTraceConfigRequest.fromObject = function fromObject(object) {
                if (object instanceof $root.perfetto.protos.ChangeTraceConfigRequest)
                    return object;
                var message = new $root.perfetto.protos.ChangeTraceConfigRequest();
                if (object.traceConfig != null) {
                    if (typeof object.traceConfig !== "object")
                        throw TypeError(".perfetto.protos.ChangeTraceConfigRequest.traceConfig: object expected");
                    message.traceConfig = $root.perfetto.protos.TraceConfig.fromObject(object.traceConfig);
                }
                return message;
            };

            /**
             * Creates a plain object from a ChangeTraceConfigRequest message. Also converts values to other types if specified.
             * @function toObject
             * @memberof perfetto.protos.ChangeTraceConfigRequest
             * @static
             * @param {perfetto.protos.ChangeTraceConfigRequest} message ChangeTraceConfigRequest
             * @param {$protobuf.IConversionOptions} [options] Conversion options
             * @returns {Object.<string,*>} Plain object
             */
            ChangeTraceConfigRequest.toObject = function toObject(message, options) {
                if (!options)
                    options = {};
                var object = {};
                if (options.defaults)
                    object.traceConfig = null;
                if (message.traceConfig != null && message.hasOwnProperty("traceConfig"))
                    object.traceConfig = $root.perfetto.protos.TraceConfig.toObject(message.traceConfig, options);
                return object;
            };

            /**
             * Converts this ChangeTraceConfigRequest to JSON.
             * @function toJSON
             * @memberof perfetto.protos.ChangeTraceConfigRequest
             * @instance
             * @returns {Object.<string,*>} JSON object
             */
            ChangeTraceConfigRequest.prototype.toJSON = function toJSON() {
                return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
            };

            return ChangeTraceConfigRequest;
        })();

        protos.ChangeTraceConfigResponse = (function() {

            /**
             * Properties of a ChangeTraceConfigResponse.
             * @memberof perfetto.protos
             * @interface IChangeTraceConfigResponse
             */

            /**
             * Constructs a new ChangeTraceConfigResponse.
             * @memberof perfetto.protos
             * @classdesc Represents a ChangeTraceConfigResponse.
             * @implements IChangeTraceConfigResponse
             * @constructor
             * @param {perfetto.protos.IChangeTraceConfigResponse=} [properties] Properties to set
             */
            function ChangeTraceConfigResponse(properties) {
                if (properties)
                    for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                        if (properties[keys[i]] != null)
                            this[keys[i]] = properties[keys[i]];
            }

            /**
             * Creates a new ChangeTraceConfigResponse instance using the specified properties.
             * @function create
             * @memberof perfetto.protos.ChangeTraceConfigResponse
             * @static
             * @param {perfetto.protos.IChangeTraceConfigResponse=} [properties] Properties to set
             * @returns {perfetto.protos.ChangeTraceConfigResponse} ChangeTraceConfigResponse instance
             */
            ChangeTraceConfigResponse.create = function create(properties) {
                return new ChangeTraceConfigResponse(properties);
            };

            /**
             * Encodes the specified ChangeTraceConfigResponse message. Does not implicitly {@link perfetto.protos.ChangeTraceConfigResponse.verify|verify} messages.
             * @function encode
             * @memberof perfetto.protos.ChangeTraceConfigResponse
             * @static
             * @param {perfetto.protos.IChangeTraceConfigResponse} message ChangeTraceConfigResponse message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            ChangeTraceConfigResponse.encode = function encode(message, writer) {
                if (!writer)
                    writer = $Writer.create();
                return writer;
            };

            /**
             * Encodes the specified ChangeTraceConfigResponse message, length delimited. Does not implicitly {@link perfetto.protos.ChangeTraceConfigResponse.verify|verify} messages.
             * @function encodeDelimited
             * @memberof perfetto.protos.ChangeTraceConfigResponse
             * @static
             * @param {perfetto.protos.IChangeTraceConfigResponse} message ChangeTraceConfigResponse message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            ChangeTraceConfigResponse.encodeDelimited = function encodeDelimited(message, writer) {
                return this.encode(message, writer).ldelim();
            };

            /**
             * Decodes a ChangeTraceConfigResponse message from the specified reader or buffer.
             * @function decode
             * @memberof perfetto.protos.ChangeTraceConfigResponse
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @param {number} [length] Message length if known beforehand
             * @returns {perfetto.protos.ChangeTraceConfigResponse} ChangeTraceConfigResponse
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            ChangeTraceConfigResponse.decode = function decode(reader, length) {
                if (!(reader instanceof $Reader))
                    reader = $Reader.create(reader);
                var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.ChangeTraceConfigResponse();
                while (reader.pos < end) {
                    var tag = reader.uint32();
                    switch (tag >>> 3) {
                    default:
                        reader.skipType(tag & 7);
                        break;
                    }
                }
                return message;
            };

            /**
             * Decodes a ChangeTraceConfigResponse message from the specified reader or buffer, length delimited.
             * @function decodeDelimited
             * @memberof perfetto.protos.ChangeTraceConfigResponse
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @returns {perfetto.protos.ChangeTraceConfigResponse} ChangeTraceConfigResponse
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            ChangeTraceConfigResponse.decodeDelimited = function decodeDelimited(reader) {
                if (!(reader instanceof $Reader))
                    reader = new $Reader(reader);
                return this.decode(reader, reader.uint32());
            };

            /**
             * Verifies a ChangeTraceConfigResponse message.
             * @function verify
             * @memberof perfetto.protos.ChangeTraceConfigResponse
             * @static
             * @param {Object.<string,*>} message Plain object to verify
             * @returns {string|null} `null` if valid, otherwise the reason why it is not
             */
            ChangeTraceConfigResponse.verify = function verify(message) {
                if (typeof message !== "object" || message === null)
                    return "object expected";
                return null;
            };

            /**
             * Creates a ChangeTraceConfigResponse message from a plain object. Also converts values to their respective internal types.
             * @function fromObject
             * @memberof perfetto.protos.ChangeTraceConfigResponse
             * @static
             * @param {Object.<string,*>} object Plain object
             * @returns {perfetto.protos.ChangeTraceConfigResponse} ChangeTraceConfigResponse
             */
            ChangeTraceConfigResponse.fromObject = function fromObject(object) {
                if (object instanceof $root.perfetto.protos.ChangeTraceConfigResponse)
                    return object;
                return new $root.perfetto.protos.ChangeTraceConfigResponse();
            };

            /**
             * Creates a plain object from a ChangeTraceConfigResponse message. Also converts values to other types if specified.
             * @function toObject
             * @memberof perfetto.protos.ChangeTraceConfigResponse
             * @static
             * @param {perfetto.protos.ChangeTraceConfigResponse} message ChangeTraceConfigResponse
             * @param {$protobuf.IConversionOptions} [options] Conversion options
             * @returns {Object.<string,*>} Plain object
             */
            ChangeTraceConfigResponse.toObject = function toObject() {
                return {};
            };

            /**
             * Converts this ChangeTraceConfigResponse to JSON.
             * @function toJSON
             * @memberof perfetto.protos.ChangeTraceConfigResponse
             * @instance
             * @returns {Object.<string,*>} JSON object
             */
            ChangeTraceConfigResponse.prototype.toJSON = function toJSON() {
                return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
            };

            return ChangeTraceConfigResponse;
        })();

        protos.DisableTracingRequest = (function() {

            /**
             * Properties of a DisableTracingRequest.
             * @memberof perfetto.protos
             * @interface IDisableTracingRequest
             */

            /**
             * Constructs a new DisableTracingRequest.
             * @memberof perfetto.protos
             * @classdesc Represents a DisableTracingRequest.
             * @implements IDisableTracingRequest
             * @constructor
             * @param {perfetto.protos.IDisableTracingRequest=} [properties] Properties to set
             */
            function DisableTracingRequest(properties) {
                if (properties)
                    for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                        if (properties[keys[i]] != null)
                            this[keys[i]] = properties[keys[i]];
            }

            /**
             * Creates a new DisableTracingRequest instance using the specified properties.
             * @function create
             * @memberof perfetto.protos.DisableTracingRequest
             * @static
             * @param {perfetto.protos.IDisableTracingRequest=} [properties] Properties to set
             * @returns {perfetto.protos.DisableTracingRequest} DisableTracingRequest instance
             */
            DisableTracingRequest.create = function create(properties) {
                return new DisableTracingRequest(properties);
            };

            /**
             * Encodes the specified DisableTracingRequest message. Does not implicitly {@link perfetto.protos.DisableTracingRequest.verify|verify} messages.
             * @function encode
             * @memberof perfetto.protos.DisableTracingRequest
             * @static
             * @param {perfetto.protos.IDisableTracingRequest} message DisableTracingRequest message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            DisableTracingRequest.encode = function encode(message, writer) {
                if (!writer)
                    writer = $Writer.create();
                return writer;
            };

            /**
             * Encodes the specified DisableTracingRequest message, length delimited. Does not implicitly {@link perfetto.protos.DisableTracingRequest.verify|verify} messages.
             * @function encodeDelimited
             * @memberof perfetto.protos.DisableTracingRequest
             * @static
             * @param {perfetto.protos.IDisableTracingRequest} message DisableTracingRequest message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            DisableTracingRequest.encodeDelimited = function encodeDelimited(message, writer) {
                return this.encode(message, writer).ldelim();
            };

            /**
             * Decodes a DisableTracingRequest message from the specified reader or buffer.
             * @function decode
             * @memberof perfetto.protos.DisableTracingRequest
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @param {number} [length] Message length if known beforehand
             * @returns {perfetto.protos.DisableTracingRequest} DisableTracingRequest
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            DisableTracingRequest.decode = function decode(reader, length) {
                if (!(reader instanceof $Reader))
                    reader = $Reader.create(reader);
                var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.DisableTracingRequest();
                while (reader.pos < end) {
                    var tag = reader.uint32();
                    switch (tag >>> 3) {
                    default:
                        reader.skipType(tag & 7);
                        break;
                    }
                }
                return message;
            };

            /**
             * Decodes a DisableTracingRequest message from the specified reader or buffer, length delimited.
             * @function decodeDelimited
             * @memberof perfetto.protos.DisableTracingRequest
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @returns {perfetto.protos.DisableTracingRequest} DisableTracingRequest
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            DisableTracingRequest.decodeDelimited = function decodeDelimited(reader) {
                if (!(reader instanceof $Reader))
                    reader = new $Reader(reader);
                return this.decode(reader, reader.uint32());
            };

            /**
             * Verifies a DisableTracingRequest message.
             * @function verify
             * @memberof perfetto.protos.DisableTracingRequest
             * @static
             * @param {Object.<string,*>} message Plain object to verify
             * @returns {string|null} `null` if valid, otherwise the reason why it is not
             */
            DisableTracingRequest.verify = function verify(message) {
                if (typeof message !== "object" || message === null)
                    return "object expected";
                return null;
            };

            /**
             * Creates a DisableTracingRequest message from a plain object. Also converts values to their respective internal types.
             * @function fromObject
             * @memberof perfetto.protos.DisableTracingRequest
             * @static
             * @param {Object.<string,*>} object Plain object
             * @returns {perfetto.protos.DisableTracingRequest} DisableTracingRequest
             */
            DisableTracingRequest.fromObject = function fromObject(object) {
                if (object instanceof $root.perfetto.protos.DisableTracingRequest)
                    return object;
                return new $root.perfetto.protos.DisableTracingRequest();
            };

            /**
             * Creates a plain object from a DisableTracingRequest message. Also converts values to other types if specified.
             * @function toObject
             * @memberof perfetto.protos.DisableTracingRequest
             * @static
             * @param {perfetto.protos.DisableTracingRequest} message DisableTracingRequest
             * @param {$protobuf.IConversionOptions} [options] Conversion options
             * @returns {Object.<string,*>} Plain object
             */
            DisableTracingRequest.toObject = function toObject() {
                return {};
            };

            /**
             * Converts this DisableTracingRequest to JSON.
             * @function toJSON
             * @memberof perfetto.protos.DisableTracingRequest
             * @instance
             * @returns {Object.<string,*>} JSON object
             */
            DisableTracingRequest.prototype.toJSON = function toJSON() {
                return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
            };

            return DisableTracingRequest;
        })();

        protos.DisableTracingResponse = (function() {

            /**
             * Properties of a DisableTracingResponse.
             * @memberof perfetto.protos
             * @interface IDisableTracingResponse
             */

            /**
             * Constructs a new DisableTracingResponse.
             * @memberof perfetto.protos
             * @classdesc Represents a DisableTracingResponse.
             * @implements IDisableTracingResponse
             * @constructor
             * @param {perfetto.protos.IDisableTracingResponse=} [properties] Properties to set
             */
            function DisableTracingResponse(properties) {
                if (properties)
                    for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                        if (properties[keys[i]] != null)
                            this[keys[i]] = properties[keys[i]];
            }

            /**
             * Creates a new DisableTracingResponse instance using the specified properties.
             * @function create
             * @memberof perfetto.protos.DisableTracingResponse
             * @static
             * @param {perfetto.protos.IDisableTracingResponse=} [properties] Properties to set
             * @returns {perfetto.protos.DisableTracingResponse} DisableTracingResponse instance
             */
            DisableTracingResponse.create = function create(properties) {
                return new DisableTracingResponse(properties);
            };

            /**
             * Encodes the specified DisableTracingResponse message. Does not implicitly {@link perfetto.protos.DisableTracingResponse.verify|verify} messages.
             * @function encode
             * @memberof perfetto.protos.DisableTracingResponse
             * @static
             * @param {perfetto.protos.IDisableTracingResponse} message DisableTracingResponse message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            DisableTracingResponse.encode = function encode(message, writer) {
                if (!writer)
                    writer = $Writer.create();
                return writer;
            };

            /**
             * Encodes the specified DisableTracingResponse message, length delimited. Does not implicitly {@link perfetto.protos.DisableTracingResponse.verify|verify} messages.
             * @function encodeDelimited
             * @memberof perfetto.protos.DisableTracingResponse
             * @static
             * @param {perfetto.protos.IDisableTracingResponse} message DisableTracingResponse message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            DisableTracingResponse.encodeDelimited = function encodeDelimited(message, writer) {
                return this.encode(message, writer).ldelim();
            };

            /**
             * Decodes a DisableTracingResponse message from the specified reader or buffer.
             * @function decode
             * @memberof perfetto.protos.DisableTracingResponse
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @param {number} [length] Message length if known beforehand
             * @returns {perfetto.protos.DisableTracingResponse} DisableTracingResponse
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            DisableTracingResponse.decode = function decode(reader, length) {
                if (!(reader instanceof $Reader))
                    reader = $Reader.create(reader);
                var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.DisableTracingResponse();
                while (reader.pos < end) {
                    var tag = reader.uint32();
                    switch (tag >>> 3) {
                    default:
                        reader.skipType(tag & 7);
                        break;
                    }
                }
                return message;
            };

            /**
             * Decodes a DisableTracingResponse message from the specified reader or buffer, length delimited.
             * @function decodeDelimited
             * @memberof perfetto.protos.DisableTracingResponse
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @returns {perfetto.protos.DisableTracingResponse} DisableTracingResponse
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            DisableTracingResponse.decodeDelimited = function decodeDelimited(reader) {
                if (!(reader instanceof $Reader))
                    reader = new $Reader(reader);
                return this.decode(reader, reader.uint32());
            };

            /**
             * Verifies a DisableTracingResponse message.
             * @function verify
             * @memberof perfetto.protos.DisableTracingResponse
             * @static
             * @param {Object.<string,*>} message Plain object to verify
             * @returns {string|null} `null` if valid, otherwise the reason why it is not
             */
            DisableTracingResponse.verify = function verify(message) {
                if (typeof message !== "object" || message === null)
                    return "object expected";
                return null;
            };

            /**
             * Creates a DisableTracingResponse message from a plain object. Also converts values to their respective internal types.
             * @function fromObject
             * @memberof perfetto.protos.DisableTracingResponse
             * @static
             * @param {Object.<string,*>} object Plain object
             * @returns {perfetto.protos.DisableTracingResponse} DisableTracingResponse
             */
            DisableTracingResponse.fromObject = function fromObject(object) {
                if (object instanceof $root.perfetto.protos.DisableTracingResponse)
                    return object;
                return new $root.perfetto.protos.DisableTracingResponse();
            };

            /**
             * Creates a plain object from a DisableTracingResponse message. Also converts values to other types if specified.
             * @function toObject
             * @memberof perfetto.protos.DisableTracingResponse
             * @static
             * @param {perfetto.protos.DisableTracingResponse} message DisableTracingResponse
             * @param {$protobuf.IConversionOptions} [options] Conversion options
             * @returns {Object.<string,*>} Plain object
             */
            DisableTracingResponse.toObject = function toObject() {
                return {};
            };

            /**
             * Converts this DisableTracingResponse to JSON.
             * @function toJSON
             * @memberof perfetto.protos.DisableTracingResponse
             * @instance
             * @returns {Object.<string,*>} JSON object
             */
            DisableTracingResponse.prototype.toJSON = function toJSON() {
                return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
            };

            return DisableTracingResponse;
        })();

        protos.ReadBuffersRequest = (function() {

            /**
             * Properties of a ReadBuffersRequest.
             * @memberof perfetto.protos
             * @interface IReadBuffersRequest
             */

            /**
             * Constructs a new ReadBuffersRequest.
             * @memberof perfetto.protos
             * @classdesc Represents a ReadBuffersRequest.
             * @implements IReadBuffersRequest
             * @constructor
             * @param {perfetto.protos.IReadBuffersRequest=} [properties] Properties to set
             */
            function ReadBuffersRequest(properties) {
                if (properties)
                    for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                        if (properties[keys[i]] != null)
                            this[keys[i]] = properties[keys[i]];
            }

            /**
             * Creates a new ReadBuffersRequest instance using the specified properties.
             * @function create
             * @memberof perfetto.protos.ReadBuffersRequest
             * @static
             * @param {perfetto.protos.IReadBuffersRequest=} [properties] Properties to set
             * @returns {perfetto.protos.ReadBuffersRequest} ReadBuffersRequest instance
             */
            ReadBuffersRequest.create = function create(properties) {
                return new ReadBuffersRequest(properties);
            };

            /**
             * Encodes the specified ReadBuffersRequest message. Does not implicitly {@link perfetto.protos.ReadBuffersRequest.verify|verify} messages.
             * @function encode
             * @memberof perfetto.protos.ReadBuffersRequest
             * @static
             * @param {perfetto.protos.IReadBuffersRequest} message ReadBuffersRequest message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            ReadBuffersRequest.encode = function encode(message, writer) {
                if (!writer)
                    writer = $Writer.create();
                return writer;
            };

            /**
             * Encodes the specified ReadBuffersRequest message, length delimited. Does not implicitly {@link perfetto.protos.ReadBuffersRequest.verify|verify} messages.
             * @function encodeDelimited
             * @memberof perfetto.protos.ReadBuffersRequest
             * @static
             * @param {perfetto.protos.IReadBuffersRequest} message ReadBuffersRequest message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            ReadBuffersRequest.encodeDelimited = function encodeDelimited(message, writer) {
                return this.encode(message, writer).ldelim();
            };

            /**
             * Decodes a ReadBuffersRequest message from the specified reader or buffer.
             * @function decode
             * @memberof perfetto.protos.ReadBuffersRequest
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @param {number} [length] Message length if known beforehand
             * @returns {perfetto.protos.ReadBuffersRequest} ReadBuffersRequest
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            ReadBuffersRequest.decode = function decode(reader, length) {
                if (!(reader instanceof $Reader))
                    reader = $Reader.create(reader);
                var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.ReadBuffersRequest();
                while (reader.pos < end) {
                    var tag = reader.uint32();
                    switch (tag >>> 3) {
                    default:
                        reader.skipType(tag & 7);
                        break;
                    }
                }
                return message;
            };

            /**
             * Decodes a ReadBuffersRequest message from the specified reader or buffer, length delimited.
             * @function decodeDelimited
             * @memberof perfetto.protos.ReadBuffersRequest
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @returns {perfetto.protos.ReadBuffersRequest} ReadBuffersRequest
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            ReadBuffersRequest.decodeDelimited = function decodeDelimited(reader) {
                if (!(reader instanceof $Reader))
                    reader = new $Reader(reader);
                return this.decode(reader, reader.uint32());
            };

            /**
             * Verifies a ReadBuffersRequest message.
             * @function verify
             * @memberof perfetto.protos.ReadBuffersRequest
             * @static
             * @param {Object.<string,*>} message Plain object to verify
             * @returns {string|null} `null` if valid, otherwise the reason why it is not
             */
            ReadBuffersRequest.verify = function verify(message) {
                if (typeof message !== "object" || message === null)
                    return "object expected";
                return null;
            };

            /**
             * Creates a ReadBuffersRequest message from a plain object. Also converts values to their respective internal types.
             * @function fromObject
             * @memberof perfetto.protos.ReadBuffersRequest
             * @static
             * @param {Object.<string,*>} object Plain object
             * @returns {perfetto.protos.ReadBuffersRequest} ReadBuffersRequest
             */
            ReadBuffersRequest.fromObject = function fromObject(object) {
                if (object instanceof $root.perfetto.protos.ReadBuffersRequest)
                    return object;
                return new $root.perfetto.protos.ReadBuffersRequest();
            };

            /**
             * Creates a plain object from a ReadBuffersRequest message. Also converts values to other types if specified.
             * @function toObject
             * @memberof perfetto.protos.ReadBuffersRequest
             * @static
             * @param {perfetto.protos.ReadBuffersRequest} message ReadBuffersRequest
             * @param {$protobuf.IConversionOptions} [options] Conversion options
             * @returns {Object.<string,*>} Plain object
             */
            ReadBuffersRequest.toObject = function toObject() {
                return {};
            };

            /**
             * Converts this ReadBuffersRequest to JSON.
             * @function toJSON
             * @memberof perfetto.protos.ReadBuffersRequest
             * @instance
             * @returns {Object.<string,*>} JSON object
             */
            ReadBuffersRequest.prototype.toJSON = function toJSON() {
                return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
            };

            return ReadBuffersRequest;
        })();

        protos.ReadBuffersResponse = (function() {

            /**
             * Properties of a ReadBuffersResponse.
             * @memberof perfetto.protos
             * @interface IReadBuffersResponse
             * @property {Array.<perfetto.protos.ReadBuffersResponse.ISlice>|null} [slices] ReadBuffersResponse slices
             */

            /**
             * Constructs a new ReadBuffersResponse.
             * @memberof perfetto.protos
             * @classdesc Represents a ReadBuffersResponse.
             * @implements IReadBuffersResponse
             * @constructor
             * @param {perfetto.protos.IReadBuffersResponse=} [properties] Properties to set
             */
            function ReadBuffersResponse(properties) {
                this.slices = [];
                if (properties)
                    for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                        if (properties[keys[i]] != null)
                            this[keys[i]] = properties[keys[i]];
            }

            /**
             * ReadBuffersResponse slices.
             * @member {Array.<perfetto.protos.ReadBuffersResponse.ISlice>} slices
             * @memberof perfetto.protos.ReadBuffersResponse
             * @instance
             */
            ReadBuffersResponse.prototype.slices = $util.emptyArray;

            /**
             * Creates a new ReadBuffersResponse instance using the specified properties.
             * @function create
             * @memberof perfetto.protos.ReadBuffersResponse
             * @static
             * @param {perfetto.protos.IReadBuffersResponse=} [properties] Properties to set
             * @returns {perfetto.protos.ReadBuffersResponse} ReadBuffersResponse instance
             */
            ReadBuffersResponse.create = function create(properties) {
                return new ReadBuffersResponse(properties);
            };

            /**
             * Encodes the specified ReadBuffersResponse message. Does not implicitly {@link perfetto.protos.ReadBuffersResponse.verify|verify} messages.
             * @function encode
             * @memberof perfetto.protos.ReadBuffersResponse
             * @static
             * @param {perfetto.protos.IReadBuffersResponse} message ReadBuffersResponse message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            ReadBuffersResponse.encode = function encode(message, writer) {
                if (!writer)
                    writer = $Writer.create();
                if (message.slices != null && message.slices.length)
                    for (var i = 0; i < message.slices.length; ++i)
                        $root.perfetto.protos.ReadBuffersResponse.Slice.encode(message.slices[i], writer.uint32(/* id 2, wireType 2 =*/18).fork()).ldelim();
                return writer;
            };

            /**
             * Encodes the specified ReadBuffersResponse message, length delimited. Does not implicitly {@link perfetto.protos.ReadBuffersResponse.verify|verify} messages.
             * @function encodeDelimited
             * @memberof perfetto.protos.ReadBuffersResponse
             * @static
             * @param {perfetto.protos.IReadBuffersResponse} message ReadBuffersResponse message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            ReadBuffersResponse.encodeDelimited = function encodeDelimited(message, writer) {
                return this.encode(message, writer).ldelim();
            };

            /**
             * Decodes a ReadBuffersResponse message from the specified reader or buffer.
             * @function decode
             * @memberof perfetto.protos.ReadBuffersResponse
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @param {number} [length] Message length if known beforehand
             * @returns {perfetto.protos.ReadBuffersResponse} ReadBuffersResponse
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            ReadBuffersResponse.decode = function decode(reader, length) {
                if (!(reader instanceof $Reader))
                    reader = $Reader.create(reader);
                var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.ReadBuffersResponse();
                while (reader.pos < end) {
                    var tag = reader.uint32();
                    switch (tag >>> 3) {
                    case 2:
                        if (!(message.slices && message.slices.length))
                            message.slices = [];
                        message.slices.push($root.perfetto.protos.ReadBuffersResponse.Slice.decode(reader, reader.uint32()));
                        break;
                    default:
                        reader.skipType(tag & 7);
                        break;
                    }
                }
                return message;
            };

            /**
             * Decodes a ReadBuffersResponse message from the specified reader or buffer, length delimited.
             * @function decodeDelimited
             * @memberof perfetto.protos.ReadBuffersResponse
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @returns {perfetto.protos.ReadBuffersResponse} ReadBuffersResponse
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            ReadBuffersResponse.decodeDelimited = function decodeDelimited(reader) {
                if (!(reader instanceof $Reader))
                    reader = new $Reader(reader);
                return this.decode(reader, reader.uint32());
            };

            /**
             * Verifies a ReadBuffersResponse message.
             * @function verify
             * @memberof perfetto.protos.ReadBuffersResponse
             * @static
             * @param {Object.<string,*>} message Plain object to verify
             * @returns {string|null} `null` if valid, otherwise the reason why it is not
             */
            ReadBuffersResponse.verify = function verify(message) {
                if (typeof message !== "object" || message === null)
                    return "object expected";
                if (message.slices != null && message.hasOwnProperty("slices")) {
                    if (!Array.isArray(message.slices))
                        return "slices: array expected";
                    for (var i = 0; i < message.slices.length; ++i) {
                        var error = $root.perfetto.protos.ReadBuffersResponse.Slice.verify(message.slices[i]);
                        if (error)
                            return "slices." + error;
                    }
                }
                return null;
            };

            /**
             * Creates a ReadBuffersResponse message from a plain object. Also converts values to their respective internal types.
             * @function fromObject
             * @memberof perfetto.protos.ReadBuffersResponse
             * @static
             * @param {Object.<string,*>} object Plain object
             * @returns {perfetto.protos.ReadBuffersResponse} ReadBuffersResponse
             */
            ReadBuffersResponse.fromObject = function fromObject(object) {
                if (object instanceof $root.perfetto.protos.ReadBuffersResponse)
                    return object;
                var message = new $root.perfetto.protos.ReadBuffersResponse();
                if (object.slices) {
                    if (!Array.isArray(object.slices))
                        throw TypeError(".perfetto.protos.ReadBuffersResponse.slices: array expected");
                    message.slices = [];
                    for (var i = 0; i < object.slices.length; ++i) {
                        if (typeof object.slices[i] !== "object")
                            throw TypeError(".perfetto.protos.ReadBuffersResponse.slices: object expected");
                        message.slices[i] = $root.perfetto.protos.ReadBuffersResponse.Slice.fromObject(object.slices[i]);
                    }
                }
                return message;
            };

            /**
             * Creates a plain object from a ReadBuffersResponse message. Also converts values to other types if specified.
             * @function toObject
             * @memberof perfetto.protos.ReadBuffersResponse
             * @static
             * @param {perfetto.protos.ReadBuffersResponse} message ReadBuffersResponse
             * @param {$protobuf.IConversionOptions} [options] Conversion options
             * @returns {Object.<string,*>} Plain object
             */
            ReadBuffersResponse.toObject = function toObject(message, options) {
                if (!options)
                    options = {};
                var object = {};
                if (options.arrays || options.defaults)
                    object.slices = [];
                if (message.slices && message.slices.length) {
                    object.slices = [];
                    for (var j = 0; j < message.slices.length; ++j)
                        object.slices[j] = $root.perfetto.protos.ReadBuffersResponse.Slice.toObject(message.slices[j], options);
                }
                return object;
            };

            /**
             * Converts this ReadBuffersResponse to JSON.
             * @function toJSON
             * @memberof perfetto.protos.ReadBuffersResponse
             * @instance
             * @returns {Object.<string,*>} JSON object
             */
            ReadBuffersResponse.prototype.toJSON = function toJSON() {
                return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
            };

            ReadBuffersResponse.Slice = (function() {

                /**
                 * Properties of a Slice.
                 * @memberof perfetto.protos.ReadBuffersResponse
                 * @interface ISlice
                 * @property {Uint8Array|null} [data] Slice data
                 * @property {boolean|null} [lastSliceForPacket] Slice lastSliceForPacket
                 */

                /**
                 * Constructs a new Slice.
                 * @memberof perfetto.protos.ReadBuffersResponse
                 * @classdesc Represents a Slice.
                 * @implements ISlice
                 * @constructor
                 * @param {perfetto.protos.ReadBuffersResponse.ISlice=} [properties] Properties to set
                 */
                function Slice(properties) {
                    if (properties)
                        for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                            if (properties[keys[i]] != null)
                                this[keys[i]] = properties[keys[i]];
                }

                /**
                 * Slice data.
                 * @member {Uint8Array} data
                 * @memberof perfetto.protos.ReadBuffersResponse.Slice
                 * @instance
                 */
                Slice.prototype.data = $util.newBuffer([]);

                /**
                 * Slice lastSliceForPacket.
                 * @member {boolean} lastSliceForPacket
                 * @memberof perfetto.protos.ReadBuffersResponse.Slice
                 * @instance
                 */
                Slice.prototype.lastSliceForPacket = false;

                /**
                 * Creates a new Slice instance using the specified properties.
                 * @function create
                 * @memberof perfetto.protos.ReadBuffersResponse.Slice
                 * @static
                 * @param {perfetto.protos.ReadBuffersResponse.ISlice=} [properties] Properties to set
                 * @returns {perfetto.protos.ReadBuffersResponse.Slice} Slice instance
                 */
                Slice.create = function create(properties) {
                    return new Slice(properties);
                };

                /**
                 * Encodes the specified Slice message. Does not implicitly {@link perfetto.protos.ReadBuffersResponse.Slice.verify|verify} messages.
                 * @function encode
                 * @memberof perfetto.protos.ReadBuffersResponse.Slice
                 * @static
                 * @param {perfetto.protos.ReadBuffersResponse.ISlice} message Slice message or plain object to encode
                 * @param {$protobuf.Writer} [writer] Writer to encode to
                 * @returns {$protobuf.Writer} Writer
                 */
                Slice.encode = function encode(message, writer) {
                    if (!writer)
                        writer = $Writer.create();
                    if (message.data != null && Object.hasOwnProperty.call(message, "data"))
                        writer.uint32(/* id 1, wireType 2 =*/10).bytes(message.data);
                    if (message.lastSliceForPacket != null && Object.hasOwnProperty.call(message, "lastSliceForPacket"))
                        writer.uint32(/* id 2, wireType 0 =*/16).bool(message.lastSliceForPacket);
                    return writer;
                };

                /**
                 * Encodes the specified Slice message, length delimited. Does not implicitly {@link perfetto.protos.ReadBuffersResponse.Slice.verify|verify} messages.
                 * @function encodeDelimited
                 * @memberof perfetto.protos.ReadBuffersResponse.Slice
                 * @static
                 * @param {perfetto.protos.ReadBuffersResponse.ISlice} message Slice message or plain object to encode
                 * @param {$protobuf.Writer} [writer] Writer to encode to
                 * @returns {$protobuf.Writer} Writer
                 */
                Slice.encodeDelimited = function encodeDelimited(message, writer) {
                    return this.encode(message, writer).ldelim();
                };

                /**
                 * Decodes a Slice message from the specified reader or buffer.
                 * @function decode
                 * @memberof perfetto.protos.ReadBuffersResponse.Slice
                 * @static
                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                 * @param {number} [length] Message length if known beforehand
                 * @returns {perfetto.protos.ReadBuffersResponse.Slice} Slice
                 * @throws {Error} If the payload is not a reader or valid buffer
                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
                 */
                Slice.decode = function decode(reader, length) {
                    if (!(reader instanceof $Reader))
                        reader = $Reader.create(reader);
                    var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.ReadBuffersResponse.Slice();
                    while (reader.pos < end) {
                        var tag = reader.uint32();
                        switch (tag >>> 3) {
                        case 1:
                            message.data = reader.bytes();
                            break;
                        case 2:
                            message.lastSliceForPacket = reader.bool();
                            break;
                        default:
                            reader.skipType(tag & 7);
                            break;
                        }
                    }
                    return message;
                };

                /**
                 * Decodes a Slice message from the specified reader or buffer, length delimited.
                 * @function decodeDelimited
                 * @memberof perfetto.protos.ReadBuffersResponse.Slice
                 * @static
                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                 * @returns {perfetto.protos.ReadBuffersResponse.Slice} Slice
                 * @throws {Error} If the payload is not a reader or valid buffer
                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
                 */
                Slice.decodeDelimited = function decodeDelimited(reader) {
                    if (!(reader instanceof $Reader))
                        reader = new $Reader(reader);
                    return this.decode(reader, reader.uint32());
                };

                /**
                 * Verifies a Slice message.
                 * @function verify
                 * @memberof perfetto.protos.ReadBuffersResponse.Slice
                 * @static
                 * @param {Object.<string,*>} message Plain object to verify
                 * @returns {string|null} `null` if valid, otherwise the reason why it is not
                 */
                Slice.verify = function verify(message) {
                    if (typeof message !== "object" || message === null)
                        return "object expected";
                    if (message.data != null && message.hasOwnProperty("data"))
                        if (!(message.data && typeof message.data.length === "number" || $util.isString(message.data)))
                            return "data: buffer expected";
                    if (message.lastSliceForPacket != null && message.hasOwnProperty("lastSliceForPacket"))
                        if (typeof message.lastSliceForPacket !== "boolean")
                            return "lastSliceForPacket: boolean expected";
                    return null;
                };

                /**
                 * Creates a Slice message from a plain object. Also converts values to their respective internal types.
                 * @function fromObject
                 * @memberof perfetto.protos.ReadBuffersResponse.Slice
                 * @static
                 * @param {Object.<string,*>} object Plain object
                 * @returns {perfetto.protos.ReadBuffersResponse.Slice} Slice
                 */
                Slice.fromObject = function fromObject(object) {
                    if (object instanceof $root.perfetto.protos.ReadBuffersResponse.Slice)
                        return object;
                    var message = new $root.perfetto.protos.ReadBuffersResponse.Slice();
                    if (object.data != null)
                        if (typeof object.data === "string")
                            $util.base64.decode(object.data, message.data = $util.newBuffer($util.base64.length(object.data)), 0);
                        else if (object.data.length)
                            message.data = object.data;
                    if (object.lastSliceForPacket != null)
                        message.lastSliceForPacket = Boolean(object.lastSliceForPacket);
                    return message;
                };

                /**
                 * Creates a plain object from a Slice message. Also converts values to other types if specified.
                 * @function toObject
                 * @memberof perfetto.protos.ReadBuffersResponse.Slice
                 * @static
                 * @param {perfetto.protos.ReadBuffersResponse.Slice} message Slice
                 * @param {$protobuf.IConversionOptions} [options] Conversion options
                 * @returns {Object.<string,*>} Plain object
                 */
                Slice.toObject = function toObject(message, options) {
                    if (!options)
                        options = {};
                    var object = {};
                    if (options.defaults) {
                        if (options.bytes === String)
                            object.data = "";
                        else {
                            object.data = [];
                            if (options.bytes !== Array)
                                object.data = $util.newBuffer(object.data);
                        }
                        object.lastSliceForPacket = false;
                    }
                    if (message.data != null && message.hasOwnProperty("data"))
                        object.data = options.bytes === String ? $util.base64.encode(message.data, 0, message.data.length) : options.bytes === Array ? Array.prototype.slice.call(message.data) : message.data;
                    if (message.lastSliceForPacket != null && message.hasOwnProperty("lastSliceForPacket"))
                        object.lastSliceForPacket = message.lastSliceForPacket;
                    return object;
                };

                /**
                 * Converts this Slice to JSON.
                 * @function toJSON
                 * @memberof perfetto.protos.ReadBuffersResponse.Slice
                 * @instance
                 * @returns {Object.<string,*>} JSON object
                 */
                Slice.prototype.toJSON = function toJSON() {
                    return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
                };

                return Slice;
            })();

            return ReadBuffersResponse;
        })();

        protos.FreeBuffersRequest = (function() {

            /**
             * Properties of a FreeBuffersRequest.
             * @memberof perfetto.protos
             * @interface IFreeBuffersRequest
             * @property {Array.<number>|null} [bufferIds] FreeBuffersRequest bufferIds
             */

            /**
             * Constructs a new FreeBuffersRequest.
             * @memberof perfetto.protos
             * @classdesc Represents a FreeBuffersRequest.
             * @implements IFreeBuffersRequest
             * @constructor
             * @param {perfetto.protos.IFreeBuffersRequest=} [properties] Properties to set
             */
            function FreeBuffersRequest(properties) {
                this.bufferIds = [];
                if (properties)
                    for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                        if (properties[keys[i]] != null)
                            this[keys[i]] = properties[keys[i]];
            }

            /**
             * FreeBuffersRequest bufferIds.
             * @member {Array.<number>} bufferIds
             * @memberof perfetto.protos.FreeBuffersRequest
             * @instance
             */
            FreeBuffersRequest.prototype.bufferIds = $util.emptyArray;

            /**
             * Creates a new FreeBuffersRequest instance using the specified properties.
             * @function create
             * @memberof perfetto.protos.FreeBuffersRequest
             * @static
             * @param {perfetto.protos.IFreeBuffersRequest=} [properties] Properties to set
             * @returns {perfetto.protos.FreeBuffersRequest} FreeBuffersRequest instance
             */
            FreeBuffersRequest.create = function create(properties) {
                return new FreeBuffersRequest(properties);
            };

            /**
             * Encodes the specified FreeBuffersRequest message. Does not implicitly {@link perfetto.protos.FreeBuffersRequest.verify|verify} messages.
             * @function encode
             * @memberof perfetto.protos.FreeBuffersRequest
             * @static
             * @param {perfetto.protos.IFreeBuffersRequest} message FreeBuffersRequest message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            FreeBuffersRequest.encode = function encode(message, writer) {
                if (!writer)
                    writer = $Writer.create();
                if (message.bufferIds != null && message.bufferIds.length)
                    for (var i = 0; i < message.bufferIds.length; ++i)
                        writer.uint32(/* id 1, wireType 0 =*/8).uint32(message.bufferIds[i]);
                return writer;
            };

            /**
             * Encodes the specified FreeBuffersRequest message, length delimited. Does not implicitly {@link perfetto.protos.FreeBuffersRequest.verify|verify} messages.
             * @function encodeDelimited
             * @memberof perfetto.protos.FreeBuffersRequest
             * @static
             * @param {perfetto.protos.IFreeBuffersRequest} message FreeBuffersRequest message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            FreeBuffersRequest.encodeDelimited = function encodeDelimited(message, writer) {
                return this.encode(message, writer).ldelim();
            };

            /**
             * Decodes a FreeBuffersRequest message from the specified reader or buffer.
             * @function decode
             * @memberof perfetto.protos.FreeBuffersRequest
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @param {number} [length] Message length if known beforehand
             * @returns {perfetto.protos.FreeBuffersRequest} FreeBuffersRequest
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            FreeBuffersRequest.decode = function decode(reader, length) {
                if (!(reader instanceof $Reader))
                    reader = $Reader.create(reader);
                var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.FreeBuffersRequest();
                while (reader.pos < end) {
                    var tag = reader.uint32();
                    switch (tag >>> 3) {
                    case 1:
                        if (!(message.bufferIds && message.bufferIds.length))
                            message.bufferIds = [];
                        if ((tag & 7) === 2) {
                            var end2 = reader.uint32() + reader.pos;
                            while (reader.pos < end2)
                                message.bufferIds.push(reader.uint32());
                        } else
                            message.bufferIds.push(reader.uint32());
                        break;
                    default:
                        reader.skipType(tag & 7);
                        break;
                    }
                }
                return message;
            };

            /**
             * Decodes a FreeBuffersRequest message from the specified reader or buffer, length delimited.
             * @function decodeDelimited
             * @memberof perfetto.protos.FreeBuffersRequest
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @returns {perfetto.protos.FreeBuffersRequest} FreeBuffersRequest
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            FreeBuffersRequest.decodeDelimited = function decodeDelimited(reader) {
                if (!(reader instanceof $Reader))
                    reader = new $Reader(reader);
                return this.decode(reader, reader.uint32());
            };

            /**
             * Verifies a FreeBuffersRequest message.
             * @function verify
             * @memberof perfetto.protos.FreeBuffersRequest
             * @static
             * @param {Object.<string,*>} message Plain object to verify
             * @returns {string|null} `null` if valid, otherwise the reason why it is not
             */
            FreeBuffersRequest.verify = function verify(message) {
                if (typeof message !== "object" || message === null)
                    return "object expected";
                if (message.bufferIds != null && message.hasOwnProperty("bufferIds")) {
                    if (!Array.isArray(message.bufferIds))
                        return "bufferIds: array expected";
                    for (var i = 0; i < message.bufferIds.length; ++i)
                        if (!$util.isInteger(message.bufferIds[i]))
                            return "bufferIds: integer[] expected";
                }
                return null;
            };

            /**
             * Creates a FreeBuffersRequest message from a plain object. Also converts values to their respective internal types.
             * @function fromObject
             * @memberof perfetto.protos.FreeBuffersRequest
             * @static
             * @param {Object.<string,*>} object Plain object
             * @returns {perfetto.protos.FreeBuffersRequest} FreeBuffersRequest
             */
            FreeBuffersRequest.fromObject = function fromObject(object) {
                if (object instanceof $root.perfetto.protos.FreeBuffersRequest)
                    return object;
                var message = new $root.perfetto.protos.FreeBuffersRequest();
                if (object.bufferIds) {
                    if (!Array.isArray(object.bufferIds))
                        throw TypeError(".perfetto.protos.FreeBuffersRequest.bufferIds: array expected");
                    message.bufferIds = [];
                    for (var i = 0; i < object.bufferIds.length; ++i)
                        message.bufferIds[i] = object.bufferIds[i] >>> 0;
                }
                return message;
            };

            /**
             * Creates a plain object from a FreeBuffersRequest message. Also converts values to other types if specified.
             * @function toObject
             * @memberof perfetto.protos.FreeBuffersRequest
             * @static
             * @param {perfetto.protos.FreeBuffersRequest} message FreeBuffersRequest
             * @param {$protobuf.IConversionOptions} [options] Conversion options
             * @returns {Object.<string,*>} Plain object
             */
            FreeBuffersRequest.toObject = function toObject(message, options) {
                if (!options)
                    options = {};
                var object = {};
                if (options.arrays || options.defaults)
                    object.bufferIds = [];
                if (message.bufferIds && message.bufferIds.length) {
                    object.bufferIds = [];
                    for (var j = 0; j < message.bufferIds.length; ++j)
                        object.bufferIds[j] = message.bufferIds[j];
                }
                return object;
            };

            /**
             * Converts this FreeBuffersRequest to JSON.
             * @function toJSON
             * @memberof perfetto.protos.FreeBuffersRequest
             * @instance
             * @returns {Object.<string,*>} JSON object
             */
            FreeBuffersRequest.prototype.toJSON = function toJSON() {
                return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
            };

            return FreeBuffersRequest;
        })();

        protos.FreeBuffersResponse = (function() {

            /**
             * Properties of a FreeBuffersResponse.
             * @memberof perfetto.protos
             * @interface IFreeBuffersResponse
             */

            /**
             * Constructs a new FreeBuffersResponse.
             * @memberof perfetto.protos
             * @classdesc Represents a FreeBuffersResponse.
             * @implements IFreeBuffersResponse
             * @constructor
             * @param {perfetto.protos.IFreeBuffersResponse=} [properties] Properties to set
             */
            function FreeBuffersResponse(properties) {
                if (properties)
                    for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                        if (properties[keys[i]] != null)
                            this[keys[i]] = properties[keys[i]];
            }

            /**
             * Creates a new FreeBuffersResponse instance using the specified properties.
             * @function create
             * @memberof perfetto.protos.FreeBuffersResponse
             * @static
             * @param {perfetto.protos.IFreeBuffersResponse=} [properties] Properties to set
             * @returns {perfetto.protos.FreeBuffersResponse} FreeBuffersResponse instance
             */
            FreeBuffersResponse.create = function create(properties) {
                return new FreeBuffersResponse(properties);
            };

            /**
             * Encodes the specified FreeBuffersResponse message. Does not implicitly {@link perfetto.protos.FreeBuffersResponse.verify|verify} messages.
             * @function encode
             * @memberof perfetto.protos.FreeBuffersResponse
             * @static
             * @param {perfetto.protos.IFreeBuffersResponse} message FreeBuffersResponse message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            FreeBuffersResponse.encode = function encode(message, writer) {
                if (!writer)
                    writer = $Writer.create();
                return writer;
            };

            /**
             * Encodes the specified FreeBuffersResponse message, length delimited. Does not implicitly {@link perfetto.protos.FreeBuffersResponse.verify|verify} messages.
             * @function encodeDelimited
             * @memberof perfetto.protos.FreeBuffersResponse
             * @static
             * @param {perfetto.protos.IFreeBuffersResponse} message FreeBuffersResponse message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            FreeBuffersResponse.encodeDelimited = function encodeDelimited(message, writer) {
                return this.encode(message, writer).ldelim();
            };

            /**
             * Decodes a FreeBuffersResponse message from the specified reader or buffer.
             * @function decode
             * @memberof perfetto.protos.FreeBuffersResponse
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @param {number} [length] Message length if known beforehand
             * @returns {perfetto.protos.FreeBuffersResponse} FreeBuffersResponse
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            FreeBuffersResponse.decode = function decode(reader, length) {
                if (!(reader instanceof $Reader))
                    reader = $Reader.create(reader);
                var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.FreeBuffersResponse();
                while (reader.pos < end) {
                    var tag = reader.uint32();
                    switch (tag >>> 3) {
                    default:
                        reader.skipType(tag & 7);
                        break;
                    }
                }
                return message;
            };

            /**
             * Decodes a FreeBuffersResponse message from the specified reader or buffer, length delimited.
             * @function decodeDelimited
             * @memberof perfetto.protos.FreeBuffersResponse
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @returns {perfetto.protos.FreeBuffersResponse} FreeBuffersResponse
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            FreeBuffersResponse.decodeDelimited = function decodeDelimited(reader) {
                if (!(reader instanceof $Reader))
                    reader = new $Reader(reader);
                return this.decode(reader, reader.uint32());
            };

            /**
             * Verifies a FreeBuffersResponse message.
             * @function verify
             * @memberof perfetto.protos.FreeBuffersResponse
             * @static
             * @param {Object.<string,*>} message Plain object to verify
             * @returns {string|null} `null` if valid, otherwise the reason why it is not
             */
            FreeBuffersResponse.verify = function verify(message) {
                if (typeof message !== "object" || message === null)
                    return "object expected";
                return null;
            };

            /**
             * Creates a FreeBuffersResponse message from a plain object. Also converts values to their respective internal types.
             * @function fromObject
             * @memberof perfetto.protos.FreeBuffersResponse
             * @static
             * @param {Object.<string,*>} object Plain object
             * @returns {perfetto.protos.FreeBuffersResponse} FreeBuffersResponse
             */
            FreeBuffersResponse.fromObject = function fromObject(object) {
                if (object instanceof $root.perfetto.protos.FreeBuffersResponse)
                    return object;
                return new $root.perfetto.protos.FreeBuffersResponse();
            };

            /**
             * Creates a plain object from a FreeBuffersResponse message. Also converts values to other types if specified.
             * @function toObject
             * @memberof perfetto.protos.FreeBuffersResponse
             * @static
             * @param {perfetto.protos.FreeBuffersResponse} message FreeBuffersResponse
             * @param {$protobuf.IConversionOptions} [options] Conversion options
             * @returns {Object.<string,*>} Plain object
             */
            FreeBuffersResponse.toObject = function toObject() {
                return {};
            };

            /**
             * Converts this FreeBuffersResponse to JSON.
             * @function toJSON
             * @memberof perfetto.protos.FreeBuffersResponse
             * @instance
             * @returns {Object.<string,*>} JSON object
             */
            FreeBuffersResponse.prototype.toJSON = function toJSON() {
                return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
            };

            return FreeBuffersResponse;
        })();

        protos.FlushRequest = (function() {

            /**
             * Properties of a FlushRequest.
             * @memberof perfetto.protos
             * @interface IFlushRequest
             * @property {number|null} [timeoutMs] FlushRequest timeoutMs
             */

            /**
             * Constructs a new FlushRequest.
             * @memberof perfetto.protos
             * @classdesc Represents a FlushRequest.
             * @implements IFlushRequest
             * @constructor
             * @param {perfetto.protos.IFlushRequest=} [properties] Properties to set
             */
            function FlushRequest(properties) {
                if (properties)
                    for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                        if (properties[keys[i]] != null)
                            this[keys[i]] = properties[keys[i]];
            }

            /**
             * FlushRequest timeoutMs.
             * @member {number} timeoutMs
             * @memberof perfetto.protos.FlushRequest
             * @instance
             */
            FlushRequest.prototype.timeoutMs = 0;

            /**
             * Creates a new FlushRequest instance using the specified properties.
             * @function create
             * @memberof perfetto.protos.FlushRequest
             * @static
             * @param {perfetto.protos.IFlushRequest=} [properties] Properties to set
             * @returns {perfetto.protos.FlushRequest} FlushRequest instance
             */
            FlushRequest.create = function create(properties) {
                return new FlushRequest(properties);
            };

            /**
             * Encodes the specified FlushRequest message. Does not implicitly {@link perfetto.protos.FlushRequest.verify|verify} messages.
             * @function encode
             * @memberof perfetto.protos.FlushRequest
             * @static
             * @param {perfetto.protos.IFlushRequest} message FlushRequest message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            FlushRequest.encode = function encode(message, writer) {
                if (!writer)
                    writer = $Writer.create();
                if (message.timeoutMs != null && Object.hasOwnProperty.call(message, "timeoutMs"))
                    writer.uint32(/* id 1, wireType 0 =*/8).uint32(message.timeoutMs);
                return writer;
            };

            /**
             * Encodes the specified FlushRequest message, length delimited. Does not implicitly {@link perfetto.protos.FlushRequest.verify|verify} messages.
             * @function encodeDelimited
             * @memberof perfetto.protos.FlushRequest
             * @static
             * @param {perfetto.protos.IFlushRequest} message FlushRequest message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            FlushRequest.encodeDelimited = function encodeDelimited(message, writer) {
                return this.encode(message, writer).ldelim();
            };

            /**
             * Decodes a FlushRequest message from the specified reader or buffer.
             * @function decode
             * @memberof perfetto.protos.FlushRequest
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @param {number} [length] Message length if known beforehand
             * @returns {perfetto.protos.FlushRequest} FlushRequest
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            FlushRequest.decode = function decode(reader, length) {
                if (!(reader instanceof $Reader))
                    reader = $Reader.create(reader);
                var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.FlushRequest();
                while (reader.pos < end) {
                    var tag = reader.uint32();
                    switch (tag >>> 3) {
                    case 1:
                        message.timeoutMs = reader.uint32();
                        break;
                    default:
                        reader.skipType(tag & 7);
                        break;
                    }
                }
                return message;
            };

            /**
             * Decodes a FlushRequest message from the specified reader or buffer, length delimited.
             * @function decodeDelimited
             * @memberof perfetto.protos.FlushRequest
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @returns {perfetto.protos.FlushRequest} FlushRequest
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            FlushRequest.decodeDelimited = function decodeDelimited(reader) {
                if (!(reader instanceof $Reader))
                    reader = new $Reader(reader);
                return this.decode(reader, reader.uint32());
            };

            /**
             * Verifies a FlushRequest message.
             * @function verify
             * @memberof perfetto.protos.FlushRequest
             * @static
             * @param {Object.<string,*>} message Plain object to verify
             * @returns {string|null} `null` if valid, otherwise the reason why it is not
             */
            FlushRequest.verify = function verify(message) {
                if (typeof message !== "object" || message === null)
                    return "object expected";
                if (message.timeoutMs != null && message.hasOwnProperty("timeoutMs"))
                    if (!$util.isInteger(message.timeoutMs))
                        return "timeoutMs: integer expected";
                return null;
            };

            /**
             * Creates a FlushRequest message from a plain object. Also converts values to their respective internal types.
             * @function fromObject
             * @memberof perfetto.protos.FlushRequest
             * @static
             * @param {Object.<string,*>} object Plain object
             * @returns {perfetto.protos.FlushRequest} FlushRequest
             */
            FlushRequest.fromObject = function fromObject(object) {
                if (object instanceof $root.perfetto.protos.FlushRequest)
                    return object;
                var message = new $root.perfetto.protos.FlushRequest();
                if (object.timeoutMs != null)
                    message.timeoutMs = object.timeoutMs >>> 0;
                return message;
            };

            /**
             * Creates a plain object from a FlushRequest message. Also converts values to other types if specified.
             * @function toObject
             * @memberof perfetto.protos.FlushRequest
             * @static
             * @param {perfetto.protos.FlushRequest} message FlushRequest
             * @param {$protobuf.IConversionOptions} [options] Conversion options
             * @returns {Object.<string,*>} Plain object
             */
            FlushRequest.toObject = function toObject(message, options) {
                if (!options)
                    options = {};
                var object = {};
                if (options.defaults)
                    object.timeoutMs = 0;
                if (message.timeoutMs != null && message.hasOwnProperty("timeoutMs"))
                    object.timeoutMs = message.timeoutMs;
                return object;
            };

            /**
             * Converts this FlushRequest to JSON.
             * @function toJSON
             * @memberof perfetto.protos.FlushRequest
             * @instance
             * @returns {Object.<string,*>} JSON object
             */
            FlushRequest.prototype.toJSON = function toJSON() {
                return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
            };

            return FlushRequest;
        })();

        protos.FlushResponse = (function() {

            /**
             * Properties of a FlushResponse.
             * @memberof perfetto.protos
             * @interface IFlushResponse
             */

            /**
             * Constructs a new FlushResponse.
             * @memberof perfetto.protos
             * @classdesc Represents a FlushResponse.
             * @implements IFlushResponse
             * @constructor
             * @param {perfetto.protos.IFlushResponse=} [properties] Properties to set
             */
            function FlushResponse(properties) {
                if (properties)
                    for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                        if (properties[keys[i]] != null)
                            this[keys[i]] = properties[keys[i]];
            }

            /**
             * Creates a new FlushResponse instance using the specified properties.
             * @function create
             * @memberof perfetto.protos.FlushResponse
             * @static
             * @param {perfetto.protos.IFlushResponse=} [properties] Properties to set
             * @returns {perfetto.protos.FlushResponse} FlushResponse instance
             */
            FlushResponse.create = function create(properties) {
                return new FlushResponse(properties);
            };

            /**
             * Encodes the specified FlushResponse message. Does not implicitly {@link perfetto.protos.FlushResponse.verify|verify} messages.
             * @function encode
             * @memberof perfetto.protos.FlushResponse
             * @static
             * @param {perfetto.protos.IFlushResponse} message FlushResponse message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            FlushResponse.encode = function encode(message, writer) {
                if (!writer)
                    writer = $Writer.create();
                return writer;
            };

            /**
             * Encodes the specified FlushResponse message, length delimited. Does not implicitly {@link perfetto.protos.FlushResponse.verify|verify} messages.
             * @function encodeDelimited
             * @memberof perfetto.protos.FlushResponse
             * @static
             * @param {perfetto.protos.IFlushResponse} message FlushResponse message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            FlushResponse.encodeDelimited = function encodeDelimited(message, writer) {
                return this.encode(message, writer).ldelim();
            };

            /**
             * Decodes a FlushResponse message from the specified reader or buffer.
             * @function decode
             * @memberof perfetto.protos.FlushResponse
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @param {number} [length] Message length if known beforehand
             * @returns {perfetto.protos.FlushResponse} FlushResponse
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            FlushResponse.decode = function decode(reader, length) {
                if (!(reader instanceof $Reader))
                    reader = $Reader.create(reader);
                var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.FlushResponse();
                while (reader.pos < end) {
                    var tag = reader.uint32();
                    switch (tag >>> 3) {
                    default:
                        reader.skipType(tag & 7);
                        break;
                    }
                }
                return message;
            };

            /**
             * Decodes a FlushResponse message from the specified reader or buffer, length delimited.
             * @function decodeDelimited
             * @memberof perfetto.protos.FlushResponse
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @returns {perfetto.protos.FlushResponse} FlushResponse
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            FlushResponse.decodeDelimited = function decodeDelimited(reader) {
                if (!(reader instanceof $Reader))
                    reader = new $Reader(reader);
                return this.decode(reader, reader.uint32());
            };

            /**
             * Verifies a FlushResponse message.
             * @function verify
             * @memberof perfetto.protos.FlushResponse
             * @static
             * @param {Object.<string,*>} message Plain object to verify
             * @returns {string|null} `null` if valid, otherwise the reason why it is not
             */
            FlushResponse.verify = function verify(message) {
                if (typeof message !== "object" || message === null)
                    return "object expected";
                return null;
            };

            /**
             * Creates a FlushResponse message from a plain object. Also converts values to their respective internal types.
             * @function fromObject
             * @memberof perfetto.protos.FlushResponse
             * @static
             * @param {Object.<string,*>} object Plain object
             * @returns {perfetto.protos.FlushResponse} FlushResponse
             */
            FlushResponse.fromObject = function fromObject(object) {
                if (object instanceof $root.perfetto.protos.FlushResponse)
                    return object;
                return new $root.perfetto.protos.FlushResponse();
            };

            /**
             * Creates a plain object from a FlushResponse message. Also converts values to other types if specified.
             * @function toObject
             * @memberof perfetto.protos.FlushResponse
             * @static
             * @param {perfetto.protos.FlushResponse} message FlushResponse
             * @param {$protobuf.IConversionOptions} [options] Conversion options
             * @returns {Object.<string,*>} Plain object
             */
            FlushResponse.toObject = function toObject() {
                return {};
            };

            /**
             * Converts this FlushResponse to JSON.
             * @function toJSON
             * @memberof perfetto.protos.FlushResponse
             * @instance
             * @returns {Object.<string,*>} JSON object
             */
            FlushResponse.prototype.toJSON = function toJSON() {
                return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
            };

            return FlushResponse;
        })();

        protos.DetachRequest = (function() {

            /**
             * Properties of a DetachRequest.
             * @memberof perfetto.protos
             * @interface IDetachRequest
             * @property {string|null} [key] DetachRequest key
             */

            /**
             * Constructs a new DetachRequest.
             * @memberof perfetto.protos
             * @classdesc Represents a DetachRequest.
             * @implements IDetachRequest
             * @constructor
             * @param {perfetto.protos.IDetachRequest=} [properties] Properties to set
             */
            function DetachRequest(properties) {
                if (properties)
                    for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                        if (properties[keys[i]] != null)
                            this[keys[i]] = properties[keys[i]];
            }

            /**
             * DetachRequest key.
             * @member {string} key
             * @memberof perfetto.protos.DetachRequest
             * @instance
             */
            DetachRequest.prototype.key = "";

            /**
             * Creates a new DetachRequest instance using the specified properties.
             * @function create
             * @memberof perfetto.protos.DetachRequest
             * @static
             * @param {perfetto.protos.IDetachRequest=} [properties] Properties to set
             * @returns {perfetto.protos.DetachRequest} DetachRequest instance
             */
            DetachRequest.create = function create(properties) {
                return new DetachRequest(properties);
            };

            /**
             * Encodes the specified DetachRequest message. Does not implicitly {@link perfetto.protos.DetachRequest.verify|verify} messages.
             * @function encode
             * @memberof perfetto.protos.DetachRequest
             * @static
             * @param {perfetto.protos.IDetachRequest} message DetachRequest message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            DetachRequest.encode = function encode(message, writer) {
                if (!writer)
                    writer = $Writer.create();
                if (message.key != null && Object.hasOwnProperty.call(message, "key"))
                    writer.uint32(/* id 1, wireType 2 =*/10).string(message.key);
                return writer;
            };

            /**
             * Encodes the specified DetachRequest message, length delimited. Does not implicitly {@link perfetto.protos.DetachRequest.verify|verify} messages.
             * @function encodeDelimited
             * @memberof perfetto.protos.DetachRequest
             * @static
             * @param {perfetto.protos.IDetachRequest} message DetachRequest message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            DetachRequest.encodeDelimited = function encodeDelimited(message, writer) {
                return this.encode(message, writer).ldelim();
            };

            /**
             * Decodes a DetachRequest message from the specified reader or buffer.
             * @function decode
             * @memberof perfetto.protos.DetachRequest
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @param {number} [length] Message length if known beforehand
             * @returns {perfetto.protos.DetachRequest} DetachRequest
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            DetachRequest.decode = function decode(reader, length) {
                if (!(reader instanceof $Reader))
                    reader = $Reader.create(reader);
                var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.DetachRequest();
                while (reader.pos < end) {
                    var tag = reader.uint32();
                    switch (tag >>> 3) {
                    case 1:
                        message.key = reader.string();
                        break;
                    default:
                        reader.skipType(tag & 7);
                        break;
                    }
                }
                return message;
            };

            /**
             * Decodes a DetachRequest message from the specified reader or buffer, length delimited.
             * @function decodeDelimited
             * @memberof perfetto.protos.DetachRequest
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @returns {perfetto.protos.DetachRequest} DetachRequest
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            DetachRequest.decodeDelimited = function decodeDelimited(reader) {
                if (!(reader instanceof $Reader))
                    reader = new $Reader(reader);
                return this.decode(reader, reader.uint32());
            };

            /**
             * Verifies a DetachRequest message.
             * @function verify
             * @memberof perfetto.protos.DetachRequest
             * @static
             * @param {Object.<string,*>} message Plain object to verify
             * @returns {string|null} `null` if valid, otherwise the reason why it is not
             */
            DetachRequest.verify = function verify(message) {
                if (typeof message !== "object" || message === null)
                    return "object expected";
                if (message.key != null && message.hasOwnProperty("key"))
                    if (!$util.isString(message.key))
                        return "key: string expected";
                return null;
            };

            /**
             * Creates a DetachRequest message from a plain object. Also converts values to their respective internal types.
             * @function fromObject
             * @memberof perfetto.protos.DetachRequest
             * @static
             * @param {Object.<string,*>} object Plain object
             * @returns {perfetto.protos.DetachRequest} DetachRequest
             */
            DetachRequest.fromObject = function fromObject(object) {
                if (object instanceof $root.perfetto.protos.DetachRequest)
                    return object;
                var message = new $root.perfetto.protos.DetachRequest();
                if (object.key != null)
                    message.key = String(object.key);
                return message;
            };

            /**
             * Creates a plain object from a DetachRequest message. Also converts values to other types if specified.
             * @function toObject
             * @memberof perfetto.protos.DetachRequest
             * @static
             * @param {perfetto.protos.DetachRequest} message DetachRequest
             * @param {$protobuf.IConversionOptions} [options] Conversion options
             * @returns {Object.<string,*>} Plain object
             */
            DetachRequest.toObject = function toObject(message, options) {
                if (!options)
                    options = {};
                var object = {};
                if (options.defaults)
                    object.key = "";
                if (message.key != null && message.hasOwnProperty("key"))
                    object.key = message.key;
                return object;
            };

            /**
             * Converts this DetachRequest to JSON.
             * @function toJSON
             * @memberof perfetto.protos.DetachRequest
             * @instance
             * @returns {Object.<string,*>} JSON object
             */
            DetachRequest.prototype.toJSON = function toJSON() {
                return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
            };

            return DetachRequest;
        })();

        protos.DetachResponse = (function() {

            /**
             * Properties of a DetachResponse.
             * @memberof perfetto.protos
             * @interface IDetachResponse
             */

            /**
             * Constructs a new DetachResponse.
             * @memberof perfetto.protos
             * @classdesc Represents a DetachResponse.
             * @implements IDetachResponse
             * @constructor
             * @param {perfetto.protos.IDetachResponse=} [properties] Properties to set
             */
            function DetachResponse(properties) {
                if (properties)
                    for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                        if (properties[keys[i]] != null)
                            this[keys[i]] = properties[keys[i]];
            }

            /**
             * Creates a new DetachResponse instance using the specified properties.
             * @function create
             * @memberof perfetto.protos.DetachResponse
             * @static
             * @param {perfetto.protos.IDetachResponse=} [properties] Properties to set
             * @returns {perfetto.protos.DetachResponse} DetachResponse instance
             */
            DetachResponse.create = function create(properties) {
                return new DetachResponse(properties);
            };

            /**
             * Encodes the specified DetachResponse message. Does not implicitly {@link perfetto.protos.DetachResponse.verify|verify} messages.
             * @function encode
             * @memberof perfetto.protos.DetachResponse
             * @static
             * @param {perfetto.protos.IDetachResponse} message DetachResponse message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            DetachResponse.encode = function encode(message, writer) {
                if (!writer)
                    writer = $Writer.create();
                return writer;
            };

            /**
             * Encodes the specified DetachResponse message, length delimited. Does not implicitly {@link perfetto.protos.DetachResponse.verify|verify} messages.
             * @function encodeDelimited
             * @memberof perfetto.protos.DetachResponse
             * @static
             * @param {perfetto.protos.IDetachResponse} message DetachResponse message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            DetachResponse.encodeDelimited = function encodeDelimited(message, writer) {
                return this.encode(message, writer).ldelim();
            };

            /**
             * Decodes a DetachResponse message from the specified reader or buffer.
             * @function decode
             * @memberof perfetto.protos.DetachResponse
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @param {number} [length] Message length if known beforehand
             * @returns {perfetto.protos.DetachResponse} DetachResponse
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            DetachResponse.decode = function decode(reader, length) {
                if (!(reader instanceof $Reader))
                    reader = $Reader.create(reader);
                var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.DetachResponse();
                while (reader.pos < end) {
                    var tag = reader.uint32();
                    switch (tag >>> 3) {
                    default:
                        reader.skipType(tag & 7);
                        break;
                    }
                }
                return message;
            };

            /**
             * Decodes a DetachResponse message from the specified reader or buffer, length delimited.
             * @function decodeDelimited
             * @memberof perfetto.protos.DetachResponse
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @returns {perfetto.protos.DetachResponse} DetachResponse
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            DetachResponse.decodeDelimited = function decodeDelimited(reader) {
                if (!(reader instanceof $Reader))
                    reader = new $Reader(reader);
                return this.decode(reader, reader.uint32());
            };

            /**
             * Verifies a DetachResponse message.
             * @function verify
             * @memberof perfetto.protos.DetachResponse
             * @static
             * @param {Object.<string,*>} message Plain object to verify
             * @returns {string|null} `null` if valid, otherwise the reason why it is not
             */
            DetachResponse.verify = function verify(message) {
                if (typeof message !== "object" || message === null)
                    return "object expected";
                return null;
            };

            /**
             * Creates a DetachResponse message from a plain object. Also converts values to their respective internal types.
             * @function fromObject
             * @memberof perfetto.protos.DetachResponse
             * @static
             * @param {Object.<string,*>} object Plain object
             * @returns {perfetto.protos.DetachResponse} DetachResponse
             */
            DetachResponse.fromObject = function fromObject(object) {
                if (object instanceof $root.perfetto.protos.DetachResponse)
                    return object;
                return new $root.perfetto.protos.DetachResponse();
            };

            /**
             * Creates a plain object from a DetachResponse message. Also converts values to other types if specified.
             * @function toObject
             * @memberof perfetto.protos.DetachResponse
             * @static
             * @param {perfetto.protos.DetachResponse} message DetachResponse
             * @param {$protobuf.IConversionOptions} [options] Conversion options
             * @returns {Object.<string,*>} Plain object
             */
            DetachResponse.toObject = function toObject() {
                return {};
            };

            /**
             * Converts this DetachResponse to JSON.
             * @function toJSON
             * @memberof perfetto.protos.DetachResponse
             * @instance
             * @returns {Object.<string,*>} JSON object
             */
            DetachResponse.prototype.toJSON = function toJSON() {
                return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
            };

            return DetachResponse;
        })();

        protos.AttachRequest = (function() {

            /**
             * Properties of an AttachRequest.
             * @memberof perfetto.protos
             * @interface IAttachRequest
             * @property {string|null} [key] AttachRequest key
             */

            /**
             * Constructs a new AttachRequest.
             * @memberof perfetto.protos
             * @classdesc Represents an AttachRequest.
             * @implements IAttachRequest
             * @constructor
             * @param {perfetto.protos.IAttachRequest=} [properties] Properties to set
             */
            function AttachRequest(properties) {
                if (properties)
                    for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                        if (properties[keys[i]] != null)
                            this[keys[i]] = properties[keys[i]];
            }

            /**
             * AttachRequest key.
             * @member {string} key
             * @memberof perfetto.protos.AttachRequest
             * @instance
             */
            AttachRequest.prototype.key = "";

            /**
             * Creates a new AttachRequest instance using the specified properties.
             * @function create
             * @memberof perfetto.protos.AttachRequest
             * @static
             * @param {perfetto.protos.IAttachRequest=} [properties] Properties to set
             * @returns {perfetto.protos.AttachRequest} AttachRequest instance
             */
            AttachRequest.create = function create(properties) {
                return new AttachRequest(properties);
            };

            /**
             * Encodes the specified AttachRequest message. Does not implicitly {@link perfetto.protos.AttachRequest.verify|verify} messages.
             * @function encode
             * @memberof perfetto.protos.AttachRequest
             * @static
             * @param {perfetto.protos.IAttachRequest} message AttachRequest message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            AttachRequest.encode = function encode(message, writer) {
                if (!writer)
                    writer = $Writer.create();
                if (message.key != null && Object.hasOwnProperty.call(message, "key"))
                    writer.uint32(/* id 1, wireType 2 =*/10).string(message.key);
                return writer;
            };

            /**
             * Encodes the specified AttachRequest message, length delimited. Does not implicitly {@link perfetto.protos.AttachRequest.verify|verify} messages.
             * @function encodeDelimited
             * @memberof perfetto.protos.AttachRequest
             * @static
             * @param {perfetto.protos.IAttachRequest} message AttachRequest message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            AttachRequest.encodeDelimited = function encodeDelimited(message, writer) {
                return this.encode(message, writer).ldelim();
            };

            /**
             * Decodes an AttachRequest message from the specified reader or buffer.
             * @function decode
             * @memberof perfetto.protos.AttachRequest
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @param {number} [length] Message length if known beforehand
             * @returns {perfetto.protos.AttachRequest} AttachRequest
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            AttachRequest.decode = function decode(reader, length) {
                if (!(reader instanceof $Reader))
                    reader = $Reader.create(reader);
                var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.AttachRequest();
                while (reader.pos < end) {
                    var tag = reader.uint32();
                    switch (tag >>> 3) {
                    case 1:
                        message.key = reader.string();
                        break;
                    default:
                        reader.skipType(tag & 7);
                        break;
                    }
                }
                return message;
            };

            /**
             * Decodes an AttachRequest message from the specified reader or buffer, length delimited.
             * @function decodeDelimited
             * @memberof perfetto.protos.AttachRequest
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @returns {perfetto.protos.AttachRequest} AttachRequest
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            AttachRequest.decodeDelimited = function decodeDelimited(reader) {
                if (!(reader instanceof $Reader))
                    reader = new $Reader(reader);
                return this.decode(reader, reader.uint32());
            };

            /**
             * Verifies an AttachRequest message.
             * @function verify
             * @memberof perfetto.protos.AttachRequest
             * @static
             * @param {Object.<string,*>} message Plain object to verify
             * @returns {string|null} `null` if valid, otherwise the reason why it is not
             */
            AttachRequest.verify = function verify(message) {
                if (typeof message !== "object" || message === null)
                    return "object expected";
                if (message.key != null && message.hasOwnProperty("key"))
                    if (!$util.isString(message.key))
                        return "key: string expected";
                return null;
            };

            /**
             * Creates an AttachRequest message from a plain object. Also converts values to their respective internal types.
             * @function fromObject
             * @memberof perfetto.protos.AttachRequest
             * @static
             * @param {Object.<string,*>} object Plain object
             * @returns {perfetto.protos.AttachRequest} AttachRequest
             */
            AttachRequest.fromObject = function fromObject(object) {
                if (object instanceof $root.perfetto.protos.AttachRequest)
                    return object;
                var message = new $root.perfetto.protos.AttachRequest();
                if (object.key != null)
                    message.key = String(object.key);
                return message;
            };

            /**
             * Creates a plain object from an AttachRequest message. Also converts values to other types if specified.
             * @function toObject
             * @memberof perfetto.protos.AttachRequest
             * @static
             * @param {perfetto.protos.AttachRequest} message AttachRequest
             * @param {$protobuf.IConversionOptions} [options] Conversion options
             * @returns {Object.<string,*>} Plain object
             */
            AttachRequest.toObject = function toObject(message, options) {
                if (!options)
                    options = {};
                var object = {};
                if (options.defaults)
                    object.key = "";
                if (message.key != null && message.hasOwnProperty("key"))
                    object.key = message.key;
                return object;
            };

            /**
             * Converts this AttachRequest to JSON.
             * @function toJSON
             * @memberof perfetto.protos.AttachRequest
             * @instance
             * @returns {Object.<string,*>} JSON object
             */
            AttachRequest.prototype.toJSON = function toJSON() {
                return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
            };

            return AttachRequest;
        })();

        protos.AttachResponse = (function() {

            /**
             * Properties of an AttachResponse.
             * @memberof perfetto.protos
             * @interface IAttachResponse
             * @property {perfetto.protos.ITraceConfig|null} [traceConfig] AttachResponse traceConfig
             */

            /**
             * Constructs a new AttachResponse.
             * @memberof perfetto.protos
             * @classdesc Represents an AttachResponse.
             * @implements IAttachResponse
             * @constructor
             * @param {perfetto.protos.IAttachResponse=} [properties] Properties to set
             */
            function AttachResponse(properties) {
                if (properties)
                    for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                        if (properties[keys[i]] != null)
                            this[keys[i]] = properties[keys[i]];
            }

            /**
             * AttachResponse traceConfig.
             * @member {perfetto.protos.ITraceConfig|null|undefined} traceConfig
             * @memberof perfetto.protos.AttachResponse
             * @instance
             */
            AttachResponse.prototype.traceConfig = null;

            /**
             * Creates a new AttachResponse instance using the specified properties.
             * @function create
             * @memberof perfetto.protos.AttachResponse
             * @static
             * @param {perfetto.protos.IAttachResponse=} [properties] Properties to set
             * @returns {perfetto.protos.AttachResponse} AttachResponse instance
             */
            AttachResponse.create = function create(properties) {
                return new AttachResponse(properties);
            };

            /**
             * Encodes the specified AttachResponse message. Does not implicitly {@link perfetto.protos.AttachResponse.verify|verify} messages.
             * @function encode
             * @memberof perfetto.protos.AttachResponse
             * @static
             * @param {perfetto.protos.IAttachResponse} message AttachResponse message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            AttachResponse.encode = function encode(message, writer) {
                if (!writer)
                    writer = $Writer.create();
                if (message.traceConfig != null && Object.hasOwnProperty.call(message, "traceConfig"))
                    $root.perfetto.protos.TraceConfig.encode(message.traceConfig, writer.uint32(/* id 1, wireType 2 =*/10).fork()).ldelim();
                return writer;
            };

            /**
             * Encodes the specified AttachResponse message, length delimited. Does not implicitly {@link perfetto.protos.AttachResponse.verify|verify} messages.
             * @function encodeDelimited
             * @memberof perfetto.protos.AttachResponse
             * @static
             * @param {perfetto.protos.IAttachResponse} message AttachResponse message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            AttachResponse.encodeDelimited = function encodeDelimited(message, writer) {
                return this.encode(message, writer).ldelim();
            };

            /**
             * Decodes an AttachResponse message from the specified reader or buffer.
             * @function decode
             * @memberof perfetto.protos.AttachResponse
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @param {number} [length] Message length if known beforehand
             * @returns {perfetto.protos.AttachResponse} AttachResponse
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            AttachResponse.decode = function decode(reader, length) {
                if (!(reader instanceof $Reader))
                    reader = $Reader.create(reader);
                var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.AttachResponse();
                while (reader.pos < end) {
                    var tag = reader.uint32();
                    switch (tag >>> 3) {
                    case 1:
                        message.traceConfig = $root.perfetto.protos.TraceConfig.decode(reader, reader.uint32());
                        break;
                    default:
                        reader.skipType(tag & 7);
                        break;
                    }
                }
                return message;
            };

            /**
             * Decodes an AttachResponse message from the specified reader or buffer, length delimited.
             * @function decodeDelimited
             * @memberof perfetto.protos.AttachResponse
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @returns {perfetto.protos.AttachResponse} AttachResponse
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            AttachResponse.decodeDelimited = function decodeDelimited(reader) {
                if (!(reader instanceof $Reader))
                    reader = new $Reader(reader);
                return this.decode(reader, reader.uint32());
            };

            /**
             * Verifies an AttachResponse message.
             * @function verify
             * @memberof perfetto.protos.AttachResponse
             * @static
             * @param {Object.<string,*>} message Plain object to verify
             * @returns {string|null} `null` if valid, otherwise the reason why it is not
             */
            AttachResponse.verify = function verify(message) {
                if (typeof message !== "object" || message === null)
                    return "object expected";
                if (message.traceConfig != null && message.hasOwnProperty("traceConfig")) {
                    var error = $root.perfetto.protos.TraceConfig.verify(message.traceConfig);
                    if (error)
                        return "traceConfig." + error;
                }
                return null;
            };

            /**
             * Creates an AttachResponse message from a plain object. Also converts values to their respective internal types.
             * @function fromObject
             * @memberof perfetto.protos.AttachResponse
             * @static
             * @param {Object.<string,*>} object Plain object
             * @returns {perfetto.protos.AttachResponse} AttachResponse
             */
            AttachResponse.fromObject = function fromObject(object) {
                if (object instanceof $root.perfetto.protos.AttachResponse)
                    return object;
                var message = new $root.perfetto.protos.AttachResponse();
                if (object.traceConfig != null) {
                    if (typeof object.traceConfig !== "object")
                        throw TypeError(".perfetto.protos.AttachResponse.traceConfig: object expected");
                    message.traceConfig = $root.perfetto.protos.TraceConfig.fromObject(object.traceConfig);
                }
                return message;
            };

            /**
             * Creates a plain object from an AttachResponse message. Also converts values to other types if specified.
             * @function toObject
             * @memberof perfetto.protos.AttachResponse
             * @static
             * @param {perfetto.protos.AttachResponse} message AttachResponse
             * @param {$protobuf.IConversionOptions} [options] Conversion options
             * @returns {Object.<string,*>} Plain object
             */
            AttachResponse.toObject = function toObject(message, options) {
                if (!options)
                    options = {};
                var object = {};
                if (options.defaults)
                    object.traceConfig = null;
                if (message.traceConfig != null && message.hasOwnProperty("traceConfig"))
                    object.traceConfig = $root.perfetto.protos.TraceConfig.toObject(message.traceConfig, options);
                return object;
            };

            /**
             * Converts this AttachResponse to JSON.
             * @function toJSON
             * @memberof perfetto.protos.AttachResponse
             * @instance
             * @returns {Object.<string,*>} JSON object
             */
            AttachResponse.prototype.toJSON = function toJSON() {
                return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
            };

            return AttachResponse;
        })();

        protos.GetTraceStatsRequest = (function() {

            /**
             * Properties of a GetTraceStatsRequest.
             * @memberof perfetto.protos
             * @interface IGetTraceStatsRequest
             */

            /**
             * Constructs a new GetTraceStatsRequest.
             * @memberof perfetto.protos
             * @classdesc Represents a GetTraceStatsRequest.
             * @implements IGetTraceStatsRequest
             * @constructor
             * @param {perfetto.protos.IGetTraceStatsRequest=} [properties] Properties to set
             */
            function GetTraceStatsRequest(properties) {
                if (properties)
                    for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                        if (properties[keys[i]] != null)
                            this[keys[i]] = properties[keys[i]];
            }

            /**
             * Creates a new GetTraceStatsRequest instance using the specified properties.
             * @function create
             * @memberof perfetto.protos.GetTraceStatsRequest
             * @static
             * @param {perfetto.protos.IGetTraceStatsRequest=} [properties] Properties to set
             * @returns {perfetto.protos.GetTraceStatsRequest} GetTraceStatsRequest instance
             */
            GetTraceStatsRequest.create = function create(properties) {
                return new GetTraceStatsRequest(properties);
            };

            /**
             * Encodes the specified GetTraceStatsRequest message. Does not implicitly {@link perfetto.protos.GetTraceStatsRequest.verify|verify} messages.
             * @function encode
             * @memberof perfetto.protos.GetTraceStatsRequest
             * @static
             * @param {perfetto.protos.IGetTraceStatsRequest} message GetTraceStatsRequest message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            GetTraceStatsRequest.encode = function encode(message, writer) {
                if (!writer)
                    writer = $Writer.create();
                return writer;
            };

            /**
             * Encodes the specified GetTraceStatsRequest message, length delimited. Does not implicitly {@link perfetto.protos.GetTraceStatsRequest.verify|verify} messages.
             * @function encodeDelimited
             * @memberof perfetto.protos.GetTraceStatsRequest
             * @static
             * @param {perfetto.protos.IGetTraceStatsRequest} message GetTraceStatsRequest message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            GetTraceStatsRequest.encodeDelimited = function encodeDelimited(message, writer) {
                return this.encode(message, writer).ldelim();
            };

            /**
             * Decodes a GetTraceStatsRequest message from the specified reader or buffer.
             * @function decode
             * @memberof perfetto.protos.GetTraceStatsRequest
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @param {number} [length] Message length if known beforehand
             * @returns {perfetto.protos.GetTraceStatsRequest} GetTraceStatsRequest
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            GetTraceStatsRequest.decode = function decode(reader, length) {
                if (!(reader instanceof $Reader))
                    reader = $Reader.create(reader);
                var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.GetTraceStatsRequest();
                while (reader.pos < end) {
                    var tag = reader.uint32();
                    switch (tag >>> 3) {
                    default:
                        reader.skipType(tag & 7);
                        break;
                    }
                }
                return message;
            };

            /**
             * Decodes a GetTraceStatsRequest message from the specified reader or buffer, length delimited.
             * @function decodeDelimited
             * @memberof perfetto.protos.GetTraceStatsRequest
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @returns {perfetto.protos.GetTraceStatsRequest} GetTraceStatsRequest
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            GetTraceStatsRequest.decodeDelimited = function decodeDelimited(reader) {
                if (!(reader instanceof $Reader))
                    reader = new $Reader(reader);
                return this.decode(reader, reader.uint32());
            };

            /**
             * Verifies a GetTraceStatsRequest message.
             * @function verify
             * @memberof perfetto.protos.GetTraceStatsRequest
             * @static
             * @param {Object.<string,*>} message Plain object to verify
             * @returns {string|null} `null` if valid, otherwise the reason why it is not
             */
            GetTraceStatsRequest.verify = function verify(message) {
                if (typeof message !== "object" || message === null)
                    return "object expected";
                return null;
            };

            /**
             * Creates a GetTraceStatsRequest message from a plain object. Also converts values to their respective internal types.
             * @function fromObject
             * @memberof perfetto.protos.GetTraceStatsRequest
             * @static
             * @param {Object.<string,*>} object Plain object
             * @returns {perfetto.protos.GetTraceStatsRequest} GetTraceStatsRequest
             */
            GetTraceStatsRequest.fromObject = function fromObject(object) {
                if (object instanceof $root.perfetto.protos.GetTraceStatsRequest)
                    return object;
                return new $root.perfetto.protos.GetTraceStatsRequest();
            };

            /**
             * Creates a plain object from a GetTraceStatsRequest message. Also converts values to other types if specified.
             * @function toObject
             * @memberof perfetto.protos.GetTraceStatsRequest
             * @static
             * @param {perfetto.protos.GetTraceStatsRequest} message GetTraceStatsRequest
             * @param {$protobuf.IConversionOptions} [options] Conversion options
             * @returns {Object.<string,*>} Plain object
             */
            GetTraceStatsRequest.toObject = function toObject() {
                return {};
            };

            /**
             * Converts this GetTraceStatsRequest to JSON.
             * @function toJSON
             * @memberof perfetto.protos.GetTraceStatsRequest
             * @instance
             * @returns {Object.<string,*>} JSON object
             */
            GetTraceStatsRequest.prototype.toJSON = function toJSON() {
                return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
            };

            return GetTraceStatsRequest;
        })();

        protos.GetTraceStatsResponse = (function() {

            /**
             * Properties of a GetTraceStatsResponse.
             * @memberof perfetto.protos
             * @interface IGetTraceStatsResponse
             * @property {perfetto.protos.ITraceStats|null} [traceStats] GetTraceStatsResponse traceStats
             */

            /**
             * Constructs a new GetTraceStatsResponse.
             * @memberof perfetto.protos
             * @classdesc Represents a GetTraceStatsResponse.
             * @implements IGetTraceStatsResponse
             * @constructor
             * @param {perfetto.protos.IGetTraceStatsResponse=} [properties] Properties to set
             */
            function GetTraceStatsResponse(properties) {
                if (properties)
                    for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                        if (properties[keys[i]] != null)
                            this[keys[i]] = properties[keys[i]];
            }

            /**
             * GetTraceStatsResponse traceStats.
             * @member {perfetto.protos.ITraceStats|null|undefined} traceStats
             * @memberof perfetto.protos.GetTraceStatsResponse
             * @instance
             */
            GetTraceStatsResponse.prototype.traceStats = null;

            /**
             * Creates a new GetTraceStatsResponse instance using the specified properties.
             * @function create
             * @memberof perfetto.protos.GetTraceStatsResponse
             * @static
             * @param {perfetto.protos.IGetTraceStatsResponse=} [properties] Properties to set
             * @returns {perfetto.protos.GetTraceStatsResponse} GetTraceStatsResponse instance
             */
            GetTraceStatsResponse.create = function create(properties) {
                return new GetTraceStatsResponse(properties);
            };

            /**
             * Encodes the specified GetTraceStatsResponse message. Does not implicitly {@link perfetto.protos.GetTraceStatsResponse.verify|verify} messages.
             * @function encode
             * @memberof perfetto.protos.GetTraceStatsResponse
             * @static
             * @param {perfetto.protos.IGetTraceStatsResponse} message GetTraceStatsResponse message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            GetTraceStatsResponse.encode = function encode(message, writer) {
                if (!writer)
                    writer = $Writer.create();
                if (message.traceStats != null && Object.hasOwnProperty.call(message, "traceStats"))
                    $root.perfetto.protos.TraceStats.encode(message.traceStats, writer.uint32(/* id 1, wireType 2 =*/10).fork()).ldelim();
                return writer;
            };

            /**
             * Encodes the specified GetTraceStatsResponse message, length delimited. Does not implicitly {@link perfetto.protos.GetTraceStatsResponse.verify|verify} messages.
             * @function encodeDelimited
             * @memberof perfetto.protos.GetTraceStatsResponse
             * @static
             * @param {perfetto.protos.IGetTraceStatsResponse} message GetTraceStatsResponse message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            GetTraceStatsResponse.encodeDelimited = function encodeDelimited(message, writer) {
                return this.encode(message, writer).ldelim();
            };

            /**
             * Decodes a GetTraceStatsResponse message from the specified reader or buffer.
             * @function decode
             * @memberof perfetto.protos.GetTraceStatsResponse
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @param {number} [length] Message length if known beforehand
             * @returns {perfetto.protos.GetTraceStatsResponse} GetTraceStatsResponse
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            GetTraceStatsResponse.decode = function decode(reader, length) {
                if (!(reader instanceof $Reader))
                    reader = $Reader.create(reader);
                var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.GetTraceStatsResponse();
                while (reader.pos < end) {
                    var tag = reader.uint32();
                    switch (tag >>> 3) {
                    case 1:
                        message.traceStats = $root.perfetto.protos.TraceStats.decode(reader, reader.uint32());
                        break;
                    default:
                        reader.skipType(tag & 7);
                        break;
                    }
                }
                return message;
            };

            /**
             * Decodes a GetTraceStatsResponse message from the specified reader or buffer, length delimited.
             * @function decodeDelimited
             * @memberof perfetto.protos.GetTraceStatsResponse
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @returns {perfetto.protos.GetTraceStatsResponse} GetTraceStatsResponse
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            GetTraceStatsResponse.decodeDelimited = function decodeDelimited(reader) {
                if (!(reader instanceof $Reader))
                    reader = new $Reader(reader);
                return this.decode(reader, reader.uint32());
            };

            /**
             * Verifies a GetTraceStatsResponse message.
             * @function verify
             * @memberof perfetto.protos.GetTraceStatsResponse
             * @static
             * @param {Object.<string,*>} message Plain object to verify
             * @returns {string|null} `null` if valid, otherwise the reason why it is not
             */
            GetTraceStatsResponse.verify = function verify(message) {
                if (typeof message !== "object" || message === null)
                    return "object expected";
                if (message.traceStats != null && message.hasOwnProperty("traceStats")) {
                    var error = $root.perfetto.protos.TraceStats.verify(message.traceStats);
                    if (error)
                        return "traceStats." + error;
                }
                return null;
            };

            /**
             * Creates a GetTraceStatsResponse message from a plain object. Also converts values to their respective internal types.
             * @function fromObject
             * @memberof perfetto.protos.GetTraceStatsResponse
             * @static
             * @param {Object.<string,*>} object Plain object
             * @returns {perfetto.protos.GetTraceStatsResponse} GetTraceStatsResponse
             */
            GetTraceStatsResponse.fromObject = function fromObject(object) {
                if (object instanceof $root.perfetto.protos.GetTraceStatsResponse)
                    return object;
                var message = new $root.perfetto.protos.GetTraceStatsResponse();
                if (object.traceStats != null) {
                    if (typeof object.traceStats !== "object")
                        throw TypeError(".perfetto.protos.GetTraceStatsResponse.traceStats: object expected");
                    message.traceStats = $root.perfetto.protos.TraceStats.fromObject(object.traceStats);
                }
                return message;
            };

            /**
             * Creates a plain object from a GetTraceStatsResponse message. Also converts values to other types if specified.
             * @function toObject
             * @memberof perfetto.protos.GetTraceStatsResponse
             * @static
             * @param {perfetto.protos.GetTraceStatsResponse} message GetTraceStatsResponse
             * @param {$protobuf.IConversionOptions} [options] Conversion options
             * @returns {Object.<string,*>} Plain object
             */
            GetTraceStatsResponse.toObject = function toObject(message, options) {
                if (!options)
                    options = {};
                var object = {};
                if (options.defaults)
                    object.traceStats = null;
                if (message.traceStats != null && message.hasOwnProperty("traceStats"))
                    object.traceStats = $root.perfetto.protos.TraceStats.toObject(message.traceStats, options);
                return object;
            };

            /**
             * Converts this GetTraceStatsResponse to JSON.
             * @function toJSON
             * @memberof perfetto.protos.GetTraceStatsResponse
             * @instance
             * @returns {Object.<string,*>} JSON object
             */
            GetTraceStatsResponse.prototype.toJSON = function toJSON() {
                return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
            };

            return GetTraceStatsResponse;
        })();

        protos.ObserveEventsRequest = (function() {

            /**
             * Properties of an ObserveEventsRequest.
             * @memberof perfetto.protos
             * @interface IObserveEventsRequest
             * @property {Array.<perfetto.protos.ObservableEvents.Type>|null} [eventsToObserve] ObserveEventsRequest eventsToObserve
             */

            /**
             * Constructs a new ObserveEventsRequest.
             * @memberof perfetto.protos
             * @classdesc Represents an ObserveEventsRequest.
             * @implements IObserveEventsRequest
             * @constructor
             * @param {perfetto.protos.IObserveEventsRequest=} [properties] Properties to set
             */
            function ObserveEventsRequest(properties) {
                this.eventsToObserve = [];
                if (properties)
                    for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                        if (properties[keys[i]] != null)
                            this[keys[i]] = properties[keys[i]];
            }

            /**
             * ObserveEventsRequest eventsToObserve.
             * @member {Array.<perfetto.protos.ObservableEvents.Type>} eventsToObserve
             * @memberof perfetto.protos.ObserveEventsRequest
             * @instance
             */
            ObserveEventsRequest.prototype.eventsToObserve = $util.emptyArray;

            /**
             * Creates a new ObserveEventsRequest instance using the specified properties.
             * @function create
             * @memberof perfetto.protos.ObserveEventsRequest
             * @static
             * @param {perfetto.protos.IObserveEventsRequest=} [properties] Properties to set
             * @returns {perfetto.protos.ObserveEventsRequest} ObserveEventsRequest instance
             */
            ObserveEventsRequest.create = function create(properties) {
                return new ObserveEventsRequest(properties);
            };

            /**
             * Encodes the specified ObserveEventsRequest message. Does not implicitly {@link perfetto.protos.ObserveEventsRequest.verify|verify} messages.
             * @function encode
             * @memberof perfetto.protos.ObserveEventsRequest
             * @static
             * @param {perfetto.protos.IObserveEventsRequest} message ObserveEventsRequest message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            ObserveEventsRequest.encode = function encode(message, writer) {
                if (!writer)
                    writer = $Writer.create();
                if (message.eventsToObserve != null && message.eventsToObserve.length)
                    for (var i = 0; i < message.eventsToObserve.length; ++i)
                        writer.uint32(/* id 1, wireType 0 =*/8).int32(message.eventsToObserve[i]);
                return writer;
            };

            /**
             * Encodes the specified ObserveEventsRequest message, length delimited. Does not implicitly {@link perfetto.protos.ObserveEventsRequest.verify|verify} messages.
             * @function encodeDelimited
             * @memberof perfetto.protos.ObserveEventsRequest
             * @static
             * @param {perfetto.protos.IObserveEventsRequest} message ObserveEventsRequest message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            ObserveEventsRequest.encodeDelimited = function encodeDelimited(message, writer) {
                return this.encode(message, writer).ldelim();
            };

            /**
             * Decodes an ObserveEventsRequest message from the specified reader or buffer.
             * @function decode
             * @memberof perfetto.protos.ObserveEventsRequest
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @param {number} [length] Message length if known beforehand
             * @returns {perfetto.protos.ObserveEventsRequest} ObserveEventsRequest
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            ObserveEventsRequest.decode = function decode(reader, length) {
                if (!(reader instanceof $Reader))
                    reader = $Reader.create(reader);
                var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.ObserveEventsRequest();
                while (reader.pos < end) {
                    var tag = reader.uint32();
                    switch (tag >>> 3) {
                    case 1:
                        if (!(message.eventsToObserve && message.eventsToObserve.length))
                            message.eventsToObserve = [];
                        if ((tag & 7) === 2) {
                            var end2 = reader.uint32() + reader.pos;
                            while (reader.pos < end2)
                                message.eventsToObserve.push(reader.int32());
                        } else
                            message.eventsToObserve.push(reader.int32());
                        break;
                    default:
                        reader.skipType(tag & 7);
                        break;
                    }
                }
                return message;
            };

            /**
             * Decodes an ObserveEventsRequest message from the specified reader or buffer, length delimited.
             * @function decodeDelimited
             * @memberof perfetto.protos.ObserveEventsRequest
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @returns {perfetto.protos.ObserveEventsRequest} ObserveEventsRequest
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            ObserveEventsRequest.decodeDelimited = function decodeDelimited(reader) {
                if (!(reader instanceof $Reader))
                    reader = new $Reader(reader);
                return this.decode(reader, reader.uint32());
            };

            /**
             * Verifies an ObserveEventsRequest message.
             * @function verify
             * @memberof perfetto.protos.ObserveEventsRequest
             * @static
             * @param {Object.<string,*>} message Plain object to verify
             * @returns {string|null} `null` if valid, otherwise the reason why it is not
             */
            ObserveEventsRequest.verify = function verify(message) {
                if (typeof message !== "object" || message === null)
                    return "object expected";
                if (message.eventsToObserve != null && message.hasOwnProperty("eventsToObserve")) {
                    if (!Array.isArray(message.eventsToObserve))
                        return "eventsToObserve: array expected";
                    for (var i = 0; i < message.eventsToObserve.length; ++i)
                        switch (message.eventsToObserve[i]) {
                        default:
                            return "eventsToObserve: enum value[] expected";
                        case 0:
                        case 1:
                        case 2:
                            break;
                        }
                }
                return null;
            };

            /**
             * Creates an ObserveEventsRequest message from a plain object. Also converts values to their respective internal types.
             * @function fromObject
             * @memberof perfetto.protos.ObserveEventsRequest
             * @static
             * @param {Object.<string,*>} object Plain object
             * @returns {perfetto.protos.ObserveEventsRequest} ObserveEventsRequest
             */
            ObserveEventsRequest.fromObject = function fromObject(object) {
                if (object instanceof $root.perfetto.protos.ObserveEventsRequest)
                    return object;
                var message = new $root.perfetto.protos.ObserveEventsRequest();
                if (object.eventsToObserve) {
                    if (!Array.isArray(object.eventsToObserve))
                        throw TypeError(".perfetto.protos.ObserveEventsRequest.eventsToObserve: array expected");
                    message.eventsToObserve = [];
                    for (var i = 0; i < object.eventsToObserve.length; ++i)
                        switch (object.eventsToObserve[i]) {
                        default:
                        case "TYPE_UNSPECIFIED":
                        case 0:
                            message.eventsToObserve[i] = 0;
                            break;
                        case "TYPE_DATA_SOURCES_INSTANCES":
                        case 1:
                            message.eventsToObserve[i] = 1;
                            break;
                        case "TYPE_ALL_DATA_SOURCES_STARTED":
                        case 2:
                            message.eventsToObserve[i] = 2;
                            break;
                        }
                }
                return message;
            };

            /**
             * Creates a plain object from an ObserveEventsRequest message. Also converts values to other types if specified.
             * @function toObject
             * @memberof perfetto.protos.ObserveEventsRequest
             * @static
             * @param {perfetto.protos.ObserveEventsRequest} message ObserveEventsRequest
             * @param {$protobuf.IConversionOptions} [options] Conversion options
             * @returns {Object.<string,*>} Plain object
             */
            ObserveEventsRequest.toObject = function toObject(message, options) {
                if (!options)
                    options = {};
                var object = {};
                if (options.arrays || options.defaults)
                    object.eventsToObserve = [];
                if (message.eventsToObserve && message.eventsToObserve.length) {
                    object.eventsToObserve = [];
                    for (var j = 0; j < message.eventsToObserve.length; ++j)
                        object.eventsToObserve[j] = options.enums === String ? $root.perfetto.protos.ObservableEvents.Type[message.eventsToObserve[j]] : message.eventsToObserve[j];
                }
                return object;
            };

            /**
             * Converts this ObserveEventsRequest to JSON.
             * @function toJSON
             * @memberof perfetto.protos.ObserveEventsRequest
             * @instance
             * @returns {Object.<string,*>} JSON object
             */
            ObserveEventsRequest.prototype.toJSON = function toJSON() {
                return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
            };

            return ObserveEventsRequest;
        })();

        protos.ObserveEventsResponse = (function() {

            /**
             * Properties of an ObserveEventsResponse.
             * @memberof perfetto.protos
             * @interface IObserveEventsResponse
             * @property {perfetto.protos.IObservableEvents|null} [events] ObserveEventsResponse events
             */

            /**
             * Constructs a new ObserveEventsResponse.
             * @memberof perfetto.protos
             * @classdesc Represents an ObserveEventsResponse.
             * @implements IObserveEventsResponse
             * @constructor
             * @param {perfetto.protos.IObserveEventsResponse=} [properties] Properties to set
             */
            function ObserveEventsResponse(properties) {
                if (properties)
                    for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                        if (properties[keys[i]] != null)
                            this[keys[i]] = properties[keys[i]];
            }

            /**
             * ObserveEventsResponse events.
             * @member {perfetto.protos.IObservableEvents|null|undefined} events
             * @memberof perfetto.protos.ObserveEventsResponse
             * @instance
             */
            ObserveEventsResponse.prototype.events = null;

            /**
             * Creates a new ObserveEventsResponse instance using the specified properties.
             * @function create
             * @memberof perfetto.protos.ObserveEventsResponse
             * @static
             * @param {perfetto.protos.IObserveEventsResponse=} [properties] Properties to set
             * @returns {perfetto.protos.ObserveEventsResponse} ObserveEventsResponse instance
             */
            ObserveEventsResponse.create = function create(properties) {
                return new ObserveEventsResponse(properties);
            };

            /**
             * Encodes the specified ObserveEventsResponse message. Does not implicitly {@link perfetto.protos.ObserveEventsResponse.verify|verify} messages.
             * @function encode
             * @memberof perfetto.protos.ObserveEventsResponse
             * @static
             * @param {perfetto.protos.IObserveEventsResponse} message ObserveEventsResponse message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            ObserveEventsResponse.encode = function encode(message, writer) {
                if (!writer)
                    writer = $Writer.create();
                if (message.events != null && Object.hasOwnProperty.call(message, "events"))
                    $root.perfetto.protos.ObservableEvents.encode(message.events, writer.uint32(/* id 1, wireType 2 =*/10).fork()).ldelim();
                return writer;
            };

            /**
             * Encodes the specified ObserveEventsResponse message, length delimited. Does not implicitly {@link perfetto.protos.ObserveEventsResponse.verify|verify} messages.
             * @function encodeDelimited
             * @memberof perfetto.protos.ObserveEventsResponse
             * @static
             * @param {perfetto.protos.IObserveEventsResponse} message ObserveEventsResponse message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            ObserveEventsResponse.encodeDelimited = function encodeDelimited(message, writer) {
                return this.encode(message, writer).ldelim();
            };

            /**
             * Decodes an ObserveEventsResponse message from the specified reader or buffer.
             * @function decode
             * @memberof perfetto.protos.ObserveEventsResponse
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @param {number} [length] Message length if known beforehand
             * @returns {perfetto.protos.ObserveEventsResponse} ObserveEventsResponse
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            ObserveEventsResponse.decode = function decode(reader, length) {
                if (!(reader instanceof $Reader))
                    reader = $Reader.create(reader);
                var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.ObserveEventsResponse();
                while (reader.pos < end) {
                    var tag = reader.uint32();
                    switch (tag >>> 3) {
                    case 1:
                        message.events = $root.perfetto.protos.ObservableEvents.decode(reader, reader.uint32());
                        break;
                    default:
                        reader.skipType(tag & 7);
                        break;
                    }
                }
                return message;
            };

            /**
             * Decodes an ObserveEventsResponse message from the specified reader or buffer, length delimited.
             * @function decodeDelimited
             * @memberof perfetto.protos.ObserveEventsResponse
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @returns {perfetto.protos.ObserveEventsResponse} ObserveEventsResponse
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            ObserveEventsResponse.decodeDelimited = function decodeDelimited(reader) {
                if (!(reader instanceof $Reader))
                    reader = new $Reader(reader);
                return this.decode(reader, reader.uint32());
            };

            /**
             * Verifies an ObserveEventsResponse message.
             * @function verify
             * @memberof perfetto.protos.ObserveEventsResponse
             * @static
             * @param {Object.<string,*>} message Plain object to verify
             * @returns {string|null} `null` if valid, otherwise the reason why it is not
             */
            ObserveEventsResponse.verify = function verify(message) {
                if (typeof message !== "object" || message === null)
                    return "object expected";
                if (message.events != null && message.hasOwnProperty("events")) {
                    var error = $root.perfetto.protos.ObservableEvents.verify(message.events);
                    if (error)
                        return "events." + error;
                }
                return null;
            };

            /**
             * Creates an ObserveEventsResponse message from a plain object. Also converts values to their respective internal types.
             * @function fromObject
             * @memberof perfetto.protos.ObserveEventsResponse
             * @static
             * @param {Object.<string,*>} object Plain object
             * @returns {perfetto.protos.ObserveEventsResponse} ObserveEventsResponse
             */
            ObserveEventsResponse.fromObject = function fromObject(object) {
                if (object instanceof $root.perfetto.protos.ObserveEventsResponse)
                    return object;
                var message = new $root.perfetto.protos.ObserveEventsResponse();
                if (object.events != null) {
                    if (typeof object.events !== "object")
                        throw TypeError(".perfetto.protos.ObserveEventsResponse.events: object expected");
                    message.events = $root.perfetto.protos.ObservableEvents.fromObject(object.events);
                }
                return message;
            };

            /**
             * Creates a plain object from an ObserveEventsResponse message. Also converts values to other types if specified.
             * @function toObject
             * @memberof perfetto.protos.ObserveEventsResponse
             * @static
             * @param {perfetto.protos.ObserveEventsResponse} message ObserveEventsResponse
             * @param {$protobuf.IConversionOptions} [options] Conversion options
             * @returns {Object.<string,*>} Plain object
             */
            ObserveEventsResponse.toObject = function toObject(message, options) {
                if (!options)
                    options = {};
                var object = {};
                if (options.defaults)
                    object.events = null;
                if (message.events != null && message.hasOwnProperty("events"))
                    object.events = $root.perfetto.protos.ObservableEvents.toObject(message.events, options);
                return object;
            };

            /**
             * Converts this ObserveEventsResponse to JSON.
             * @function toJSON
             * @memberof perfetto.protos.ObserveEventsResponse
             * @instance
             * @returns {Object.<string,*>} JSON object
             */
            ObserveEventsResponse.prototype.toJSON = function toJSON() {
                return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
            };

            return ObserveEventsResponse;
        })();

        protos.QueryServiceStateRequest = (function() {

            /**
             * Properties of a QueryServiceStateRequest.
             * @memberof perfetto.protos
             * @interface IQueryServiceStateRequest
             */

            /**
             * Constructs a new QueryServiceStateRequest.
             * @memberof perfetto.protos
             * @classdesc Represents a QueryServiceStateRequest.
             * @implements IQueryServiceStateRequest
             * @constructor
             * @param {perfetto.protos.IQueryServiceStateRequest=} [properties] Properties to set
             */
            function QueryServiceStateRequest(properties) {
                if (properties)
                    for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                        if (properties[keys[i]] != null)
                            this[keys[i]] = properties[keys[i]];
            }

            /**
             * Creates a new QueryServiceStateRequest instance using the specified properties.
             * @function create
             * @memberof perfetto.protos.QueryServiceStateRequest
             * @static
             * @param {perfetto.protos.IQueryServiceStateRequest=} [properties] Properties to set
             * @returns {perfetto.protos.QueryServiceStateRequest} QueryServiceStateRequest instance
             */
            QueryServiceStateRequest.create = function create(properties) {
                return new QueryServiceStateRequest(properties);
            };

            /**
             * Encodes the specified QueryServiceStateRequest message. Does not implicitly {@link perfetto.protos.QueryServiceStateRequest.verify|verify} messages.
             * @function encode
             * @memberof perfetto.protos.QueryServiceStateRequest
             * @static
             * @param {perfetto.protos.IQueryServiceStateRequest} message QueryServiceStateRequest message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            QueryServiceStateRequest.encode = function encode(message, writer) {
                if (!writer)
                    writer = $Writer.create();
                return writer;
            };

            /**
             * Encodes the specified QueryServiceStateRequest message, length delimited. Does not implicitly {@link perfetto.protos.QueryServiceStateRequest.verify|verify} messages.
             * @function encodeDelimited
             * @memberof perfetto.protos.QueryServiceStateRequest
             * @static
             * @param {perfetto.protos.IQueryServiceStateRequest} message QueryServiceStateRequest message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            QueryServiceStateRequest.encodeDelimited = function encodeDelimited(message, writer) {
                return this.encode(message, writer).ldelim();
            };

            /**
             * Decodes a QueryServiceStateRequest message from the specified reader or buffer.
             * @function decode
             * @memberof perfetto.protos.QueryServiceStateRequest
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @param {number} [length] Message length if known beforehand
             * @returns {perfetto.protos.QueryServiceStateRequest} QueryServiceStateRequest
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            QueryServiceStateRequest.decode = function decode(reader, length) {
                if (!(reader instanceof $Reader))
                    reader = $Reader.create(reader);
                var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.QueryServiceStateRequest();
                while (reader.pos < end) {
                    var tag = reader.uint32();
                    switch (tag >>> 3) {
                    default:
                        reader.skipType(tag & 7);
                        break;
                    }
                }
                return message;
            };

            /**
             * Decodes a QueryServiceStateRequest message from the specified reader or buffer, length delimited.
             * @function decodeDelimited
             * @memberof perfetto.protos.QueryServiceStateRequest
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @returns {perfetto.protos.QueryServiceStateRequest} QueryServiceStateRequest
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            QueryServiceStateRequest.decodeDelimited = function decodeDelimited(reader) {
                if (!(reader instanceof $Reader))
                    reader = new $Reader(reader);
                return this.decode(reader, reader.uint32());
            };

            /**
             * Verifies a QueryServiceStateRequest message.
             * @function verify
             * @memberof perfetto.protos.QueryServiceStateRequest
             * @static
             * @param {Object.<string,*>} message Plain object to verify
             * @returns {string|null} `null` if valid, otherwise the reason why it is not
             */
            QueryServiceStateRequest.verify = function verify(message) {
                if (typeof message !== "object" || message === null)
                    return "object expected";
                return null;
            };

            /**
             * Creates a QueryServiceStateRequest message from a plain object. Also converts values to their respective internal types.
             * @function fromObject
             * @memberof perfetto.protos.QueryServiceStateRequest
             * @static
             * @param {Object.<string,*>} object Plain object
             * @returns {perfetto.protos.QueryServiceStateRequest} QueryServiceStateRequest
             */
            QueryServiceStateRequest.fromObject = function fromObject(object) {
                if (object instanceof $root.perfetto.protos.QueryServiceStateRequest)
                    return object;
                return new $root.perfetto.protos.QueryServiceStateRequest();
            };

            /**
             * Creates a plain object from a QueryServiceStateRequest message. Also converts values to other types if specified.
             * @function toObject
             * @memberof perfetto.protos.QueryServiceStateRequest
             * @static
             * @param {perfetto.protos.QueryServiceStateRequest} message QueryServiceStateRequest
             * @param {$protobuf.IConversionOptions} [options] Conversion options
             * @returns {Object.<string,*>} Plain object
             */
            QueryServiceStateRequest.toObject = function toObject() {
                return {};
            };

            /**
             * Converts this QueryServiceStateRequest to JSON.
             * @function toJSON
             * @memberof perfetto.protos.QueryServiceStateRequest
             * @instance
             * @returns {Object.<string,*>} JSON object
             */
            QueryServiceStateRequest.prototype.toJSON = function toJSON() {
                return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
            };

            return QueryServiceStateRequest;
        })();

        protos.QueryServiceStateResponse = (function() {

            /**
             * Properties of a QueryServiceStateResponse.
             * @memberof perfetto.protos
             * @interface IQueryServiceStateResponse
             * @property {perfetto.protos.ITracingServiceState|null} [serviceState] QueryServiceStateResponse serviceState
             */

            /**
             * Constructs a new QueryServiceStateResponse.
             * @memberof perfetto.protos
             * @classdesc Represents a QueryServiceStateResponse.
             * @implements IQueryServiceStateResponse
             * @constructor
             * @param {perfetto.protos.IQueryServiceStateResponse=} [properties] Properties to set
             */
            function QueryServiceStateResponse(properties) {
                if (properties)
                    for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                        if (properties[keys[i]] != null)
                            this[keys[i]] = properties[keys[i]];
            }

            /**
             * QueryServiceStateResponse serviceState.
             * @member {perfetto.protos.ITracingServiceState|null|undefined} serviceState
             * @memberof perfetto.protos.QueryServiceStateResponse
             * @instance
             */
            QueryServiceStateResponse.prototype.serviceState = null;

            /**
             * Creates a new QueryServiceStateResponse instance using the specified properties.
             * @function create
             * @memberof perfetto.protos.QueryServiceStateResponse
             * @static
             * @param {perfetto.protos.IQueryServiceStateResponse=} [properties] Properties to set
             * @returns {perfetto.protos.QueryServiceStateResponse} QueryServiceStateResponse instance
             */
            QueryServiceStateResponse.create = function create(properties) {
                return new QueryServiceStateResponse(properties);
            };

            /**
             * Encodes the specified QueryServiceStateResponse message. Does not implicitly {@link perfetto.protos.QueryServiceStateResponse.verify|verify} messages.
             * @function encode
             * @memberof perfetto.protos.QueryServiceStateResponse
             * @static
             * @param {perfetto.protos.IQueryServiceStateResponse} message QueryServiceStateResponse message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            QueryServiceStateResponse.encode = function encode(message, writer) {
                if (!writer)
                    writer = $Writer.create();
                if (message.serviceState != null && Object.hasOwnProperty.call(message, "serviceState"))
                    $root.perfetto.protos.TracingServiceState.encode(message.serviceState, writer.uint32(/* id 1, wireType 2 =*/10).fork()).ldelim();
                return writer;
            };

            /**
             * Encodes the specified QueryServiceStateResponse message, length delimited. Does not implicitly {@link perfetto.protos.QueryServiceStateResponse.verify|verify} messages.
             * @function encodeDelimited
             * @memberof perfetto.protos.QueryServiceStateResponse
             * @static
             * @param {perfetto.protos.IQueryServiceStateResponse} message QueryServiceStateResponse message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            QueryServiceStateResponse.encodeDelimited = function encodeDelimited(message, writer) {
                return this.encode(message, writer).ldelim();
            };

            /**
             * Decodes a QueryServiceStateResponse message from the specified reader or buffer.
             * @function decode
             * @memberof perfetto.protos.QueryServiceStateResponse
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @param {number} [length] Message length if known beforehand
             * @returns {perfetto.protos.QueryServiceStateResponse} QueryServiceStateResponse
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            QueryServiceStateResponse.decode = function decode(reader, length) {
                if (!(reader instanceof $Reader))
                    reader = $Reader.create(reader);
                var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.QueryServiceStateResponse();
                while (reader.pos < end) {
                    var tag = reader.uint32();
                    switch (tag >>> 3) {
                    case 1:
                        message.serviceState = $root.perfetto.protos.TracingServiceState.decode(reader, reader.uint32());
                        break;
                    default:
                        reader.skipType(tag & 7);
                        break;
                    }
                }
                return message;
            };

            /**
             * Decodes a QueryServiceStateResponse message from the specified reader or buffer, length delimited.
             * @function decodeDelimited
             * @memberof perfetto.protos.QueryServiceStateResponse
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @returns {perfetto.protos.QueryServiceStateResponse} QueryServiceStateResponse
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            QueryServiceStateResponse.decodeDelimited = function decodeDelimited(reader) {
                if (!(reader instanceof $Reader))
                    reader = new $Reader(reader);
                return this.decode(reader, reader.uint32());
            };

            /**
             * Verifies a QueryServiceStateResponse message.
             * @function verify
             * @memberof perfetto.protos.QueryServiceStateResponse
             * @static
             * @param {Object.<string,*>} message Plain object to verify
             * @returns {string|null} `null` if valid, otherwise the reason why it is not
             */
            QueryServiceStateResponse.verify = function verify(message) {
                if (typeof message !== "object" || message === null)
                    return "object expected";
                if (message.serviceState != null && message.hasOwnProperty("serviceState")) {
                    var error = $root.perfetto.protos.TracingServiceState.verify(message.serviceState);
                    if (error)
                        return "serviceState." + error;
                }
                return null;
            };

            /**
             * Creates a QueryServiceStateResponse message from a plain object. Also converts values to their respective internal types.
             * @function fromObject
             * @memberof perfetto.protos.QueryServiceStateResponse
             * @static
             * @param {Object.<string,*>} object Plain object
             * @returns {perfetto.protos.QueryServiceStateResponse} QueryServiceStateResponse
             */
            QueryServiceStateResponse.fromObject = function fromObject(object) {
                if (object instanceof $root.perfetto.protos.QueryServiceStateResponse)
                    return object;
                var message = new $root.perfetto.protos.QueryServiceStateResponse();
                if (object.serviceState != null) {
                    if (typeof object.serviceState !== "object")
                        throw TypeError(".perfetto.protos.QueryServiceStateResponse.serviceState: object expected");
                    message.serviceState = $root.perfetto.protos.TracingServiceState.fromObject(object.serviceState);
                }
                return message;
            };

            /**
             * Creates a plain object from a QueryServiceStateResponse message. Also converts values to other types if specified.
             * @function toObject
             * @memberof perfetto.protos.QueryServiceStateResponse
             * @static
             * @param {perfetto.protos.QueryServiceStateResponse} message QueryServiceStateResponse
             * @param {$protobuf.IConversionOptions} [options] Conversion options
             * @returns {Object.<string,*>} Plain object
             */
            QueryServiceStateResponse.toObject = function toObject(message, options) {
                if (!options)
                    options = {};
                var object = {};
                if (options.defaults)
                    object.serviceState = null;
                if (message.serviceState != null && message.hasOwnProperty("serviceState"))
                    object.serviceState = $root.perfetto.protos.TracingServiceState.toObject(message.serviceState, options);
                return object;
            };

            /**
             * Converts this QueryServiceStateResponse to JSON.
             * @function toJSON
             * @memberof perfetto.protos.QueryServiceStateResponse
             * @instance
             * @returns {Object.<string,*>} JSON object
             */
            QueryServiceStateResponse.prototype.toJSON = function toJSON() {
                return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
            };

            return QueryServiceStateResponse;
        })();

        protos.QueryCapabilitiesRequest = (function() {

            /**
             * Properties of a QueryCapabilitiesRequest.
             * @memberof perfetto.protos
             * @interface IQueryCapabilitiesRequest
             */

            /**
             * Constructs a new QueryCapabilitiesRequest.
             * @memberof perfetto.protos
             * @classdesc Represents a QueryCapabilitiesRequest.
             * @implements IQueryCapabilitiesRequest
             * @constructor
             * @param {perfetto.protos.IQueryCapabilitiesRequest=} [properties] Properties to set
             */
            function QueryCapabilitiesRequest(properties) {
                if (properties)
                    for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                        if (properties[keys[i]] != null)
                            this[keys[i]] = properties[keys[i]];
            }

            /**
             * Creates a new QueryCapabilitiesRequest instance using the specified properties.
             * @function create
             * @memberof perfetto.protos.QueryCapabilitiesRequest
             * @static
             * @param {perfetto.protos.IQueryCapabilitiesRequest=} [properties] Properties to set
             * @returns {perfetto.protos.QueryCapabilitiesRequest} QueryCapabilitiesRequest instance
             */
            QueryCapabilitiesRequest.create = function create(properties) {
                return new QueryCapabilitiesRequest(properties);
            };

            /**
             * Encodes the specified QueryCapabilitiesRequest message. Does not implicitly {@link perfetto.protos.QueryCapabilitiesRequest.verify|verify} messages.
             * @function encode
             * @memberof perfetto.protos.QueryCapabilitiesRequest
             * @static
             * @param {perfetto.protos.IQueryCapabilitiesRequest} message QueryCapabilitiesRequest message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            QueryCapabilitiesRequest.encode = function encode(message, writer) {
                if (!writer)
                    writer = $Writer.create();
                return writer;
            };

            /**
             * Encodes the specified QueryCapabilitiesRequest message, length delimited. Does not implicitly {@link perfetto.protos.QueryCapabilitiesRequest.verify|verify} messages.
             * @function encodeDelimited
             * @memberof perfetto.protos.QueryCapabilitiesRequest
             * @static
             * @param {perfetto.protos.IQueryCapabilitiesRequest} message QueryCapabilitiesRequest message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            QueryCapabilitiesRequest.encodeDelimited = function encodeDelimited(message, writer) {
                return this.encode(message, writer).ldelim();
            };

            /**
             * Decodes a QueryCapabilitiesRequest message from the specified reader or buffer.
             * @function decode
             * @memberof perfetto.protos.QueryCapabilitiesRequest
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @param {number} [length] Message length if known beforehand
             * @returns {perfetto.protos.QueryCapabilitiesRequest} QueryCapabilitiesRequest
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            QueryCapabilitiesRequest.decode = function decode(reader, length) {
                if (!(reader instanceof $Reader))
                    reader = $Reader.create(reader);
                var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.QueryCapabilitiesRequest();
                while (reader.pos < end) {
                    var tag = reader.uint32();
                    switch (tag >>> 3) {
                    default:
                        reader.skipType(tag & 7);
                        break;
                    }
                }
                return message;
            };

            /**
             * Decodes a QueryCapabilitiesRequest message from the specified reader or buffer, length delimited.
             * @function decodeDelimited
             * @memberof perfetto.protos.QueryCapabilitiesRequest
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @returns {perfetto.protos.QueryCapabilitiesRequest} QueryCapabilitiesRequest
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            QueryCapabilitiesRequest.decodeDelimited = function decodeDelimited(reader) {
                if (!(reader instanceof $Reader))
                    reader = new $Reader(reader);
                return this.decode(reader, reader.uint32());
            };

            /**
             * Verifies a QueryCapabilitiesRequest message.
             * @function verify
             * @memberof perfetto.protos.QueryCapabilitiesRequest
             * @static
             * @param {Object.<string,*>} message Plain object to verify
             * @returns {string|null} `null` if valid, otherwise the reason why it is not
             */
            QueryCapabilitiesRequest.verify = function verify(message) {
                if (typeof message !== "object" || message === null)
                    return "object expected";
                return null;
            };

            /**
             * Creates a QueryCapabilitiesRequest message from a plain object. Also converts values to their respective internal types.
             * @function fromObject
             * @memberof perfetto.protos.QueryCapabilitiesRequest
             * @static
             * @param {Object.<string,*>} object Plain object
             * @returns {perfetto.protos.QueryCapabilitiesRequest} QueryCapabilitiesRequest
             */
            QueryCapabilitiesRequest.fromObject = function fromObject(object) {
                if (object instanceof $root.perfetto.protos.QueryCapabilitiesRequest)
                    return object;
                return new $root.perfetto.protos.QueryCapabilitiesRequest();
            };

            /**
             * Creates a plain object from a QueryCapabilitiesRequest message. Also converts values to other types if specified.
             * @function toObject
             * @memberof perfetto.protos.QueryCapabilitiesRequest
             * @static
             * @param {perfetto.protos.QueryCapabilitiesRequest} message QueryCapabilitiesRequest
             * @param {$protobuf.IConversionOptions} [options] Conversion options
             * @returns {Object.<string,*>} Plain object
             */
            QueryCapabilitiesRequest.toObject = function toObject() {
                return {};
            };

            /**
             * Converts this QueryCapabilitiesRequest to JSON.
             * @function toJSON
             * @memberof perfetto.protos.QueryCapabilitiesRequest
             * @instance
             * @returns {Object.<string,*>} JSON object
             */
            QueryCapabilitiesRequest.prototype.toJSON = function toJSON() {
                return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
            };

            return QueryCapabilitiesRequest;
        })();

        protos.QueryCapabilitiesResponse = (function() {

            /**
             * Properties of a QueryCapabilitiesResponse.
             * @memberof perfetto.protos
             * @interface IQueryCapabilitiesResponse
             * @property {perfetto.protos.ITracingServiceCapabilities|null} [capabilities] QueryCapabilitiesResponse capabilities
             */

            /**
             * Constructs a new QueryCapabilitiesResponse.
             * @memberof perfetto.protos
             * @classdesc Represents a QueryCapabilitiesResponse.
             * @implements IQueryCapabilitiesResponse
             * @constructor
             * @param {perfetto.protos.IQueryCapabilitiesResponse=} [properties] Properties to set
             */
            function QueryCapabilitiesResponse(properties) {
                if (properties)
                    for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                        if (properties[keys[i]] != null)
                            this[keys[i]] = properties[keys[i]];
            }

            /**
             * QueryCapabilitiesResponse capabilities.
             * @member {perfetto.protos.ITracingServiceCapabilities|null|undefined} capabilities
             * @memberof perfetto.protos.QueryCapabilitiesResponse
             * @instance
             */
            QueryCapabilitiesResponse.prototype.capabilities = null;

            /**
             * Creates a new QueryCapabilitiesResponse instance using the specified properties.
             * @function create
             * @memberof perfetto.protos.QueryCapabilitiesResponse
             * @static
             * @param {perfetto.protos.IQueryCapabilitiesResponse=} [properties] Properties to set
             * @returns {perfetto.protos.QueryCapabilitiesResponse} QueryCapabilitiesResponse instance
             */
            QueryCapabilitiesResponse.create = function create(properties) {
                return new QueryCapabilitiesResponse(properties);
            };

            /**
             * Encodes the specified QueryCapabilitiesResponse message. Does not implicitly {@link perfetto.protos.QueryCapabilitiesResponse.verify|verify} messages.
             * @function encode
             * @memberof perfetto.protos.QueryCapabilitiesResponse
             * @static
             * @param {perfetto.protos.IQueryCapabilitiesResponse} message QueryCapabilitiesResponse message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            QueryCapabilitiesResponse.encode = function encode(message, writer) {
                if (!writer)
                    writer = $Writer.create();
                if (message.capabilities != null && Object.hasOwnProperty.call(message, "capabilities"))
                    $root.perfetto.protos.TracingServiceCapabilities.encode(message.capabilities, writer.uint32(/* id 1, wireType 2 =*/10).fork()).ldelim();
                return writer;
            };

            /**
             * Encodes the specified QueryCapabilitiesResponse message, length delimited. Does not implicitly {@link perfetto.protos.QueryCapabilitiesResponse.verify|verify} messages.
             * @function encodeDelimited
             * @memberof perfetto.protos.QueryCapabilitiesResponse
             * @static
             * @param {perfetto.protos.IQueryCapabilitiesResponse} message QueryCapabilitiesResponse message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            QueryCapabilitiesResponse.encodeDelimited = function encodeDelimited(message, writer) {
                return this.encode(message, writer).ldelim();
            };

            /**
             * Decodes a QueryCapabilitiesResponse message from the specified reader or buffer.
             * @function decode
             * @memberof perfetto.protos.QueryCapabilitiesResponse
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @param {number} [length] Message length if known beforehand
             * @returns {perfetto.protos.QueryCapabilitiesResponse} QueryCapabilitiesResponse
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            QueryCapabilitiesResponse.decode = function decode(reader, length) {
                if (!(reader instanceof $Reader))
                    reader = $Reader.create(reader);
                var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.QueryCapabilitiesResponse();
                while (reader.pos < end) {
                    var tag = reader.uint32();
                    switch (tag >>> 3) {
                    case 1:
                        message.capabilities = $root.perfetto.protos.TracingServiceCapabilities.decode(reader, reader.uint32());
                        break;
                    default:
                        reader.skipType(tag & 7);
                        break;
                    }
                }
                return message;
            };

            /**
             * Decodes a QueryCapabilitiesResponse message from the specified reader or buffer, length delimited.
             * @function decodeDelimited
             * @memberof perfetto.protos.QueryCapabilitiesResponse
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @returns {perfetto.protos.QueryCapabilitiesResponse} QueryCapabilitiesResponse
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            QueryCapabilitiesResponse.decodeDelimited = function decodeDelimited(reader) {
                if (!(reader instanceof $Reader))
                    reader = new $Reader(reader);
                return this.decode(reader, reader.uint32());
            };

            /**
             * Verifies a QueryCapabilitiesResponse message.
             * @function verify
             * @memberof perfetto.protos.QueryCapabilitiesResponse
             * @static
             * @param {Object.<string,*>} message Plain object to verify
             * @returns {string|null} `null` if valid, otherwise the reason why it is not
             */
            QueryCapabilitiesResponse.verify = function verify(message) {
                if (typeof message !== "object" || message === null)
                    return "object expected";
                if (message.capabilities != null && message.hasOwnProperty("capabilities")) {
                    var error = $root.perfetto.protos.TracingServiceCapabilities.verify(message.capabilities);
                    if (error)
                        return "capabilities." + error;
                }
                return null;
            };

            /**
             * Creates a QueryCapabilitiesResponse message from a plain object. Also converts values to their respective internal types.
             * @function fromObject
             * @memberof perfetto.protos.QueryCapabilitiesResponse
             * @static
             * @param {Object.<string,*>} object Plain object
             * @returns {perfetto.protos.QueryCapabilitiesResponse} QueryCapabilitiesResponse
             */
            QueryCapabilitiesResponse.fromObject = function fromObject(object) {
                if (object instanceof $root.perfetto.protos.QueryCapabilitiesResponse)
                    return object;
                var message = new $root.perfetto.protos.QueryCapabilitiesResponse();
                if (object.capabilities != null) {
                    if (typeof object.capabilities !== "object")
                        throw TypeError(".perfetto.protos.QueryCapabilitiesResponse.capabilities: object expected");
                    message.capabilities = $root.perfetto.protos.TracingServiceCapabilities.fromObject(object.capabilities);
                }
                return message;
            };

            /**
             * Creates a plain object from a QueryCapabilitiesResponse message. Also converts values to other types if specified.
             * @function toObject
             * @memberof perfetto.protos.QueryCapabilitiesResponse
             * @static
             * @param {perfetto.protos.QueryCapabilitiesResponse} message QueryCapabilitiesResponse
             * @param {$protobuf.IConversionOptions} [options] Conversion options
             * @returns {Object.<string,*>} Plain object
             */
            QueryCapabilitiesResponse.toObject = function toObject(message, options) {
                if (!options)
                    options = {};
                var object = {};
                if (options.defaults)
                    object.capabilities = null;
                if (message.capabilities != null && message.hasOwnProperty("capabilities"))
                    object.capabilities = $root.perfetto.protos.TracingServiceCapabilities.toObject(message.capabilities, options);
                return object;
            };

            /**
             * Converts this QueryCapabilitiesResponse to JSON.
             * @function toJSON
             * @memberof perfetto.protos.QueryCapabilitiesResponse
             * @instance
             * @returns {Object.<string,*>} JSON object
             */
            QueryCapabilitiesResponse.prototype.toJSON = function toJSON() {
                return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
            };

            return QueryCapabilitiesResponse;
        })();

        protos.SaveTraceForBugreportRequest = (function() {

            /**
             * Properties of a SaveTraceForBugreportRequest.
             * @memberof perfetto.protos
             * @interface ISaveTraceForBugreportRequest
             */

            /**
             * Constructs a new SaveTraceForBugreportRequest.
             * @memberof perfetto.protos
             * @classdesc Represents a SaveTraceForBugreportRequest.
             * @implements ISaveTraceForBugreportRequest
             * @constructor
             * @param {perfetto.protos.ISaveTraceForBugreportRequest=} [properties] Properties to set
             */
            function SaveTraceForBugreportRequest(properties) {
                if (properties)
                    for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                        if (properties[keys[i]] != null)
                            this[keys[i]] = properties[keys[i]];
            }

            /**
             * Creates a new SaveTraceForBugreportRequest instance using the specified properties.
             * @function create
             * @memberof perfetto.protos.SaveTraceForBugreportRequest
             * @static
             * @param {perfetto.protos.ISaveTraceForBugreportRequest=} [properties] Properties to set
             * @returns {perfetto.protos.SaveTraceForBugreportRequest} SaveTraceForBugreportRequest instance
             */
            SaveTraceForBugreportRequest.create = function create(properties) {
                return new SaveTraceForBugreportRequest(properties);
            };

            /**
             * Encodes the specified SaveTraceForBugreportRequest message. Does not implicitly {@link perfetto.protos.SaveTraceForBugreportRequest.verify|verify} messages.
             * @function encode
             * @memberof perfetto.protos.SaveTraceForBugreportRequest
             * @static
             * @param {perfetto.protos.ISaveTraceForBugreportRequest} message SaveTraceForBugreportRequest message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            SaveTraceForBugreportRequest.encode = function encode(message, writer) {
                if (!writer)
                    writer = $Writer.create();
                return writer;
            };

            /**
             * Encodes the specified SaveTraceForBugreportRequest message, length delimited. Does not implicitly {@link perfetto.protos.SaveTraceForBugreportRequest.verify|verify} messages.
             * @function encodeDelimited
             * @memberof perfetto.protos.SaveTraceForBugreportRequest
             * @static
             * @param {perfetto.protos.ISaveTraceForBugreportRequest} message SaveTraceForBugreportRequest message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            SaveTraceForBugreportRequest.encodeDelimited = function encodeDelimited(message, writer) {
                return this.encode(message, writer).ldelim();
            };

            /**
             * Decodes a SaveTraceForBugreportRequest message from the specified reader or buffer.
             * @function decode
             * @memberof perfetto.protos.SaveTraceForBugreportRequest
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @param {number} [length] Message length if known beforehand
             * @returns {perfetto.protos.SaveTraceForBugreportRequest} SaveTraceForBugreportRequest
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            SaveTraceForBugreportRequest.decode = function decode(reader, length) {
                if (!(reader instanceof $Reader))
                    reader = $Reader.create(reader);
                var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.SaveTraceForBugreportRequest();
                while (reader.pos < end) {
                    var tag = reader.uint32();
                    switch (tag >>> 3) {
                    default:
                        reader.skipType(tag & 7);
                        break;
                    }
                }
                return message;
            };

            /**
             * Decodes a SaveTraceForBugreportRequest message from the specified reader or buffer, length delimited.
             * @function decodeDelimited
             * @memberof perfetto.protos.SaveTraceForBugreportRequest
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @returns {perfetto.protos.SaveTraceForBugreportRequest} SaveTraceForBugreportRequest
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            SaveTraceForBugreportRequest.decodeDelimited = function decodeDelimited(reader) {
                if (!(reader instanceof $Reader))
                    reader = new $Reader(reader);
                return this.decode(reader, reader.uint32());
            };

            /**
             * Verifies a SaveTraceForBugreportRequest message.
             * @function verify
             * @memberof perfetto.protos.SaveTraceForBugreportRequest
             * @static
             * @param {Object.<string,*>} message Plain object to verify
             * @returns {string|null} `null` if valid, otherwise the reason why it is not
             */
            SaveTraceForBugreportRequest.verify = function verify(message) {
                if (typeof message !== "object" || message === null)
                    return "object expected";
                return null;
            };

            /**
             * Creates a SaveTraceForBugreportRequest message from a plain object. Also converts values to their respective internal types.
             * @function fromObject
             * @memberof perfetto.protos.SaveTraceForBugreportRequest
             * @static
             * @param {Object.<string,*>} object Plain object
             * @returns {perfetto.protos.SaveTraceForBugreportRequest} SaveTraceForBugreportRequest
             */
            SaveTraceForBugreportRequest.fromObject = function fromObject(object) {
                if (object instanceof $root.perfetto.protos.SaveTraceForBugreportRequest)
                    return object;
                return new $root.perfetto.protos.SaveTraceForBugreportRequest();
            };

            /**
             * Creates a plain object from a SaveTraceForBugreportRequest message. Also converts values to other types if specified.
             * @function toObject
             * @memberof perfetto.protos.SaveTraceForBugreportRequest
             * @static
             * @param {perfetto.protos.SaveTraceForBugreportRequest} message SaveTraceForBugreportRequest
             * @param {$protobuf.IConversionOptions} [options] Conversion options
             * @returns {Object.<string,*>} Plain object
             */
            SaveTraceForBugreportRequest.toObject = function toObject() {
                return {};
            };

            /**
             * Converts this SaveTraceForBugreportRequest to JSON.
             * @function toJSON
             * @memberof perfetto.protos.SaveTraceForBugreportRequest
             * @instance
             * @returns {Object.<string,*>} JSON object
             */
            SaveTraceForBugreportRequest.prototype.toJSON = function toJSON() {
                return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
            };

            return SaveTraceForBugreportRequest;
        })();

        protos.SaveTraceForBugreportResponse = (function() {

            /**
             * Properties of a SaveTraceForBugreportResponse.
             * @memberof perfetto.protos
             * @interface ISaveTraceForBugreportResponse
             * @property {boolean|null} [success] SaveTraceForBugreportResponse success
             * @property {string|null} [msg] SaveTraceForBugreportResponse msg
             */

            /**
             * Constructs a new SaveTraceForBugreportResponse.
             * @memberof perfetto.protos
             * @classdesc Represents a SaveTraceForBugreportResponse.
             * @implements ISaveTraceForBugreportResponse
             * @constructor
             * @param {perfetto.protos.ISaveTraceForBugreportResponse=} [properties] Properties to set
             */
            function SaveTraceForBugreportResponse(properties) {
                if (properties)
                    for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                        if (properties[keys[i]] != null)
                            this[keys[i]] = properties[keys[i]];
            }

            /**
             * SaveTraceForBugreportResponse success.
             * @member {boolean} success
             * @memberof perfetto.protos.SaveTraceForBugreportResponse
             * @instance
             */
            SaveTraceForBugreportResponse.prototype.success = false;

            /**
             * SaveTraceForBugreportResponse msg.
             * @member {string} msg
             * @memberof perfetto.protos.SaveTraceForBugreportResponse
             * @instance
             */
            SaveTraceForBugreportResponse.prototype.msg = "";

            /**
             * Creates a new SaveTraceForBugreportResponse instance using the specified properties.
             * @function create
             * @memberof perfetto.protos.SaveTraceForBugreportResponse
             * @static
             * @param {perfetto.protos.ISaveTraceForBugreportResponse=} [properties] Properties to set
             * @returns {perfetto.protos.SaveTraceForBugreportResponse} SaveTraceForBugreportResponse instance
             */
            SaveTraceForBugreportResponse.create = function create(properties) {
                return new SaveTraceForBugreportResponse(properties);
            };

            /**
             * Encodes the specified SaveTraceForBugreportResponse message. Does not implicitly {@link perfetto.protos.SaveTraceForBugreportResponse.verify|verify} messages.
             * @function encode
             * @memberof perfetto.protos.SaveTraceForBugreportResponse
             * @static
             * @param {perfetto.protos.ISaveTraceForBugreportResponse} message SaveTraceForBugreportResponse message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            SaveTraceForBugreportResponse.encode = function encode(message, writer) {
                if (!writer)
                    writer = $Writer.create();
                if (message.success != null && Object.hasOwnProperty.call(message, "success"))
                    writer.uint32(/* id 1, wireType 0 =*/8).bool(message.success);
                if (message.msg != null && Object.hasOwnProperty.call(message, "msg"))
                    writer.uint32(/* id 2, wireType 2 =*/18).string(message.msg);
                return writer;
            };

            /**
             * Encodes the specified SaveTraceForBugreportResponse message, length delimited. Does not implicitly {@link perfetto.protos.SaveTraceForBugreportResponse.verify|verify} messages.
             * @function encodeDelimited
             * @memberof perfetto.protos.SaveTraceForBugreportResponse
             * @static
             * @param {perfetto.protos.ISaveTraceForBugreportResponse} message SaveTraceForBugreportResponse message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            SaveTraceForBugreportResponse.encodeDelimited = function encodeDelimited(message, writer) {
                return this.encode(message, writer).ldelim();
            };

            /**
             * Decodes a SaveTraceForBugreportResponse message from the specified reader or buffer.
             * @function decode
             * @memberof perfetto.protos.SaveTraceForBugreportResponse
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @param {number} [length] Message length if known beforehand
             * @returns {perfetto.protos.SaveTraceForBugreportResponse} SaveTraceForBugreportResponse
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            SaveTraceForBugreportResponse.decode = function decode(reader, length) {
                if (!(reader instanceof $Reader))
                    reader = $Reader.create(reader);
                var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.SaveTraceForBugreportResponse();
                while (reader.pos < end) {
                    var tag = reader.uint32();
                    switch (tag >>> 3) {
                    case 1:
                        message.success = reader.bool();
                        break;
                    case 2:
                        message.msg = reader.string();
                        break;
                    default:
                        reader.skipType(tag & 7);
                        break;
                    }
                }
                return message;
            };

            /**
             * Decodes a SaveTraceForBugreportResponse message from the specified reader or buffer, length delimited.
             * @function decodeDelimited
             * @memberof perfetto.protos.SaveTraceForBugreportResponse
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @returns {perfetto.protos.SaveTraceForBugreportResponse} SaveTraceForBugreportResponse
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            SaveTraceForBugreportResponse.decodeDelimited = function decodeDelimited(reader) {
                if (!(reader instanceof $Reader))
                    reader = new $Reader(reader);
                return this.decode(reader, reader.uint32());
            };

            /**
             * Verifies a SaveTraceForBugreportResponse message.
             * @function verify
             * @memberof perfetto.protos.SaveTraceForBugreportResponse
             * @static
             * @param {Object.<string,*>} message Plain object to verify
             * @returns {string|null} `null` if valid, otherwise the reason why it is not
             */
            SaveTraceForBugreportResponse.verify = function verify(message) {
                if (typeof message !== "object" || message === null)
                    return "object expected";
                if (message.success != null && message.hasOwnProperty("success"))
                    if (typeof message.success !== "boolean")
                        return "success: boolean expected";
                if (message.msg != null && message.hasOwnProperty("msg"))
                    if (!$util.isString(message.msg))
                        return "msg: string expected";
                return null;
            };

            /**
             * Creates a SaveTraceForBugreportResponse message from a plain object. Also converts values to their respective internal types.
             * @function fromObject
             * @memberof perfetto.protos.SaveTraceForBugreportResponse
             * @static
             * @param {Object.<string,*>} object Plain object
             * @returns {perfetto.protos.SaveTraceForBugreportResponse} SaveTraceForBugreportResponse
             */
            SaveTraceForBugreportResponse.fromObject = function fromObject(object) {
                if (object instanceof $root.perfetto.protos.SaveTraceForBugreportResponse)
                    return object;
                var message = new $root.perfetto.protos.SaveTraceForBugreportResponse();
                if (object.success != null)
                    message.success = Boolean(object.success);
                if (object.msg != null)
                    message.msg = String(object.msg);
                return message;
            };

            /**
             * Creates a plain object from a SaveTraceForBugreportResponse message. Also converts values to other types if specified.
             * @function toObject
             * @memberof perfetto.protos.SaveTraceForBugreportResponse
             * @static
             * @param {perfetto.protos.SaveTraceForBugreportResponse} message SaveTraceForBugreportResponse
             * @param {$protobuf.IConversionOptions} [options] Conversion options
             * @returns {Object.<string,*>} Plain object
             */
            SaveTraceForBugreportResponse.toObject = function toObject(message, options) {
                if (!options)
                    options = {};
                var object = {};
                if (options.defaults) {
                    object.success = false;
                    object.msg = "";
                }
                if (message.success != null && message.hasOwnProperty("success"))
                    object.success = message.success;
                if (message.msg != null && message.hasOwnProperty("msg"))
                    object.msg = message.msg;
                return object;
            };

            /**
             * Converts this SaveTraceForBugreportResponse to JSON.
             * @function toJSON
             * @memberof perfetto.protos.SaveTraceForBugreportResponse
             * @instance
             * @returns {Object.<string,*>} JSON object
             */
            SaveTraceForBugreportResponse.prototype.toJSON = function toJSON() {
                return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
            };

            return SaveTraceForBugreportResponse;
        })();

        protos.IPCFrame = (function() {

            /**
             * Properties of a IPCFrame.
             * @memberof perfetto.protos
             * @interface IIPCFrame
             * @property {number|null} [requestId] IPCFrame requestId
             * @property {perfetto.protos.IPCFrame.IBindService|null} [msgBindService] IPCFrame msgBindService
             * @property {perfetto.protos.IPCFrame.IBindServiceReply|null} [msgBindServiceReply] IPCFrame msgBindServiceReply
             * @property {perfetto.protos.IPCFrame.IInvokeMethod|null} [msgInvokeMethod] IPCFrame msgInvokeMethod
             * @property {perfetto.protos.IPCFrame.IInvokeMethodReply|null} [msgInvokeMethodReply] IPCFrame msgInvokeMethodReply
             * @property {perfetto.protos.IPCFrame.IRequestError|null} [msgRequestError] IPCFrame msgRequestError
             * @property {Array.<Uint8Array>|null} [dataForTesting] IPCFrame dataForTesting
             */

            /**
             * Constructs a new IPCFrame.
             * @memberof perfetto.protos
             * @classdesc Represents a IPCFrame.
             * @implements IIPCFrame
             * @constructor
             * @param {perfetto.protos.IIPCFrame=} [properties] Properties to set
             */
            function IPCFrame(properties) {
                this.dataForTesting = [];
                if (properties)
                    for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                        if (properties[keys[i]] != null)
                            this[keys[i]] = properties[keys[i]];
            }

            /**
             * IPCFrame requestId.
             * @member {number} requestId
             * @memberof perfetto.protos.IPCFrame
             * @instance
             */
            IPCFrame.prototype.requestId = $util.Long ? $util.Long.fromBits(0,0,true) : 0;

            /**
             * IPCFrame msgBindService.
             * @member {perfetto.protos.IPCFrame.IBindService|null|undefined} msgBindService
             * @memberof perfetto.protos.IPCFrame
             * @instance
             */
            IPCFrame.prototype.msgBindService = null;

            /**
             * IPCFrame msgBindServiceReply.
             * @member {perfetto.protos.IPCFrame.IBindServiceReply|null|undefined} msgBindServiceReply
             * @memberof perfetto.protos.IPCFrame
             * @instance
             */
            IPCFrame.prototype.msgBindServiceReply = null;

            /**
             * IPCFrame msgInvokeMethod.
             * @member {perfetto.protos.IPCFrame.IInvokeMethod|null|undefined} msgInvokeMethod
             * @memberof perfetto.protos.IPCFrame
             * @instance
             */
            IPCFrame.prototype.msgInvokeMethod = null;

            /**
             * IPCFrame msgInvokeMethodReply.
             * @member {perfetto.protos.IPCFrame.IInvokeMethodReply|null|undefined} msgInvokeMethodReply
             * @memberof perfetto.protos.IPCFrame
             * @instance
             */
            IPCFrame.prototype.msgInvokeMethodReply = null;

            /**
             * IPCFrame msgRequestError.
             * @member {perfetto.protos.IPCFrame.IRequestError|null|undefined} msgRequestError
             * @memberof perfetto.protos.IPCFrame
             * @instance
             */
            IPCFrame.prototype.msgRequestError = null;

            /**
             * IPCFrame dataForTesting.
             * @member {Array.<Uint8Array>} dataForTesting
             * @memberof perfetto.protos.IPCFrame
             * @instance
             */
            IPCFrame.prototype.dataForTesting = $util.emptyArray;

            // OneOf field names bound to virtual getters and setters
            var $oneOfFields;

            /**
             * IPCFrame msg.
             * @member {"msgBindService"|"msgBindServiceReply"|"msgInvokeMethod"|"msgInvokeMethodReply"|"msgRequestError"|undefined} msg
             * @memberof perfetto.protos.IPCFrame
             * @instance
             */
            Object.defineProperty(IPCFrame.prototype, "msg", {
                get: $util.oneOfGetter($oneOfFields = ["msgBindService", "msgBindServiceReply", "msgInvokeMethod", "msgInvokeMethodReply", "msgRequestError"]),
                set: $util.oneOfSetter($oneOfFields)
            });

            /**
             * Creates a new IPCFrame instance using the specified properties.
             * @function create
             * @memberof perfetto.protos.IPCFrame
             * @static
             * @param {perfetto.protos.IIPCFrame=} [properties] Properties to set
             * @returns {perfetto.protos.IPCFrame} IPCFrame instance
             */
            IPCFrame.create = function create(properties) {
                return new IPCFrame(properties);
            };

            /**
             * Encodes the specified IPCFrame message. Does not implicitly {@link perfetto.protos.IPCFrame.verify|verify} messages.
             * @function encode
             * @memberof perfetto.protos.IPCFrame
             * @static
             * @param {perfetto.protos.IIPCFrame} message IPCFrame message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            IPCFrame.encode = function encode(message, writer) {
                if (!writer)
                    writer = $Writer.create();
                if (message.dataForTesting != null && message.dataForTesting.length)
                    for (var i = 0; i < message.dataForTesting.length; ++i)
                        writer.uint32(/* id 1, wireType 2 =*/10).bytes(message.dataForTesting[i]);
                if (message.requestId != null && Object.hasOwnProperty.call(message, "requestId"))
                    writer.uint32(/* id 2, wireType 0 =*/16).uint64(message.requestId);
                if (message.msgBindService != null && Object.hasOwnProperty.call(message, "msgBindService"))
                    $root.perfetto.protos.IPCFrame.BindService.encode(message.msgBindService, writer.uint32(/* id 3, wireType 2 =*/26).fork()).ldelim();
                if (message.msgBindServiceReply != null && Object.hasOwnProperty.call(message, "msgBindServiceReply"))
                    $root.perfetto.protos.IPCFrame.BindServiceReply.encode(message.msgBindServiceReply, writer.uint32(/* id 4, wireType 2 =*/34).fork()).ldelim();
                if (message.msgInvokeMethod != null && Object.hasOwnProperty.call(message, "msgInvokeMethod"))
                    $root.perfetto.protos.IPCFrame.InvokeMethod.encode(message.msgInvokeMethod, writer.uint32(/* id 5, wireType 2 =*/42).fork()).ldelim();
                if (message.msgInvokeMethodReply != null && Object.hasOwnProperty.call(message, "msgInvokeMethodReply"))
                    $root.perfetto.protos.IPCFrame.InvokeMethodReply.encode(message.msgInvokeMethodReply, writer.uint32(/* id 6, wireType 2 =*/50).fork()).ldelim();
                if (message.msgRequestError != null && Object.hasOwnProperty.call(message, "msgRequestError"))
                    $root.perfetto.protos.IPCFrame.RequestError.encode(message.msgRequestError, writer.uint32(/* id 7, wireType 2 =*/58).fork()).ldelim();
                return writer;
            };

            /**
             * Encodes the specified IPCFrame message, length delimited. Does not implicitly {@link perfetto.protos.IPCFrame.verify|verify} messages.
             * @function encodeDelimited
             * @memberof perfetto.protos.IPCFrame
             * @static
             * @param {perfetto.protos.IIPCFrame} message IPCFrame message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            IPCFrame.encodeDelimited = function encodeDelimited(message, writer) {
                return this.encode(message, writer).ldelim();
            };

            /**
             * Decodes a IPCFrame message from the specified reader or buffer.
             * @function decode
             * @memberof perfetto.protos.IPCFrame
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @param {number} [length] Message length if known beforehand
             * @returns {perfetto.protos.IPCFrame} IPCFrame
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            IPCFrame.decode = function decode(reader, length) {
                if (!(reader instanceof $Reader))
                    reader = $Reader.create(reader);
                var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.IPCFrame();
                while (reader.pos < end) {
                    var tag = reader.uint32();
                    switch (tag >>> 3) {
                    case 2:
                        message.requestId = reader.uint64();
                        break;
                    case 3:
                        message.msgBindService = $root.perfetto.protos.IPCFrame.BindService.decode(reader, reader.uint32());
                        break;
                    case 4:
                        message.msgBindServiceReply = $root.perfetto.protos.IPCFrame.BindServiceReply.decode(reader, reader.uint32());
                        break;
                    case 5:
                        message.msgInvokeMethod = $root.perfetto.protos.IPCFrame.InvokeMethod.decode(reader, reader.uint32());
                        break;
                    case 6:
                        message.msgInvokeMethodReply = $root.perfetto.protos.IPCFrame.InvokeMethodReply.decode(reader, reader.uint32());
                        break;
                    case 7:
                        message.msgRequestError = $root.perfetto.protos.IPCFrame.RequestError.decode(reader, reader.uint32());
                        break;
                    case 1:
                        if (!(message.dataForTesting && message.dataForTesting.length))
                            message.dataForTesting = [];
                        message.dataForTesting.push(reader.bytes());
                        break;
                    default:
                        reader.skipType(tag & 7);
                        break;
                    }
                }
                return message;
            };

            /**
             * Decodes a IPCFrame message from the specified reader or buffer, length delimited.
             * @function decodeDelimited
             * @memberof perfetto.protos.IPCFrame
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @returns {perfetto.protos.IPCFrame} IPCFrame
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            IPCFrame.decodeDelimited = function decodeDelimited(reader) {
                if (!(reader instanceof $Reader))
                    reader = new $Reader(reader);
                return this.decode(reader, reader.uint32());
            };

            /**
             * Verifies a IPCFrame message.
             * @function verify
             * @memberof perfetto.protos.IPCFrame
             * @static
             * @param {Object.<string,*>} message Plain object to verify
             * @returns {string|null} `null` if valid, otherwise the reason why it is not
             */
            IPCFrame.verify = function verify(message) {
                if (typeof message !== "object" || message === null)
                    return "object expected";
                var properties = {};
                if (message.requestId != null && message.hasOwnProperty("requestId"))
                    if (!$util.isInteger(message.requestId) && !(message.requestId && $util.isInteger(message.requestId.low) && $util.isInteger(message.requestId.high)))
                        return "requestId: integer|Long expected";
                if (message.msgBindService != null && message.hasOwnProperty("msgBindService")) {
                    properties.msg = 1;
                    {
                        var error = $root.perfetto.protos.IPCFrame.BindService.verify(message.msgBindService);
                        if (error)
                            return "msgBindService." + error;
                    }
                }
                if (message.msgBindServiceReply != null && message.hasOwnProperty("msgBindServiceReply")) {
                    if (properties.msg === 1)
                        return "msg: multiple values";
                    properties.msg = 1;
                    {
                        var error = $root.perfetto.protos.IPCFrame.BindServiceReply.verify(message.msgBindServiceReply);
                        if (error)
                            return "msgBindServiceReply." + error;
                    }
                }
                if (message.msgInvokeMethod != null && message.hasOwnProperty("msgInvokeMethod")) {
                    if (properties.msg === 1)
                        return "msg: multiple values";
                    properties.msg = 1;
                    {
                        var error = $root.perfetto.protos.IPCFrame.InvokeMethod.verify(message.msgInvokeMethod);
                        if (error)
                            return "msgInvokeMethod." + error;
                    }
                }
                if (message.msgInvokeMethodReply != null && message.hasOwnProperty("msgInvokeMethodReply")) {
                    if (properties.msg === 1)
                        return "msg: multiple values";
                    properties.msg = 1;
                    {
                        var error = $root.perfetto.protos.IPCFrame.InvokeMethodReply.verify(message.msgInvokeMethodReply);
                        if (error)
                            return "msgInvokeMethodReply." + error;
                    }
                }
                if (message.msgRequestError != null && message.hasOwnProperty("msgRequestError")) {
                    if (properties.msg === 1)
                        return "msg: multiple values";
                    properties.msg = 1;
                    {
                        var error = $root.perfetto.protos.IPCFrame.RequestError.verify(message.msgRequestError);
                        if (error)
                            return "msgRequestError." + error;
                    }
                }
                if (message.dataForTesting != null && message.hasOwnProperty("dataForTesting")) {
                    if (!Array.isArray(message.dataForTesting))
                        return "dataForTesting: array expected";
                    for (var i = 0; i < message.dataForTesting.length; ++i)
                        if (!(message.dataForTesting[i] && typeof message.dataForTesting[i].length === "number" || $util.isString(message.dataForTesting[i])))
                            return "dataForTesting: buffer[] expected";
                }
                return null;
            };

            /**
             * Creates a IPCFrame message from a plain object. Also converts values to their respective internal types.
             * @function fromObject
             * @memberof perfetto.protos.IPCFrame
             * @static
             * @param {Object.<string,*>} object Plain object
             * @returns {perfetto.protos.IPCFrame} IPCFrame
             */
            IPCFrame.fromObject = function fromObject(object) {
                if (object instanceof $root.perfetto.protos.IPCFrame)
                    return object;
                var message = new $root.perfetto.protos.IPCFrame();
                if (object.requestId != null)
                    if ($util.Long)
                        (message.requestId = $util.Long.fromValue(object.requestId)).unsigned = true;
                    else if (typeof object.requestId === "string")
                        message.requestId = parseInt(object.requestId, 10);
                    else if (typeof object.requestId === "number")
                        message.requestId = object.requestId;
                    else if (typeof object.requestId === "object")
                        message.requestId = new $util.LongBits(object.requestId.low >>> 0, object.requestId.high >>> 0).toNumber(true);
                if (object.msgBindService != null) {
                    if (typeof object.msgBindService !== "object")
                        throw TypeError(".perfetto.protos.IPCFrame.msgBindService: object expected");
                    message.msgBindService = $root.perfetto.protos.IPCFrame.BindService.fromObject(object.msgBindService);
                }
                if (object.msgBindServiceReply != null) {
                    if (typeof object.msgBindServiceReply !== "object")
                        throw TypeError(".perfetto.protos.IPCFrame.msgBindServiceReply: object expected");
                    message.msgBindServiceReply = $root.perfetto.protos.IPCFrame.BindServiceReply.fromObject(object.msgBindServiceReply);
                }
                if (object.msgInvokeMethod != null) {
                    if (typeof object.msgInvokeMethod !== "object")
                        throw TypeError(".perfetto.protos.IPCFrame.msgInvokeMethod: object expected");
                    message.msgInvokeMethod = $root.perfetto.protos.IPCFrame.InvokeMethod.fromObject(object.msgInvokeMethod);
                }
                if (object.msgInvokeMethodReply != null) {
                    if (typeof object.msgInvokeMethodReply !== "object")
                        throw TypeError(".perfetto.protos.IPCFrame.msgInvokeMethodReply: object expected");
                    message.msgInvokeMethodReply = $root.perfetto.protos.IPCFrame.InvokeMethodReply.fromObject(object.msgInvokeMethodReply);
                }
                if (object.msgRequestError != null) {
                    if (typeof object.msgRequestError !== "object")
                        throw TypeError(".perfetto.protos.IPCFrame.msgRequestError: object expected");
                    message.msgRequestError = $root.perfetto.protos.IPCFrame.RequestError.fromObject(object.msgRequestError);
                }
                if (object.dataForTesting) {
                    if (!Array.isArray(object.dataForTesting))
                        throw TypeError(".perfetto.protos.IPCFrame.dataForTesting: array expected");
                    message.dataForTesting = [];
                    for (var i = 0; i < object.dataForTesting.length; ++i)
                        if (typeof object.dataForTesting[i] === "string")
                            $util.base64.decode(object.dataForTesting[i], message.dataForTesting[i] = $util.newBuffer($util.base64.length(object.dataForTesting[i])), 0);
                        else if (object.dataForTesting[i].length)
                            message.dataForTesting[i] = object.dataForTesting[i];
                }
                return message;
            };

            /**
             * Creates a plain object from a IPCFrame message. Also converts values to other types if specified.
             * @function toObject
             * @memberof perfetto.protos.IPCFrame
             * @static
             * @param {perfetto.protos.IPCFrame} message IPCFrame
             * @param {$protobuf.IConversionOptions} [options] Conversion options
             * @returns {Object.<string,*>} Plain object
             */
            IPCFrame.toObject = function toObject(message, options) {
                if (!options)
                    options = {};
                var object = {};
                if (options.arrays || options.defaults)
                    object.dataForTesting = [];
                if (options.defaults)
                    if ($util.Long) {
                        var long = new $util.Long(0, 0, true);
                        object.requestId = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
                    } else
                        object.requestId = options.longs === String ? "0" : 0;
                if (message.dataForTesting && message.dataForTesting.length) {
                    object.dataForTesting = [];
                    for (var j = 0; j < message.dataForTesting.length; ++j)
                        object.dataForTesting[j] = options.bytes === String ? $util.base64.encode(message.dataForTesting[j], 0, message.dataForTesting[j].length) : options.bytes === Array ? Array.prototype.slice.call(message.dataForTesting[j]) : message.dataForTesting[j];
                }
                if (message.requestId != null && message.hasOwnProperty("requestId"))
                    if (typeof message.requestId === "number")
                        object.requestId = options.longs === String ? String(message.requestId) : message.requestId;
                    else
                        object.requestId = options.longs === String ? $util.Long.prototype.toString.call(message.requestId) : options.longs === Number ? new $util.LongBits(message.requestId.low >>> 0, message.requestId.high >>> 0).toNumber(true) : message.requestId;
                if (message.msgBindService != null && message.hasOwnProperty("msgBindService")) {
                    object.msgBindService = $root.perfetto.protos.IPCFrame.BindService.toObject(message.msgBindService, options);
                    if (options.oneofs)
                        object.msg = "msgBindService";
                }
                if (message.msgBindServiceReply != null && message.hasOwnProperty("msgBindServiceReply")) {
                    object.msgBindServiceReply = $root.perfetto.protos.IPCFrame.BindServiceReply.toObject(message.msgBindServiceReply, options);
                    if (options.oneofs)
                        object.msg = "msgBindServiceReply";
                }
                if (message.msgInvokeMethod != null && message.hasOwnProperty("msgInvokeMethod")) {
                    object.msgInvokeMethod = $root.perfetto.protos.IPCFrame.InvokeMethod.toObject(message.msgInvokeMethod, options);
                    if (options.oneofs)
                        object.msg = "msgInvokeMethod";
                }
                if (message.msgInvokeMethodReply != null && message.hasOwnProperty("msgInvokeMethodReply")) {
                    object.msgInvokeMethodReply = $root.perfetto.protos.IPCFrame.InvokeMethodReply.toObject(message.msgInvokeMethodReply, options);
                    if (options.oneofs)
                        object.msg = "msgInvokeMethodReply";
                }
                if (message.msgRequestError != null && message.hasOwnProperty("msgRequestError")) {
                    object.msgRequestError = $root.perfetto.protos.IPCFrame.RequestError.toObject(message.msgRequestError, options);
                    if (options.oneofs)
                        object.msg = "msgRequestError";
                }
                return object;
            };

            /**
             * Converts this IPCFrame to JSON.
             * @function toJSON
             * @memberof perfetto.protos.IPCFrame
             * @instance
             * @returns {Object.<string,*>} JSON object
             */
            IPCFrame.prototype.toJSON = function toJSON() {
                return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
            };

            IPCFrame.BindService = (function() {

                /**
                 * Properties of a BindService.
                 * @memberof perfetto.protos.IPCFrame
                 * @interface IBindService
                 * @property {string|null} [serviceName] BindService serviceName
                 */

                /**
                 * Constructs a new BindService.
                 * @memberof perfetto.protos.IPCFrame
                 * @classdesc Represents a BindService.
                 * @implements IBindService
                 * @constructor
                 * @param {perfetto.protos.IPCFrame.IBindService=} [properties] Properties to set
                 */
                function BindService(properties) {
                    if (properties)
                        for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                            if (properties[keys[i]] != null)
                                this[keys[i]] = properties[keys[i]];
                }

                /**
                 * BindService serviceName.
                 * @member {string} serviceName
                 * @memberof perfetto.protos.IPCFrame.BindService
                 * @instance
                 */
                BindService.prototype.serviceName = "";

                /**
                 * Creates a new BindService instance using the specified properties.
                 * @function create
                 * @memberof perfetto.protos.IPCFrame.BindService
                 * @static
                 * @param {perfetto.protos.IPCFrame.IBindService=} [properties] Properties to set
                 * @returns {perfetto.protos.IPCFrame.BindService} BindService instance
                 */
                BindService.create = function create(properties) {
                    return new BindService(properties);
                };

                /**
                 * Encodes the specified BindService message. Does not implicitly {@link perfetto.protos.IPCFrame.BindService.verify|verify} messages.
                 * @function encode
                 * @memberof perfetto.protos.IPCFrame.BindService
                 * @static
                 * @param {perfetto.protos.IPCFrame.IBindService} message BindService message or plain object to encode
                 * @param {$protobuf.Writer} [writer] Writer to encode to
                 * @returns {$protobuf.Writer} Writer
                 */
                BindService.encode = function encode(message, writer) {
                    if (!writer)
                        writer = $Writer.create();
                    if (message.serviceName != null && Object.hasOwnProperty.call(message, "serviceName"))
                        writer.uint32(/* id 1, wireType 2 =*/10).string(message.serviceName);
                    return writer;
                };

                /**
                 * Encodes the specified BindService message, length delimited. Does not implicitly {@link perfetto.protos.IPCFrame.BindService.verify|verify} messages.
                 * @function encodeDelimited
                 * @memberof perfetto.protos.IPCFrame.BindService
                 * @static
                 * @param {perfetto.protos.IPCFrame.IBindService} message BindService message or plain object to encode
                 * @param {$protobuf.Writer} [writer] Writer to encode to
                 * @returns {$protobuf.Writer} Writer
                 */
                BindService.encodeDelimited = function encodeDelimited(message, writer) {
                    return this.encode(message, writer).ldelim();
                };

                /**
                 * Decodes a BindService message from the specified reader or buffer.
                 * @function decode
                 * @memberof perfetto.protos.IPCFrame.BindService
                 * @static
                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                 * @param {number} [length] Message length if known beforehand
                 * @returns {perfetto.protos.IPCFrame.BindService} BindService
                 * @throws {Error} If the payload is not a reader or valid buffer
                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
                 */
                BindService.decode = function decode(reader, length) {
                    if (!(reader instanceof $Reader))
                        reader = $Reader.create(reader);
                    var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.IPCFrame.BindService();
                    while (reader.pos < end) {
                        var tag = reader.uint32();
                        switch (tag >>> 3) {
                        case 1:
                            message.serviceName = reader.string();
                            break;
                        default:
                            reader.skipType(tag & 7);
                            break;
                        }
                    }
                    return message;
                };

                /**
                 * Decodes a BindService message from the specified reader or buffer, length delimited.
                 * @function decodeDelimited
                 * @memberof perfetto.protos.IPCFrame.BindService
                 * @static
                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                 * @returns {perfetto.protos.IPCFrame.BindService} BindService
                 * @throws {Error} If the payload is not a reader or valid buffer
                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
                 */
                BindService.decodeDelimited = function decodeDelimited(reader) {
                    if (!(reader instanceof $Reader))
                        reader = new $Reader(reader);
                    return this.decode(reader, reader.uint32());
                };

                /**
                 * Verifies a BindService message.
                 * @function verify
                 * @memberof perfetto.protos.IPCFrame.BindService
                 * @static
                 * @param {Object.<string,*>} message Plain object to verify
                 * @returns {string|null} `null` if valid, otherwise the reason why it is not
                 */
                BindService.verify = function verify(message) {
                    if (typeof message !== "object" || message === null)
                        return "object expected";
                    if (message.serviceName != null && message.hasOwnProperty("serviceName"))
                        if (!$util.isString(message.serviceName))
                            return "serviceName: string expected";
                    return null;
                };

                /**
                 * Creates a BindService message from a plain object. Also converts values to their respective internal types.
                 * @function fromObject
                 * @memberof perfetto.protos.IPCFrame.BindService
                 * @static
                 * @param {Object.<string,*>} object Plain object
                 * @returns {perfetto.protos.IPCFrame.BindService} BindService
                 */
                BindService.fromObject = function fromObject(object) {
                    if (object instanceof $root.perfetto.protos.IPCFrame.BindService)
                        return object;
                    var message = new $root.perfetto.protos.IPCFrame.BindService();
                    if (object.serviceName != null)
                        message.serviceName = String(object.serviceName);
                    return message;
                };

                /**
                 * Creates a plain object from a BindService message. Also converts values to other types if specified.
                 * @function toObject
                 * @memberof perfetto.protos.IPCFrame.BindService
                 * @static
                 * @param {perfetto.protos.IPCFrame.BindService} message BindService
                 * @param {$protobuf.IConversionOptions} [options] Conversion options
                 * @returns {Object.<string,*>} Plain object
                 */
                BindService.toObject = function toObject(message, options) {
                    if (!options)
                        options = {};
                    var object = {};
                    if (options.defaults)
                        object.serviceName = "";
                    if (message.serviceName != null && message.hasOwnProperty("serviceName"))
                        object.serviceName = message.serviceName;
                    return object;
                };

                /**
                 * Converts this BindService to JSON.
                 * @function toJSON
                 * @memberof perfetto.protos.IPCFrame.BindService
                 * @instance
                 * @returns {Object.<string,*>} JSON object
                 */
                BindService.prototype.toJSON = function toJSON() {
                    return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
                };

                return BindService;
            })();

            IPCFrame.BindServiceReply = (function() {

                /**
                 * Properties of a BindServiceReply.
                 * @memberof perfetto.protos.IPCFrame
                 * @interface IBindServiceReply
                 * @property {boolean|null} [success] BindServiceReply success
                 * @property {number|null} [serviceId] BindServiceReply serviceId
                 * @property {Array.<perfetto.protos.IPCFrame.BindServiceReply.IMethodInfo>|null} [methods] BindServiceReply methods
                 */

                /**
                 * Constructs a new BindServiceReply.
                 * @memberof perfetto.protos.IPCFrame
                 * @classdesc Represents a BindServiceReply.
                 * @implements IBindServiceReply
                 * @constructor
                 * @param {perfetto.protos.IPCFrame.IBindServiceReply=} [properties] Properties to set
                 */
                function BindServiceReply(properties) {
                    this.methods = [];
                    if (properties)
                        for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                            if (properties[keys[i]] != null)
                                this[keys[i]] = properties[keys[i]];
                }

                /**
                 * BindServiceReply success.
                 * @member {boolean} success
                 * @memberof perfetto.protos.IPCFrame.BindServiceReply
                 * @instance
                 */
                BindServiceReply.prototype.success = false;

                /**
                 * BindServiceReply serviceId.
                 * @member {number} serviceId
                 * @memberof perfetto.protos.IPCFrame.BindServiceReply
                 * @instance
                 */
                BindServiceReply.prototype.serviceId = 0;

                /**
                 * BindServiceReply methods.
                 * @member {Array.<perfetto.protos.IPCFrame.BindServiceReply.IMethodInfo>} methods
                 * @memberof perfetto.protos.IPCFrame.BindServiceReply
                 * @instance
                 */
                BindServiceReply.prototype.methods = $util.emptyArray;

                /**
                 * Creates a new BindServiceReply instance using the specified properties.
                 * @function create
                 * @memberof perfetto.protos.IPCFrame.BindServiceReply
                 * @static
                 * @param {perfetto.protos.IPCFrame.IBindServiceReply=} [properties] Properties to set
                 * @returns {perfetto.protos.IPCFrame.BindServiceReply} BindServiceReply instance
                 */
                BindServiceReply.create = function create(properties) {
                    return new BindServiceReply(properties);
                };

                /**
                 * Encodes the specified BindServiceReply message. Does not implicitly {@link perfetto.protos.IPCFrame.BindServiceReply.verify|verify} messages.
                 * @function encode
                 * @memberof perfetto.protos.IPCFrame.BindServiceReply
                 * @static
                 * @param {perfetto.protos.IPCFrame.IBindServiceReply} message BindServiceReply message or plain object to encode
                 * @param {$protobuf.Writer} [writer] Writer to encode to
                 * @returns {$protobuf.Writer} Writer
                 */
                BindServiceReply.encode = function encode(message, writer) {
                    if (!writer)
                        writer = $Writer.create();
                    if (message.success != null && Object.hasOwnProperty.call(message, "success"))
                        writer.uint32(/* id 1, wireType 0 =*/8).bool(message.success);
                    if (message.serviceId != null && Object.hasOwnProperty.call(message, "serviceId"))
                        writer.uint32(/* id 2, wireType 0 =*/16).uint32(message.serviceId);
                    if (message.methods != null && message.methods.length)
                        for (var i = 0; i < message.methods.length; ++i)
                            $root.perfetto.protos.IPCFrame.BindServiceReply.MethodInfo.encode(message.methods[i], writer.uint32(/* id 3, wireType 2 =*/26).fork()).ldelim();
                    return writer;
                };

                /**
                 * Encodes the specified BindServiceReply message, length delimited. Does not implicitly {@link perfetto.protos.IPCFrame.BindServiceReply.verify|verify} messages.
                 * @function encodeDelimited
                 * @memberof perfetto.protos.IPCFrame.BindServiceReply
                 * @static
                 * @param {perfetto.protos.IPCFrame.IBindServiceReply} message BindServiceReply message or plain object to encode
                 * @param {$protobuf.Writer} [writer] Writer to encode to
                 * @returns {$protobuf.Writer} Writer
                 */
                BindServiceReply.encodeDelimited = function encodeDelimited(message, writer) {
                    return this.encode(message, writer).ldelim();
                };

                /**
                 * Decodes a BindServiceReply message from the specified reader or buffer.
                 * @function decode
                 * @memberof perfetto.protos.IPCFrame.BindServiceReply
                 * @static
                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                 * @param {number} [length] Message length if known beforehand
                 * @returns {perfetto.protos.IPCFrame.BindServiceReply} BindServiceReply
                 * @throws {Error} If the payload is not a reader or valid buffer
                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
                 */
                BindServiceReply.decode = function decode(reader, length) {
                    if (!(reader instanceof $Reader))
                        reader = $Reader.create(reader);
                    var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.IPCFrame.BindServiceReply();
                    while (reader.pos < end) {
                        var tag = reader.uint32();
                        switch (tag >>> 3) {
                        case 1:
                            message.success = reader.bool();
                            break;
                        case 2:
                            message.serviceId = reader.uint32();
                            break;
                        case 3:
                            if (!(message.methods && message.methods.length))
                                message.methods = [];
                            message.methods.push($root.perfetto.protos.IPCFrame.BindServiceReply.MethodInfo.decode(reader, reader.uint32()));
                            break;
                        default:
                            reader.skipType(tag & 7);
                            break;
                        }
                    }
                    return message;
                };

                /**
                 * Decodes a BindServiceReply message from the specified reader or buffer, length delimited.
                 * @function decodeDelimited
                 * @memberof perfetto.protos.IPCFrame.BindServiceReply
                 * @static
                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                 * @returns {perfetto.protos.IPCFrame.BindServiceReply} BindServiceReply
                 * @throws {Error} If the payload is not a reader or valid buffer
                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
                 */
                BindServiceReply.decodeDelimited = function decodeDelimited(reader) {
                    if (!(reader instanceof $Reader))
                        reader = new $Reader(reader);
                    return this.decode(reader, reader.uint32());
                };

                /**
                 * Verifies a BindServiceReply message.
                 * @function verify
                 * @memberof perfetto.protos.IPCFrame.BindServiceReply
                 * @static
                 * @param {Object.<string,*>} message Plain object to verify
                 * @returns {string|null} `null` if valid, otherwise the reason why it is not
                 */
                BindServiceReply.verify = function verify(message) {
                    if (typeof message !== "object" || message === null)
                        return "object expected";
                    if (message.success != null && message.hasOwnProperty("success"))
                        if (typeof message.success !== "boolean")
                            return "success: boolean expected";
                    if (message.serviceId != null && message.hasOwnProperty("serviceId"))
                        if (!$util.isInteger(message.serviceId))
                            return "serviceId: integer expected";
                    if (message.methods != null && message.hasOwnProperty("methods")) {
                        if (!Array.isArray(message.methods))
                            return "methods: array expected";
                        for (var i = 0; i < message.methods.length; ++i) {
                            var error = $root.perfetto.protos.IPCFrame.BindServiceReply.MethodInfo.verify(message.methods[i]);
                            if (error)
                                return "methods." + error;
                        }
                    }
                    return null;
                };

                /**
                 * Creates a BindServiceReply message from a plain object. Also converts values to their respective internal types.
                 * @function fromObject
                 * @memberof perfetto.protos.IPCFrame.BindServiceReply
                 * @static
                 * @param {Object.<string,*>} object Plain object
                 * @returns {perfetto.protos.IPCFrame.BindServiceReply} BindServiceReply
                 */
                BindServiceReply.fromObject = function fromObject(object) {
                    if (object instanceof $root.perfetto.protos.IPCFrame.BindServiceReply)
                        return object;
                    var message = new $root.perfetto.protos.IPCFrame.BindServiceReply();
                    if (object.success != null)
                        message.success = Boolean(object.success);
                    if (object.serviceId != null)
                        message.serviceId = object.serviceId >>> 0;
                    if (object.methods) {
                        if (!Array.isArray(object.methods))
                            throw TypeError(".perfetto.protos.IPCFrame.BindServiceReply.methods: array expected");
                        message.methods = [];
                        for (var i = 0; i < object.methods.length; ++i) {
                            if (typeof object.methods[i] !== "object")
                                throw TypeError(".perfetto.protos.IPCFrame.BindServiceReply.methods: object expected");
                            message.methods[i] = $root.perfetto.protos.IPCFrame.BindServiceReply.MethodInfo.fromObject(object.methods[i]);
                        }
                    }
                    return message;
                };

                /**
                 * Creates a plain object from a BindServiceReply message. Also converts values to other types if specified.
                 * @function toObject
                 * @memberof perfetto.protos.IPCFrame.BindServiceReply
                 * @static
                 * @param {perfetto.protos.IPCFrame.BindServiceReply} message BindServiceReply
                 * @param {$protobuf.IConversionOptions} [options] Conversion options
                 * @returns {Object.<string,*>} Plain object
                 */
                BindServiceReply.toObject = function toObject(message, options) {
                    if (!options)
                        options = {};
                    var object = {};
                    if (options.arrays || options.defaults)
                        object.methods = [];
                    if (options.defaults) {
                        object.success = false;
                        object.serviceId = 0;
                    }
                    if (message.success != null && message.hasOwnProperty("success"))
                        object.success = message.success;
                    if (message.serviceId != null && message.hasOwnProperty("serviceId"))
                        object.serviceId = message.serviceId;
                    if (message.methods && message.methods.length) {
                        object.methods = [];
                        for (var j = 0; j < message.methods.length; ++j)
                            object.methods[j] = $root.perfetto.protos.IPCFrame.BindServiceReply.MethodInfo.toObject(message.methods[j], options);
                    }
                    return object;
                };

                /**
                 * Converts this BindServiceReply to JSON.
                 * @function toJSON
                 * @memberof perfetto.protos.IPCFrame.BindServiceReply
                 * @instance
                 * @returns {Object.<string,*>} JSON object
                 */
                BindServiceReply.prototype.toJSON = function toJSON() {
                    return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
                };

                BindServiceReply.MethodInfo = (function() {

                    /**
                     * Properties of a MethodInfo.
                     * @memberof perfetto.protos.IPCFrame.BindServiceReply
                     * @interface IMethodInfo
                     * @property {number|null} [id] MethodInfo id
                     * @property {string|null} [name] MethodInfo name
                     */

                    /**
                     * Constructs a new MethodInfo.
                     * @memberof perfetto.protos.IPCFrame.BindServiceReply
                     * @classdesc Represents a MethodInfo.
                     * @implements IMethodInfo
                     * @constructor
                     * @param {perfetto.protos.IPCFrame.BindServiceReply.IMethodInfo=} [properties] Properties to set
                     */
                    function MethodInfo(properties) {
                        if (properties)
                            for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                                if (properties[keys[i]] != null)
                                    this[keys[i]] = properties[keys[i]];
                    }

                    /**
                     * MethodInfo id.
                     * @member {number} id
                     * @memberof perfetto.protos.IPCFrame.BindServiceReply.MethodInfo
                     * @instance
                     */
                    MethodInfo.prototype.id = 0;

                    /**
                     * MethodInfo name.
                     * @member {string} name
                     * @memberof perfetto.protos.IPCFrame.BindServiceReply.MethodInfo
                     * @instance
                     */
                    MethodInfo.prototype.name = "";

                    /**
                     * Creates a new MethodInfo instance using the specified properties.
                     * @function create
                     * @memberof perfetto.protos.IPCFrame.BindServiceReply.MethodInfo
                     * @static
                     * @param {perfetto.protos.IPCFrame.BindServiceReply.IMethodInfo=} [properties] Properties to set
                     * @returns {perfetto.protos.IPCFrame.BindServiceReply.MethodInfo} MethodInfo instance
                     */
                    MethodInfo.create = function create(properties) {
                        return new MethodInfo(properties);
                    };

                    /**
                     * Encodes the specified MethodInfo message. Does not implicitly {@link perfetto.protos.IPCFrame.BindServiceReply.MethodInfo.verify|verify} messages.
                     * @function encode
                     * @memberof perfetto.protos.IPCFrame.BindServiceReply.MethodInfo
                     * @static
                     * @param {perfetto.protos.IPCFrame.BindServiceReply.IMethodInfo} message MethodInfo message or plain object to encode
                     * @param {$protobuf.Writer} [writer] Writer to encode to
                     * @returns {$protobuf.Writer} Writer
                     */
                    MethodInfo.encode = function encode(message, writer) {
                        if (!writer)
                            writer = $Writer.create();
                        if (message.id != null && Object.hasOwnProperty.call(message, "id"))
                            writer.uint32(/* id 1, wireType 0 =*/8).uint32(message.id);
                        if (message.name != null && Object.hasOwnProperty.call(message, "name"))
                            writer.uint32(/* id 2, wireType 2 =*/18).string(message.name);
                        return writer;
                    };

                    /**
                     * Encodes the specified MethodInfo message, length delimited. Does not implicitly {@link perfetto.protos.IPCFrame.BindServiceReply.MethodInfo.verify|verify} messages.
                     * @function encodeDelimited
                     * @memberof perfetto.protos.IPCFrame.BindServiceReply.MethodInfo
                     * @static
                     * @param {perfetto.protos.IPCFrame.BindServiceReply.IMethodInfo} message MethodInfo message or plain object to encode
                     * @param {$protobuf.Writer} [writer] Writer to encode to
                     * @returns {$protobuf.Writer} Writer
                     */
                    MethodInfo.encodeDelimited = function encodeDelimited(message, writer) {
                        return this.encode(message, writer).ldelim();
                    };

                    /**
                     * Decodes a MethodInfo message from the specified reader or buffer.
                     * @function decode
                     * @memberof perfetto.protos.IPCFrame.BindServiceReply.MethodInfo
                     * @static
                     * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                     * @param {number} [length] Message length if known beforehand
                     * @returns {perfetto.protos.IPCFrame.BindServiceReply.MethodInfo} MethodInfo
                     * @throws {Error} If the payload is not a reader or valid buffer
                     * @throws {$protobuf.util.ProtocolError} If required fields are missing
                     */
                    MethodInfo.decode = function decode(reader, length) {
                        if (!(reader instanceof $Reader))
                            reader = $Reader.create(reader);
                        var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.IPCFrame.BindServiceReply.MethodInfo();
                        while (reader.pos < end) {
                            var tag = reader.uint32();
                            switch (tag >>> 3) {
                            case 1:
                                message.id = reader.uint32();
                                break;
                            case 2:
                                message.name = reader.string();
                                break;
                            default:
                                reader.skipType(tag & 7);
                                break;
                            }
                        }
                        return message;
                    };

                    /**
                     * Decodes a MethodInfo message from the specified reader or buffer, length delimited.
                     * @function decodeDelimited
                     * @memberof perfetto.protos.IPCFrame.BindServiceReply.MethodInfo
                     * @static
                     * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                     * @returns {perfetto.protos.IPCFrame.BindServiceReply.MethodInfo} MethodInfo
                     * @throws {Error} If the payload is not a reader or valid buffer
                     * @throws {$protobuf.util.ProtocolError} If required fields are missing
                     */
                    MethodInfo.decodeDelimited = function decodeDelimited(reader) {
                        if (!(reader instanceof $Reader))
                            reader = new $Reader(reader);
                        return this.decode(reader, reader.uint32());
                    };

                    /**
                     * Verifies a MethodInfo message.
                     * @function verify
                     * @memberof perfetto.protos.IPCFrame.BindServiceReply.MethodInfo
                     * @static
                     * @param {Object.<string,*>} message Plain object to verify
                     * @returns {string|null} `null` if valid, otherwise the reason why it is not
                     */
                    MethodInfo.verify = function verify(message) {
                        if (typeof message !== "object" || message === null)
                            return "object expected";
                        if (message.id != null && message.hasOwnProperty("id"))
                            if (!$util.isInteger(message.id))
                                return "id: integer expected";
                        if (message.name != null && message.hasOwnProperty("name"))
                            if (!$util.isString(message.name))
                                return "name: string expected";
                        return null;
                    };

                    /**
                     * Creates a MethodInfo message from a plain object. Also converts values to their respective internal types.
                     * @function fromObject
                     * @memberof perfetto.protos.IPCFrame.BindServiceReply.MethodInfo
                     * @static
                     * @param {Object.<string,*>} object Plain object
                     * @returns {perfetto.protos.IPCFrame.BindServiceReply.MethodInfo} MethodInfo
                     */
                    MethodInfo.fromObject = function fromObject(object) {
                        if (object instanceof $root.perfetto.protos.IPCFrame.BindServiceReply.MethodInfo)
                            return object;
                        var message = new $root.perfetto.protos.IPCFrame.BindServiceReply.MethodInfo();
                        if (object.id != null)
                            message.id = object.id >>> 0;
                        if (object.name != null)
                            message.name = String(object.name);
                        return message;
                    };

                    /**
                     * Creates a plain object from a MethodInfo message. Also converts values to other types if specified.
                     * @function toObject
                     * @memberof perfetto.protos.IPCFrame.BindServiceReply.MethodInfo
                     * @static
                     * @param {perfetto.protos.IPCFrame.BindServiceReply.MethodInfo} message MethodInfo
                     * @param {$protobuf.IConversionOptions} [options] Conversion options
                     * @returns {Object.<string,*>} Plain object
                     */
                    MethodInfo.toObject = function toObject(message, options) {
                        if (!options)
                            options = {};
                        var object = {};
                        if (options.defaults) {
                            object.id = 0;
                            object.name = "";
                        }
                        if (message.id != null && message.hasOwnProperty("id"))
                            object.id = message.id;
                        if (message.name != null && message.hasOwnProperty("name"))
                            object.name = message.name;
                        return object;
                    };

                    /**
                     * Converts this MethodInfo to JSON.
                     * @function toJSON
                     * @memberof perfetto.protos.IPCFrame.BindServiceReply.MethodInfo
                     * @instance
                     * @returns {Object.<string,*>} JSON object
                     */
                    MethodInfo.prototype.toJSON = function toJSON() {
                        return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
                    };

                    return MethodInfo;
                })();

                return BindServiceReply;
            })();

            IPCFrame.InvokeMethod = (function() {

                /**
                 * Properties of an InvokeMethod.
                 * @memberof perfetto.protos.IPCFrame
                 * @interface IInvokeMethod
                 * @property {number|null} [serviceId] InvokeMethod serviceId
                 * @property {number|null} [methodId] InvokeMethod methodId
                 * @property {Uint8Array|null} [argsProto] InvokeMethod argsProto
                 * @property {boolean|null} [dropReply] InvokeMethod dropReply
                 */

                /**
                 * Constructs a new InvokeMethod.
                 * @memberof perfetto.protos.IPCFrame
                 * @classdesc Represents an InvokeMethod.
                 * @implements IInvokeMethod
                 * @constructor
                 * @param {perfetto.protos.IPCFrame.IInvokeMethod=} [properties] Properties to set
                 */
                function InvokeMethod(properties) {
                    if (properties)
                        for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                            if (properties[keys[i]] != null)
                                this[keys[i]] = properties[keys[i]];
                }

                /**
                 * InvokeMethod serviceId.
                 * @member {number} serviceId
                 * @memberof perfetto.protos.IPCFrame.InvokeMethod
                 * @instance
                 */
                InvokeMethod.prototype.serviceId = 0;

                /**
                 * InvokeMethod methodId.
                 * @member {number} methodId
                 * @memberof perfetto.protos.IPCFrame.InvokeMethod
                 * @instance
                 */
                InvokeMethod.prototype.methodId = 0;

                /**
                 * InvokeMethod argsProto.
                 * @member {Uint8Array} argsProto
                 * @memberof perfetto.protos.IPCFrame.InvokeMethod
                 * @instance
                 */
                InvokeMethod.prototype.argsProto = $util.newBuffer([]);

                /**
                 * InvokeMethod dropReply.
                 * @member {boolean} dropReply
                 * @memberof perfetto.protos.IPCFrame.InvokeMethod
                 * @instance
                 */
                InvokeMethod.prototype.dropReply = false;

                /**
                 * Creates a new InvokeMethod instance using the specified properties.
                 * @function create
                 * @memberof perfetto.protos.IPCFrame.InvokeMethod
                 * @static
                 * @param {perfetto.protos.IPCFrame.IInvokeMethod=} [properties] Properties to set
                 * @returns {perfetto.protos.IPCFrame.InvokeMethod} InvokeMethod instance
                 */
                InvokeMethod.create = function create(properties) {
                    return new InvokeMethod(properties);
                };

                /**
                 * Encodes the specified InvokeMethod message. Does not implicitly {@link perfetto.protos.IPCFrame.InvokeMethod.verify|verify} messages.
                 * @function encode
                 * @memberof perfetto.protos.IPCFrame.InvokeMethod
                 * @static
                 * @param {perfetto.protos.IPCFrame.IInvokeMethod} message InvokeMethod message or plain object to encode
                 * @param {$protobuf.Writer} [writer] Writer to encode to
                 * @returns {$protobuf.Writer} Writer
                 */
                InvokeMethod.encode = function encode(message, writer) {
                    if (!writer)
                        writer = $Writer.create();
                    if (message.serviceId != null && Object.hasOwnProperty.call(message, "serviceId"))
                        writer.uint32(/* id 1, wireType 0 =*/8).uint32(message.serviceId);
                    if (message.methodId != null && Object.hasOwnProperty.call(message, "methodId"))
                        writer.uint32(/* id 2, wireType 0 =*/16).uint32(message.methodId);
                    if (message.argsProto != null && Object.hasOwnProperty.call(message, "argsProto"))
                        writer.uint32(/* id 3, wireType 2 =*/26).bytes(message.argsProto);
                    if (message.dropReply != null && Object.hasOwnProperty.call(message, "dropReply"))
                        writer.uint32(/* id 4, wireType 0 =*/32).bool(message.dropReply);
                    return writer;
                };

                /**
                 * Encodes the specified InvokeMethod message, length delimited. Does not implicitly {@link perfetto.protos.IPCFrame.InvokeMethod.verify|verify} messages.
                 * @function encodeDelimited
                 * @memberof perfetto.protos.IPCFrame.InvokeMethod
                 * @static
                 * @param {perfetto.protos.IPCFrame.IInvokeMethod} message InvokeMethod message or plain object to encode
                 * @param {$protobuf.Writer} [writer] Writer to encode to
                 * @returns {$protobuf.Writer} Writer
                 */
                InvokeMethod.encodeDelimited = function encodeDelimited(message, writer) {
                    return this.encode(message, writer).ldelim();
                };

                /**
                 * Decodes an InvokeMethod message from the specified reader or buffer.
                 * @function decode
                 * @memberof perfetto.protos.IPCFrame.InvokeMethod
                 * @static
                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                 * @param {number} [length] Message length if known beforehand
                 * @returns {perfetto.protos.IPCFrame.InvokeMethod} InvokeMethod
                 * @throws {Error} If the payload is not a reader or valid buffer
                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
                 */
                InvokeMethod.decode = function decode(reader, length) {
                    if (!(reader instanceof $Reader))
                        reader = $Reader.create(reader);
                    var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.IPCFrame.InvokeMethod();
                    while (reader.pos < end) {
                        var tag = reader.uint32();
                        switch (tag >>> 3) {
                        case 1:
                            message.serviceId = reader.uint32();
                            break;
                        case 2:
                            message.methodId = reader.uint32();
                            break;
                        case 3:
                            message.argsProto = reader.bytes();
                            break;
                        case 4:
                            message.dropReply = reader.bool();
                            break;
                        default:
                            reader.skipType(tag & 7);
                            break;
                        }
                    }
                    return message;
                };

                /**
                 * Decodes an InvokeMethod message from the specified reader or buffer, length delimited.
                 * @function decodeDelimited
                 * @memberof perfetto.protos.IPCFrame.InvokeMethod
                 * @static
                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                 * @returns {perfetto.protos.IPCFrame.InvokeMethod} InvokeMethod
                 * @throws {Error} If the payload is not a reader or valid buffer
                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
                 */
                InvokeMethod.decodeDelimited = function decodeDelimited(reader) {
                    if (!(reader instanceof $Reader))
                        reader = new $Reader(reader);
                    return this.decode(reader, reader.uint32());
                };

                /**
                 * Verifies an InvokeMethod message.
                 * @function verify
                 * @memberof perfetto.protos.IPCFrame.InvokeMethod
                 * @static
                 * @param {Object.<string,*>} message Plain object to verify
                 * @returns {string|null} `null` if valid, otherwise the reason why it is not
                 */
                InvokeMethod.verify = function verify(message) {
                    if (typeof message !== "object" || message === null)
                        return "object expected";
                    if (message.serviceId != null && message.hasOwnProperty("serviceId"))
                        if (!$util.isInteger(message.serviceId))
                            return "serviceId: integer expected";
                    if (message.methodId != null && message.hasOwnProperty("methodId"))
                        if (!$util.isInteger(message.methodId))
                            return "methodId: integer expected";
                    if (message.argsProto != null && message.hasOwnProperty("argsProto"))
                        if (!(message.argsProto && typeof message.argsProto.length === "number" || $util.isString(message.argsProto)))
                            return "argsProto: buffer expected";
                    if (message.dropReply != null && message.hasOwnProperty("dropReply"))
                        if (typeof message.dropReply !== "boolean")
                            return "dropReply: boolean expected";
                    return null;
                };

                /**
                 * Creates an InvokeMethod message from a plain object. Also converts values to their respective internal types.
                 * @function fromObject
                 * @memberof perfetto.protos.IPCFrame.InvokeMethod
                 * @static
                 * @param {Object.<string,*>} object Plain object
                 * @returns {perfetto.protos.IPCFrame.InvokeMethod} InvokeMethod
                 */
                InvokeMethod.fromObject = function fromObject(object) {
                    if (object instanceof $root.perfetto.protos.IPCFrame.InvokeMethod)
                        return object;
                    var message = new $root.perfetto.protos.IPCFrame.InvokeMethod();
                    if (object.serviceId != null)
                        message.serviceId = object.serviceId >>> 0;
                    if (object.methodId != null)
                        message.methodId = object.methodId >>> 0;
                    if (object.argsProto != null)
                        if (typeof object.argsProto === "string")
                            $util.base64.decode(object.argsProto, message.argsProto = $util.newBuffer($util.base64.length(object.argsProto)), 0);
                        else if (object.argsProto.length)
                            message.argsProto = object.argsProto;
                    if (object.dropReply != null)
                        message.dropReply = Boolean(object.dropReply);
                    return message;
                };

                /**
                 * Creates a plain object from an InvokeMethod message. Also converts values to other types if specified.
                 * @function toObject
                 * @memberof perfetto.protos.IPCFrame.InvokeMethod
                 * @static
                 * @param {perfetto.protos.IPCFrame.InvokeMethod} message InvokeMethod
                 * @param {$protobuf.IConversionOptions} [options] Conversion options
                 * @returns {Object.<string,*>} Plain object
                 */
                InvokeMethod.toObject = function toObject(message, options) {
                    if (!options)
                        options = {};
                    var object = {};
                    if (options.defaults) {
                        object.serviceId = 0;
                        object.methodId = 0;
                        if (options.bytes === String)
                            object.argsProto = "";
                        else {
                            object.argsProto = [];
                            if (options.bytes !== Array)
                                object.argsProto = $util.newBuffer(object.argsProto);
                        }
                        object.dropReply = false;
                    }
                    if (message.serviceId != null && message.hasOwnProperty("serviceId"))
                        object.serviceId = message.serviceId;
                    if (message.methodId != null && message.hasOwnProperty("methodId"))
                        object.methodId = message.methodId;
                    if (message.argsProto != null && message.hasOwnProperty("argsProto"))
                        object.argsProto = options.bytes === String ? $util.base64.encode(message.argsProto, 0, message.argsProto.length) : options.bytes === Array ? Array.prototype.slice.call(message.argsProto) : message.argsProto;
                    if (message.dropReply != null && message.hasOwnProperty("dropReply"))
                        object.dropReply = message.dropReply;
                    return object;
                };

                /**
                 * Converts this InvokeMethod to JSON.
                 * @function toJSON
                 * @memberof perfetto.protos.IPCFrame.InvokeMethod
                 * @instance
                 * @returns {Object.<string,*>} JSON object
                 */
                InvokeMethod.prototype.toJSON = function toJSON() {
                    return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
                };

                return InvokeMethod;
            })();

            IPCFrame.InvokeMethodReply = (function() {

                /**
                 * Properties of an InvokeMethodReply.
                 * @memberof perfetto.protos.IPCFrame
                 * @interface IInvokeMethodReply
                 * @property {boolean|null} [success] InvokeMethodReply success
                 * @property {boolean|null} [hasMore] InvokeMethodReply hasMore
                 * @property {Uint8Array|null} [replyProto] InvokeMethodReply replyProto
                 */

                /**
                 * Constructs a new InvokeMethodReply.
                 * @memberof perfetto.protos.IPCFrame
                 * @classdesc Represents an InvokeMethodReply.
                 * @implements IInvokeMethodReply
                 * @constructor
                 * @param {perfetto.protos.IPCFrame.IInvokeMethodReply=} [properties] Properties to set
                 */
                function InvokeMethodReply(properties) {
                    if (properties)
                        for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                            if (properties[keys[i]] != null)
                                this[keys[i]] = properties[keys[i]];
                }

                /**
                 * InvokeMethodReply success.
                 * @member {boolean} success
                 * @memberof perfetto.protos.IPCFrame.InvokeMethodReply
                 * @instance
                 */
                InvokeMethodReply.prototype.success = false;

                /**
                 * InvokeMethodReply hasMore.
                 * @member {boolean} hasMore
                 * @memberof perfetto.protos.IPCFrame.InvokeMethodReply
                 * @instance
                 */
                InvokeMethodReply.prototype.hasMore = false;

                /**
                 * InvokeMethodReply replyProto.
                 * @member {Uint8Array} replyProto
                 * @memberof perfetto.protos.IPCFrame.InvokeMethodReply
                 * @instance
                 */
                InvokeMethodReply.prototype.replyProto = $util.newBuffer([]);

                /**
                 * Creates a new InvokeMethodReply instance using the specified properties.
                 * @function create
                 * @memberof perfetto.protos.IPCFrame.InvokeMethodReply
                 * @static
                 * @param {perfetto.protos.IPCFrame.IInvokeMethodReply=} [properties] Properties to set
                 * @returns {perfetto.protos.IPCFrame.InvokeMethodReply} InvokeMethodReply instance
                 */
                InvokeMethodReply.create = function create(properties) {
                    return new InvokeMethodReply(properties);
                };

                /**
                 * Encodes the specified InvokeMethodReply message. Does not implicitly {@link perfetto.protos.IPCFrame.InvokeMethodReply.verify|verify} messages.
                 * @function encode
                 * @memberof perfetto.protos.IPCFrame.InvokeMethodReply
                 * @static
                 * @param {perfetto.protos.IPCFrame.IInvokeMethodReply} message InvokeMethodReply message or plain object to encode
                 * @param {$protobuf.Writer} [writer] Writer to encode to
                 * @returns {$protobuf.Writer} Writer
                 */
                InvokeMethodReply.encode = function encode(message, writer) {
                    if (!writer)
                        writer = $Writer.create();
                    if (message.success != null && Object.hasOwnProperty.call(message, "success"))
                        writer.uint32(/* id 1, wireType 0 =*/8).bool(message.success);
                    if (message.hasMore != null && Object.hasOwnProperty.call(message, "hasMore"))
                        writer.uint32(/* id 2, wireType 0 =*/16).bool(message.hasMore);
                    if (message.replyProto != null && Object.hasOwnProperty.call(message, "replyProto"))
                        writer.uint32(/* id 3, wireType 2 =*/26).bytes(message.replyProto);
                    return writer;
                };

                /**
                 * Encodes the specified InvokeMethodReply message, length delimited. Does not implicitly {@link perfetto.protos.IPCFrame.InvokeMethodReply.verify|verify} messages.
                 * @function encodeDelimited
                 * @memberof perfetto.protos.IPCFrame.InvokeMethodReply
                 * @static
                 * @param {perfetto.protos.IPCFrame.IInvokeMethodReply} message InvokeMethodReply message or plain object to encode
                 * @param {$protobuf.Writer} [writer] Writer to encode to
                 * @returns {$protobuf.Writer} Writer
                 */
                InvokeMethodReply.encodeDelimited = function encodeDelimited(message, writer) {
                    return this.encode(message, writer).ldelim();
                };

                /**
                 * Decodes an InvokeMethodReply message from the specified reader or buffer.
                 * @function decode
                 * @memberof perfetto.protos.IPCFrame.InvokeMethodReply
                 * @static
                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                 * @param {number} [length] Message length if known beforehand
                 * @returns {perfetto.protos.IPCFrame.InvokeMethodReply} InvokeMethodReply
                 * @throws {Error} If the payload is not a reader or valid buffer
                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
                 */
                InvokeMethodReply.decode = function decode(reader, length) {
                    if (!(reader instanceof $Reader))
                        reader = $Reader.create(reader);
                    var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.IPCFrame.InvokeMethodReply();
                    while (reader.pos < end) {
                        var tag = reader.uint32();
                        switch (tag >>> 3) {
                        case 1:
                            message.success = reader.bool();
                            break;
                        case 2:
                            message.hasMore = reader.bool();
                            break;
                        case 3:
                            message.replyProto = reader.bytes();
                            break;
                        default:
                            reader.skipType(tag & 7);
                            break;
                        }
                    }
                    return message;
                };

                /**
                 * Decodes an InvokeMethodReply message from the specified reader or buffer, length delimited.
                 * @function decodeDelimited
                 * @memberof perfetto.protos.IPCFrame.InvokeMethodReply
                 * @static
                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                 * @returns {perfetto.protos.IPCFrame.InvokeMethodReply} InvokeMethodReply
                 * @throws {Error} If the payload is not a reader or valid buffer
                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
                 */
                InvokeMethodReply.decodeDelimited = function decodeDelimited(reader) {
                    if (!(reader instanceof $Reader))
                        reader = new $Reader(reader);
                    return this.decode(reader, reader.uint32());
                };

                /**
                 * Verifies an InvokeMethodReply message.
                 * @function verify
                 * @memberof perfetto.protos.IPCFrame.InvokeMethodReply
                 * @static
                 * @param {Object.<string,*>} message Plain object to verify
                 * @returns {string|null} `null` if valid, otherwise the reason why it is not
                 */
                InvokeMethodReply.verify = function verify(message) {
                    if (typeof message !== "object" || message === null)
                        return "object expected";
                    if (message.success != null && message.hasOwnProperty("success"))
                        if (typeof message.success !== "boolean")
                            return "success: boolean expected";
                    if (message.hasMore != null && message.hasOwnProperty("hasMore"))
                        if (typeof message.hasMore !== "boolean")
                            return "hasMore: boolean expected";
                    if (message.replyProto != null && message.hasOwnProperty("replyProto"))
                        if (!(message.replyProto && typeof message.replyProto.length === "number" || $util.isString(message.replyProto)))
                            return "replyProto: buffer expected";
                    return null;
                };

                /**
                 * Creates an InvokeMethodReply message from a plain object. Also converts values to their respective internal types.
                 * @function fromObject
                 * @memberof perfetto.protos.IPCFrame.InvokeMethodReply
                 * @static
                 * @param {Object.<string,*>} object Plain object
                 * @returns {perfetto.protos.IPCFrame.InvokeMethodReply} InvokeMethodReply
                 */
                InvokeMethodReply.fromObject = function fromObject(object) {
                    if (object instanceof $root.perfetto.protos.IPCFrame.InvokeMethodReply)
                        return object;
                    var message = new $root.perfetto.protos.IPCFrame.InvokeMethodReply();
                    if (object.success != null)
                        message.success = Boolean(object.success);
                    if (object.hasMore != null)
                        message.hasMore = Boolean(object.hasMore);
                    if (object.replyProto != null)
                        if (typeof object.replyProto === "string")
                            $util.base64.decode(object.replyProto, message.replyProto = $util.newBuffer($util.base64.length(object.replyProto)), 0);
                        else if (object.replyProto.length)
                            message.replyProto = object.replyProto;
                    return message;
                };

                /**
                 * Creates a plain object from an InvokeMethodReply message. Also converts values to other types if specified.
                 * @function toObject
                 * @memberof perfetto.protos.IPCFrame.InvokeMethodReply
                 * @static
                 * @param {perfetto.protos.IPCFrame.InvokeMethodReply} message InvokeMethodReply
                 * @param {$protobuf.IConversionOptions} [options] Conversion options
                 * @returns {Object.<string,*>} Plain object
                 */
                InvokeMethodReply.toObject = function toObject(message, options) {
                    if (!options)
                        options = {};
                    var object = {};
                    if (options.defaults) {
                        object.success = false;
                        object.hasMore = false;
                        if (options.bytes === String)
                            object.replyProto = "";
                        else {
                            object.replyProto = [];
                            if (options.bytes !== Array)
                                object.replyProto = $util.newBuffer(object.replyProto);
                        }
                    }
                    if (message.success != null && message.hasOwnProperty("success"))
                        object.success = message.success;
                    if (message.hasMore != null && message.hasOwnProperty("hasMore"))
                        object.hasMore = message.hasMore;
                    if (message.replyProto != null && message.hasOwnProperty("replyProto"))
                        object.replyProto = options.bytes === String ? $util.base64.encode(message.replyProto, 0, message.replyProto.length) : options.bytes === Array ? Array.prototype.slice.call(message.replyProto) : message.replyProto;
                    return object;
                };

                /**
                 * Converts this InvokeMethodReply to JSON.
                 * @function toJSON
                 * @memberof perfetto.protos.IPCFrame.InvokeMethodReply
                 * @instance
                 * @returns {Object.<string,*>} JSON object
                 */
                InvokeMethodReply.prototype.toJSON = function toJSON() {
                    return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
                };

                return InvokeMethodReply;
            })();

            IPCFrame.RequestError = (function() {

                /**
                 * Properties of a RequestError.
                 * @memberof perfetto.protos.IPCFrame
                 * @interface IRequestError
                 * @property {string|null} [error] RequestError error
                 */

                /**
                 * Constructs a new RequestError.
                 * @memberof perfetto.protos.IPCFrame
                 * @classdesc Represents a RequestError.
                 * @implements IRequestError
                 * @constructor
                 * @param {perfetto.protos.IPCFrame.IRequestError=} [properties] Properties to set
                 */
                function RequestError(properties) {
                    if (properties)
                        for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                            if (properties[keys[i]] != null)
                                this[keys[i]] = properties[keys[i]];
                }

                /**
                 * RequestError error.
                 * @member {string} error
                 * @memberof perfetto.protos.IPCFrame.RequestError
                 * @instance
                 */
                RequestError.prototype.error = "";

                /**
                 * Creates a new RequestError instance using the specified properties.
                 * @function create
                 * @memberof perfetto.protos.IPCFrame.RequestError
                 * @static
                 * @param {perfetto.protos.IPCFrame.IRequestError=} [properties] Properties to set
                 * @returns {perfetto.protos.IPCFrame.RequestError} RequestError instance
                 */
                RequestError.create = function create(properties) {
                    return new RequestError(properties);
                };

                /**
                 * Encodes the specified RequestError message. Does not implicitly {@link perfetto.protos.IPCFrame.RequestError.verify|verify} messages.
                 * @function encode
                 * @memberof perfetto.protos.IPCFrame.RequestError
                 * @static
                 * @param {perfetto.protos.IPCFrame.IRequestError} message RequestError message or plain object to encode
                 * @param {$protobuf.Writer} [writer] Writer to encode to
                 * @returns {$protobuf.Writer} Writer
                 */
                RequestError.encode = function encode(message, writer) {
                    if (!writer)
                        writer = $Writer.create();
                    if (message.error != null && Object.hasOwnProperty.call(message, "error"))
                        writer.uint32(/* id 1, wireType 2 =*/10).string(message.error);
                    return writer;
                };

                /**
                 * Encodes the specified RequestError message, length delimited. Does not implicitly {@link perfetto.protos.IPCFrame.RequestError.verify|verify} messages.
                 * @function encodeDelimited
                 * @memberof perfetto.protos.IPCFrame.RequestError
                 * @static
                 * @param {perfetto.protos.IPCFrame.IRequestError} message RequestError message or plain object to encode
                 * @param {$protobuf.Writer} [writer] Writer to encode to
                 * @returns {$protobuf.Writer} Writer
                 */
                RequestError.encodeDelimited = function encodeDelimited(message, writer) {
                    return this.encode(message, writer).ldelim();
                };

                /**
                 * Decodes a RequestError message from the specified reader or buffer.
                 * @function decode
                 * @memberof perfetto.protos.IPCFrame.RequestError
                 * @static
                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                 * @param {number} [length] Message length if known beforehand
                 * @returns {perfetto.protos.IPCFrame.RequestError} RequestError
                 * @throws {Error} If the payload is not a reader or valid buffer
                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
                 */
                RequestError.decode = function decode(reader, length) {
                    if (!(reader instanceof $Reader))
                        reader = $Reader.create(reader);
                    var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.IPCFrame.RequestError();
                    while (reader.pos < end) {
                        var tag = reader.uint32();
                        switch (tag >>> 3) {
                        case 1:
                            message.error = reader.string();
                            break;
                        default:
                            reader.skipType(tag & 7);
                            break;
                        }
                    }
                    return message;
                };

                /**
                 * Decodes a RequestError message from the specified reader or buffer, length delimited.
                 * @function decodeDelimited
                 * @memberof perfetto.protos.IPCFrame.RequestError
                 * @static
                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                 * @returns {perfetto.protos.IPCFrame.RequestError} RequestError
                 * @throws {Error} If the payload is not a reader or valid buffer
                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
                 */
                RequestError.decodeDelimited = function decodeDelimited(reader) {
                    if (!(reader instanceof $Reader))
                        reader = new $Reader(reader);
                    return this.decode(reader, reader.uint32());
                };

                /**
                 * Verifies a RequestError message.
                 * @function verify
                 * @memberof perfetto.protos.IPCFrame.RequestError
                 * @static
                 * @param {Object.<string,*>} message Plain object to verify
                 * @returns {string|null} `null` if valid, otherwise the reason why it is not
                 */
                RequestError.verify = function verify(message) {
                    if (typeof message !== "object" || message === null)
                        return "object expected";
                    if (message.error != null && message.hasOwnProperty("error"))
                        if (!$util.isString(message.error))
                            return "error: string expected";
                    return null;
                };

                /**
                 * Creates a RequestError message from a plain object. Also converts values to their respective internal types.
                 * @function fromObject
                 * @memberof perfetto.protos.IPCFrame.RequestError
                 * @static
                 * @param {Object.<string,*>} object Plain object
                 * @returns {perfetto.protos.IPCFrame.RequestError} RequestError
                 */
                RequestError.fromObject = function fromObject(object) {
                    if (object instanceof $root.perfetto.protos.IPCFrame.RequestError)
                        return object;
                    var message = new $root.perfetto.protos.IPCFrame.RequestError();
                    if (object.error != null)
                        message.error = String(object.error);
                    return message;
                };

                /**
                 * Creates a plain object from a RequestError message. Also converts values to other types if specified.
                 * @function toObject
                 * @memberof perfetto.protos.IPCFrame.RequestError
                 * @static
                 * @param {perfetto.protos.IPCFrame.RequestError} message RequestError
                 * @param {$protobuf.IConversionOptions} [options] Conversion options
                 * @returns {Object.<string,*>} Plain object
                 */
                RequestError.toObject = function toObject(message, options) {
                    if (!options)
                        options = {};
                    var object = {};
                    if (options.defaults)
                        object.error = "";
                    if (message.error != null && message.hasOwnProperty("error"))
                        object.error = message.error;
                    return object;
                };

                /**
                 * Converts this RequestError to JSON.
                 * @function toJSON
                 * @memberof perfetto.protos.IPCFrame.RequestError
                 * @instance
                 * @returns {Object.<string,*>} JSON object
                 */
                RequestError.prototype.toJSON = function toJSON() {
                    return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
                };

                return RequestError;
            })();

            return IPCFrame;
        })();

        protos.TraceMetadata = (function() {

            /**
             * Properties of a TraceMetadata.
             * @memberof perfetto.protos
             * @interface ITraceMetadata
             * @property {number|null} [traceDurationNs] TraceMetadata traceDurationNs
             * @property {string|null} [traceUuid] TraceMetadata traceUuid
             * @property {string|null} [androidBuildFingerprint] TraceMetadata androidBuildFingerprint
             * @property {number|null} [statsdTriggeringSubscriptionId] TraceMetadata statsdTriggeringSubscriptionId
             * @property {number|null} [traceSizeBytes] TraceMetadata traceSizeBytes
             * @property {Array.<string>|null} [traceTrigger] TraceMetadata traceTrigger
             * @property {string|null} [uniqueSessionName] TraceMetadata uniqueSessionName
             * @property {string|null} [traceConfigPbtxt] TraceMetadata traceConfigPbtxt
             * @property {number|null} [schedDurationNs] TraceMetadata schedDurationNs
             */

            /**
             * Constructs a new TraceMetadata.
             * @memberof perfetto.protos
             * @classdesc Represents a TraceMetadata.
             * @implements ITraceMetadata
             * @constructor
             * @param {perfetto.protos.ITraceMetadata=} [properties] Properties to set
             */
            function TraceMetadata(properties) {
                this.traceTrigger = [];
                if (properties)
                    for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                        if (properties[keys[i]] != null)
                            this[keys[i]] = properties[keys[i]];
            }

            /**
             * TraceMetadata traceDurationNs.
             * @member {number} traceDurationNs
             * @memberof perfetto.protos.TraceMetadata
             * @instance
             */
            TraceMetadata.prototype.traceDurationNs = $util.Long ? $util.Long.fromBits(0,0,false) : 0;

            /**
             * TraceMetadata traceUuid.
             * @member {string} traceUuid
             * @memberof perfetto.protos.TraceMetadata
             * @instance
             */
            TraceMetadata.prototype.traceUuid = "";

            /**
             * TraceMetadata androidBuildFingerprint.
             * @member {string} androidBuildFingerprint
             * @memberof perfetto.protos.TraceMetadata
             * @instance
             */
            TraceMetadata.prototype.androidBuildFingerprint = "";

            /**
             * TraceMetadata statsdTriggeringSubscriptionId.
             * @member {number} statsdTriggeringSubscriptionId
             * @memberof perfetto.protos.TraceMetadata
             * @instance
             */
            TraceMetadata.prototype.statsdTriggeringSubscriptionId = $util.Long ? $util.Long.fromBits(0,0,false) : 0;

            /**
             * TraceMetadata traceSizeBytes.
             * @member {number} traceSizeBytes
             * @memberof perfetto.protos.TraceMetadata
             * @instance
             */
            TraceMetadata.prototype.traceSizeBytes = $util.Long ? $util.Long.fromBits(0,0,false) : 0;

            /**
             * TraceMetadata traceTrigger.
             * @member {Array.<string>} traceTrigger
             * @memberof perfetto.protos.TraceMetadata
             * @instance
             */
            TraceMetadata.prototype.traceTrigger = $util.emptyArray;

            /**
             * TraceMetadata uniqueSessionName.
             * @member {string} uniqueSessionName
             * @memberof perfetto.protos.TraceMetadata
             * @instance
             */
            TraceMetadata.prototype.uniqueSessionName = "";

            /**
             * TraceMetadata traceConfigPbtxt.
             * @member {string} traceConfigPbtxt
             * @memberof perfetto.protos.TraceMetadata
             * @instance
             */
            TraceMetadata.prototype.traceConfigPbtxt = "";

            /**
             * TraceMetadata schedDurationNs.
             * @member {number} schedDurationNs
             * @memberof perfetto.protos.TraceMetadata
             * @instance
             */
            TraceMetadata.prototype.schedDurationNs = $util.Long ? $util.Long.fromBits(0,0,false) : 0;

            /**
             * Creates a new TraceMetadata instance using the specified properties.
             * @function create
             * @memberof perfetto.protos.TraceMetadata
             * @static
             * @param {perfetto.protos.ITraceMetadata=} [properties] Properties to set
             * @returns {perfetto.protos.TraceMetadata} TraceMetadata instance
             */
            TraceMetadata.create = function create(properties) {
                return new TraceMetadata(properties);
            };

            /**
             * Encodes the specified TraceMetadata message. Does not implicitly {@link perfetto.protos.TraceMetadata.verify|verify} messages.
             * @function encode
             * @memberof perfetto.protos.TraceMetadata
             * @static
             * @param {perfetto.protos.ITraceMetadata} message TraceMetadata message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            TraceMetadata.encode = function encode(message, writer) {
                if (!writer)
                    writer = $Writer.create();
                if (message.traceDurationNs != null && Object.hasOwnProperty.call(message, "traceDurationNs"))
                    writer.uint32(/* id 2, wireType 0 =*/16).int64(message.traceDurationNs);
                if (message.traceUuid != null && Object.hasOwnProperty.call(message, "traceUuid"))
                    writer.uint32(/* id 3, wireType 2 =*/26).string(message.traceUuid);
                if (message.androidBuildFingerprint != null && Object.hasOwnProperty.call(message, "androidBuildFingerprint"))
                    writer.uint32(/* id 4, wireType 2 =*/34).string(message.androidBuildFingerprint);
                if (message.statsdTriggeringSubscriptionId != null && Object.hasOwnProperty.call(message, "statsdTriggeringSubscriptionId"))
                    writer.uint32(/* id 5, wireType 0 =*/40).int64(message.statsdTriggeringSubscriptionId);
                if (message.traceSizeBytes != null && Object.hasOwnProperty.call(message, "traceSizeBytes"))
                    writer.uint32(/* id 6, wireType 0 =*/48).int64(message.traceSizeBytes);
                if (message.traceTrigger != null && message.traceTrigger.length)
                    for (var i = 0; i < message.traceTrigger.length; ++i)
                        writer.uint32(/* id 7, wireType 2 =*/58).string(message.traceTrigger[i]);
                if (message.uniqueSessionName != null && Object.hasOwnProperty.call(message, "uniqueSessionName"))
                    writer.uint32(/* id 8, wireType 2 =*/66).string(message.uniqueSessionName);
                if (message.traceConfigPbtxt != null && Object.hasOwnProperty.call(message, "traceConfigPbtxt"))
                    writer.uint32(/* id 9, wireType 2 =*/74).string(message.traceConfigPbtxt);
                if (message.schedDurationNs != null && Object.hasOwnProperty.call(message, "schedDurationNs"))
                    writer.uint32(/* id 10, wireType 0 =*/80).int64(message.schedDurationNs);
                return writer;
            };

            /**
             * Encodes the specified TraceMetadata message, length delimited. Does not implicitly {@link perfetto.protos.TraceMetadata.verify|verify} messages.
             * @function encodeDelimited
             * @memberof perfetto.protos.TraceMetadata
             * @static
             * @param {perfetto.protos.ITraceMetadata} message TraceMetadata message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            TraceMetadata.encodeDelimited = function encodeDelimited(message, writer) {
                return this.encode(message, writer).ldelim();
            };

            /**
             * Decodes a TraceMetadata message from the specified reader or buffer.
             * @function decode
             * @memberof perfetto.protos.TraceMetadata
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @param {number} [length] Message length if known beforehand
             * @returns {perfetto.protos.TraceMetadata} TraceMetadata
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            TraceMetadata.decode = function decode(reader, length) {
                if (!(reader instanceof $Reader))
                    reader = $Reader.create(reader);
                var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.TraceMetadata();
                while (reader.pos < end) {
                    var tag = reader.uint32();
                    switch (tag >>> 3) {
                    case 2:
                        message.traceDurationNs = reader.int64();
                        break;
                    case 3:
                        message.traceUuid = reader.string();
                        break;
                    case 4:
                        message.androidBuildFingerprint = reader.string();
                        break;
                    case 5:
                        message.statsdTriggeringSubscriptionId = reader.int64();
                        break;
                    case 6:
                        message.traceSizeBytes = reader.int64();
                        break;
                    case 7:
                        if (!(message.traceTrigger && message.traceTrigger.length))
                            message.traceTrigger = [];
                        message.traceTrigger.push(reader.string());
                        break;
                    case 8:
                        message.uniqueSessionName = reader.string();
                        break;
                    case 9:
                        message.traceConfigPbtxt = reader.string();
                        break;
                    case 10:
                        message.schedDurationNs = reader.int64();
                        break;
                    default:
                        reader.skipType(tag & 7);
                        break;
                    }
                }
                return message;
            };

            /**
             * Decodes a TraceMetadata message from the specified reader or buffer, length delimited.
             * @function decodeDelimited
             * @memberof perfetto.protos.TraceMetadata
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @returns {perfetto.protos.TraceMetadata} TraceMetadata
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            TraceMetadata.decodeDelimited = function decodeDelimited(reader) {
                if (!(reader instanceof $Reader))
                    reader = new $Reader(reader);
                return this.decode(reader, reader.uint32());
            };

            /**
             * Verifies a TraceMetadata message.
             * @function verify
             * @memberof perfetto.protos.TraceMetadata
             * @static
             * @param {Object.<string,*>} message Plain object to verify
             * @returns {string|null} `null` if valid, otherwise the reason why it is not
             */
            TraceMetadata.verify = function verify(message) {
                if (typeof message !== "object" || message === null)
                    return "object expected";
                if (message.traceDurationNs != null && message.hasOwnProperty("traceDurationNs"))
                    if (!$util.isInteger(message.traceDurationNs) && !(message.traceDurationNs && $util.isInteger(message.traceDurationNs.low) && $util.isInteger(message.traceDurationNs.high)))
                        return "traceDurationNs: integer|Long expected";
                if (message.traceUuid != null && message.hasOwnProperty("traceUuid"))
                    if (!$util.isString(message.traceUuid))
                        return "traceUuid: string expected";
                if (message.androidBuildFingerprint != null && message.hasOwnProperty("androidBuildFingerprint"))
                    if (!$util.isString(message.androidBuildFingerprint))
                        return "androidBuildFingerprint: string expected";
                if (message.statsdTriggeringSubscriptionId != null && message.hasOwnProperty("statsdTriggeringSubscriptionId"))
                    if (!$util.isInteger(message.statsdTriggeringSubscriptionId) && !(message.statsdTriggeringSubscriptionId && $util.isInteger(message.statsdTriggeringSubscriptionId.low) && $util.isInteger(message.statsdTriggeringSubscriptionId.high)))
                        return "statsdTriggeringSubscriptionId: integer|Long expected";
                if (message.traceSizeBytes != null && message.hasOwnProperty("traceSizeBytes"))
                    if (!$util.isInteger(message.traceSizeBytes) && !(message.traceSizeBytes && $util.isInteger(message.traceSizeBytes.low) && $util.isInteger(message.traceSizeBytes.high)))
                        return "traceSizeBytes: integer|Long expected";
                if (message.traceTrigger != null && message.hasOwnProperty("traceTrigger")) {
                    if (!Array.isArray(message.traceTrigger))
                        return "traceTrigger: array expected";
                    for (var i = 0; i < message.traceTrigger.length; ++i)
                        if (!$util.isString(message.traceTrigger[i]))
                            return "traceTrigger: string[] expected";
                }
                if (message.uniqueSessionName != null && message.hasOwnProperty("uniqueSessionName"))
                    if (!$util.isString(message.uniqueSessionName))
                        return "uniqueSessionName: string expected";
                if (message.traceConfigPbtxt != null && message.hasOwnProperty("traceConfigPbtxt"))
                    if (!$util.isString(message.traceConfigPbtxt))
                        return "traceConfigPbtxt: string expected";
                if (message.schedDurationNs != null && message.hasOwnProperty("schedDurationNs"))
                    if (!$util.isInteger(message.schedDurationNs) && !(message.schedDurationNs && $util.isInteger(message.schedDurationNs.low) && $util.isInteger(message.schedDurationNs.high)))
                        return "schedDurationNs: integer|Long expected";
                return null;
            };

            /**
             * Creates a TraceMetadata message from a plain object. Also converts values to their respective internal types.
             * @function fromObject
             * @memberof perfetto.protos.TraceMetadata
             * @static
             * @param {Object.<string,*>} object Plain object
             * @returns {perfetto.protos.TraceMetadata} TraceMetadata
             */
            TraceMetadata.fromObject = function fromObject(object) {
                if (object instanceof $root.perfetto.protos.TraceMetadata)
                    return object;
                var message = new $root.perfetto.protos.TraceMetadata();
                if (object.traceDurationNs != null)
                    if ($util.Long)
                        (message.traceDurationNs = $util.Long.fromValue(object.traceDurationNs)).unsigned = false;
                    else if (typeof object.traceDurationNs === "string")
                        message.traceDurationNs = parseInt(object.traceDurationNs, 10);
                    else if (typeof object.traceDurationNs === "number")
                        message.traceDurationNs = object.traceDurationNs;
                    else if (typeof object.traceDurationNs === "object")
                        message.traceDurationNs = new $util.LongBits(object.traceDurationNs.low >>> 0, object.traceDurationNs.high >>> 0).toNumber();
                if (object.traceUuid != null)
                    message.traceUuid = String(object.traceUuid);
                if (object.androidBuildFingerprint != null)
                    message.androidBuildFingerprint = String(object.androidBuildFingerprint);
                if (object.statsdTriggeringSubscriptionId != null)
                    if ($util.Long)
                        (message.statsdTriggeringSubscriptionId = $util.Long.fromValue(object.statsdTriggeringSubscriptionId)).unsigned = false;
                    else if (typeof object.statsdTriggeringSubscriptionId === "string")
                        message.statsdTriggeringSubscriptionId = parseInt(object.statsdTriggeringSubscriptionId, 10);
                    else if (typeof object.statsdTriggeringSubscriptionId === "number")
                        message.statsdTriggeringSubscriptionId = object.statsdTriggeringSubscriptionId;
                    else if (typeof object.statsdTriggeringSubscriptionId === "object")
                        message.statsdTriggeringSubscriptionId = new $util.LongBits(object.statsdTriggeringSubscriptionId.low >>> 0, object.statsdTriggeringSubscriptionId.high >>> 0).toNumber();
                if (object.traceSizeBytes != null)
                    if ($util.Long)
                        (message.traceSizeBytes = $util.Long.fromValue(object.traceSizeBytes)).unsigned = false;
                    else if (typeof object.traceSizeBytes === "string")
                        message.traceSizeBytes = parseInt(object.traceSizeBytes, 10);
                    else if (typeof object.traceSizeBytes === "number")
                        message.traceSizeBytes = object.traceSizeBytes;
                    else if (typeof object.traceSizeBytes === "object")
                        message.traceSizeBytes = new $util.LongBits(object.traceSizeBytes.low >>> 0, object.traceSizeBytes.high >>> 0).toNumber();
                if (object.traceTrigger) {
                    if (!Array.isArray(object.traceTrigger))
                        throw TypeError(".perfetto.protos.TraceMetadata.traceTrigger: array expected");
                    message.traceTrigger = [];
                    for (var i = 0; i < object.traceTrigger.length; ++i)
                        message.traceTrigger[i] = String(object.traceTrigger[i]);
                }
                if (object.uniqueSessionName != null)
                    message.uniqueSessionName = String(object.uniqueSessionName);
                if (object.traceConfigPbtxt != null)
                    message.traceConfigPbtxt = String(object.traceConfigPbtxt);
                if (object.schedDurationNs != null)
                    if ($util.Long)
                        (message.schedDurationNs = $util.Long.fromValue(object.schedDurationNs)).unsigned = false;
                    else if (typeof object.schedDurationNs === "string")
                        message.schedDurationNs = parseInt(object.schedDurationNs, 10);
                    else if (typeof object.schedDurationNs === "number")
                        message.schedDurationNs = object.schedDurationNs;
                    else if (typeof object.schedDurationNs === "object")
                        message.schedDurationNs = new $util.LongBits(object.schedDurationNs.low >>> 0, object.schedDurationNs.high >>> 0).toNumber();
                return message;
            };

            /**
             * Creates a plain object from a TraceMetadata message. Also converts values to other types if specified.
             * @function toObject
             * @memberof perfetto.protos.TraceMetadata
             * @static
             * @param {perfetto.protos.TraceMetadata} message TraceMetadata
             * @param {$protobuf.IConversionOptions} [options] Conversion options
             * @returns {Object.<string,*>} Plain object
             */
            TraceMetadata.toObject = function toObject(message, options) {
                if (!options)
                    options = {};
                var object = {};
                if (options.arrays || options.defaults)
                    object.traceTrigger = [];
                if (options.defaults) {
                    if ($util.Long) {
                        var long = new $util.Long(0, 0, false);
                        object.traceDurationNs = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
                    } else
                        object.traceDurationNs = options.longs === String ? "0" : 0;
                    object.traceUuid = "";
                    object.androidBuildFingerprint = "";
                    if ($util.Long) {
                        var long = new $util.Long(0, 0, false);
                        object.statsdTriggeringSubscriptionId = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
                    } else
                        object.statsdTriggeringSubscriptionId = options.longs === String ? "0" : 0;
                    if ($util.Long) {
                        var long = new $util.Long(0, 0, false);
                        object.traceSizeBytes = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
                    } else
                        object.traceSizeBytes = options.longs === String ? "0" : 0;
                    object.uniqueSessionName = "";
                    object.traceConfigPbtxt = "";
                    if ($util.Long) {
                        var long = new $util.Long(0, 0, false);
                        object.schedDurationNs = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
                    } else
                        object.schedDurationNs = options.longs === String ? "0" : 0;
                }
                if (message.traceDurationNs != null && message.hasOwnProperty("traceDurationNs"))
                    if (typeof message.traceDurationNs === "number")
                        object.traceDurationNs = options.longs === String ? String(message.traceDurationNs) : message.traceDurationNs;
                    else
                        object.traceDurationNs = options.longs === String ? $util.Long.prototype.toString.call(message.traceDurationNs) : options.longs === Number ? new $util.LongBits(message.traceDurationNs.low >>> 0, message.traceDurationNs.high >>> 0).toNumber() : message.traceDurationNs;
                if (message.traceUuid != null && message.hasOwnProperty("traceUuid"))
                    object.traceUuid = message.traceUuid;
                if (message.androidBuildFingerprint != null && message.hasOwnProperty("androidBuildFingerprint"))
                    object.androidBuildFingerprint = message.androidBuildFingerprint;
                if (message.statsdTriggeringSubscriptionId != null && message.hasOwnProperty("statsdTriggeringSubscriptionId"))
                    if (typeof message.statsdTriggeringSubscriptionId === "number")
                        object.statsdTriggeringSubscriptionId = options.longs === String ? String(message.statsdTriggeringSubscriptionId) : message.statsdTriggeringSubscriptionId;
                    else
                        object.statsdTriggeringSubscriptionId = options.longs === String ? $util.Long.prototype.toString.call(message.statsdTriggeringSubscriptionId) : options.longs === Number ? new $util.LongBits(message.statsdTriggeringSubscriptionId.low >>> 0, message.statsdTriggeringSubscriptionId.high >>> 0).toNumber() : message.statsdTriggeringSubscriptionId;
                if (message.traceSizeBytes != null && message.hasOwnProperty("traceSizeBytes"))
                    if (typeof message.traceSizeBytes === "number")
                        object.traceSizeBytes = options.longs === String ? String(message.traceSizeBytes) : message.traceSizeBytes;
                    else
                        object.traceSizeBytes = options.longs === String ? $util.Long.prototype.toString.call(message.traceSizeBytes) : options.longs === Number ? new $util.LongBits(message.traceSizeBytes.low >>> 0, message.traceSizeBytes.high >>> 0).toNumber() : message.traceSizeBytes;
                if (message.traceTrigger && message.traceTrigger.length) {
                    object.traceTrigger = [];
                    for (var j = 0; j < message.traceTrigger.length; ++j)
                        object.traceTrigger[j] = message.traceTrigger[j];
                }
                if (message.uniqueSessionName != null && message.hasOwnProperty("uniqueSessionName"))
                    object.uniqueSessionName = message.uniqueSessionName;
                if (message.traceConfigPbtxt != null && message.hasOwnProperty("traceConfigPbtxt"))
                    object.traceConfigPbtxt = message.traceConfigPbtxt;
                if (message.schedDurationNs != null && message.hasOwnProperty("schedDurationNs"))
                    if (typeof message.schedDurationNs === "number")
                        object.schedDurationNs = options.longs === String ? String(message.schedDurationNs) : message.schedDurationNs;
                    else
                        object.schedDurationNs = options.longs === String ? $util.Long.prototype.toString.call(message.schedDurationNs) : options.longs === Number ? new $util.LongBits(message.schedDurationNs.low >>> 0, message.schedDurationNs.high >>> 0).toNumber() : message.schedDurationNs;
                return object;
            };

            /**
             * Converts this TraceMetadata to JSON.
             * @function toJSON
             * @memberof perfetto.protos.TraceMetadata
             * @instance
             * @returns {Object.<string,*>} JSON object
             */
            TraceMetadata.prototype.toJSON = function toJSON() {
                return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
            };

            return TraceMetadata;
        })();

        protos.TraceAnalysisStats = (function() {

            /**
             * Properties of a TraceAnalysisStats.
             * @memberof perfetto.protos
             * @interface ITraceAnalysisStats
             * @property {Array.<perfetto.protos.TraceAnalysisStats.IStat>|null} [stat] TraceAnalysisStats stat
             */

            /**
             * Constructs a new TraceAnalysisStats.
             * @memberof perfetto.protos
             * @classdesc Represents a TraceAnalysisStats.
             * @implements ITraceAnalysisStats
             * @constructor
             * @param {perfetto.protos.ITraceAnalysisStats=} [properties] Properties to set
             */
            function TraceAnalysisStats(properties) {
                this.stat = [];
                if (properties)
                    for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                        if (properties[keys[i]] != null)
                            this[keys[i]] = properties[keys[i]];
            }

            /**
             * TraceAnalysisStats stat.
             * @member {Array.<perfetto.protos.TraceAnalysisStats.IStat>} stat
             * @memberof perfetto.protos.TraceAnalysisStats
             * @instance
             */
            TraceAnalysisStats.prototype.stat = $util.emptyArray;

            /**
             * Creates a new TraceAnalysisStats instance using the specified properties.
             * @function create
             * @memberof perfetto.protos.TraceAnalysisStats
             * @static
             * @param {perfetto.protos.ITraceAnalysisStats=} [properties] Properties to set
             * @returns {perfetto.protos.TraceAnalysisStats} TraceAnalysisStats instance
             */
            TraceAnalysisStats.create = function create(properties) {
                return new TraceAnalysisStats(properties);
            };

            /**
             * Encodes the specified TraceAnalysisStats message. Does not implicitly {@link perfetto.protos.TraceAnalysisStats.verify|verify} messages.
             * @function encode
             * @memberof perfetto.protos.TraceAnalysisStats
             * @static
             * @param {perfetto.protos.ITraceAnalysisStats} message TraceAnalysisStats message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            TraceAnalysisStats.encode = function encode(message, writer) {
                if (!writer)
                    writer = $Writer.create();
                if (message.stat != null && message.stat.length)
                    for (var i = 0; i < message.stat.length; ++i)
                        $root.perfetto.protos.TraceAnalysisStats.Stat.encode(message.stat[i], writer.uint32(/* id 1, wireType 2 =*/10).fork()).ldelim();
                return writer;
            };

            /**
             * Encodes the specified TraceAnalysisStats message, length delimited. Does not implicitly {@link perfetto.protos.TraceAnalysisStats.verify|verify} messages.
             * @function encodeDelimited
             * @memberof perfetto.protos.TraceAnalysisStats
             * @static
             * @param {perfetto.protos.ITraceAnalysisStats} message TraceAnalysisStats message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            TraceAnalysisStats.encodeDelimited = function encodeDelimited(message, writer) {
                return this.encode(message, writer).ldelim();
            };

            /**
             * Decodes a TraceAnalysisStats message from the specified reader or buffer.
             * @function decode
             * @memberof perfetto.protos.TraceAnalysisStats
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @param {number} [length] Message length if known beforehand
             * @returns {perfetto.protos.TraceAnalysisStats} TraceAnalysisStats
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            TraceAnalysisStats.decode = function decode(reader, length) {
                if (!(reader instanceof $Reader))
                    reader = $Reader.create(reader);
                var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.TraceAnalysisStats();
                while (reader.pos < end) {
                    var tag = reader.uint32();
                    switch (tag >>> 3) {
                    case 1:
                        if (!(message.stat && message.stat.length))
                            message.stat = [];
                        message.stat.push($root.perfetto.protos.TraceAnalysisStats.Stat.decode(reader, reader.uint32()));
                        break;
                    default:
                        reader.skipType(tag & 7);
                        break;
                    }
                }
                return message;
            };

            /**
             * Decodes a TraceAnalysisStats message from the specified reader or buffer, length delimited.
             * @function decodeDelimited
             * @memberof perfetto.protos.TraceAnalysisStats
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @returns {perfetto.protos.TraceAnalysisStats} TraceAnalysisStats
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            TraceAnalysisStats.decodeDelimited = function decodeDelimited(reader) {
                if (!(reader instanceof $Reader))
                    reader = new $Reader(reader);
                return this.decode(reader, reader.uint32());
            };

            /**
             * Verifies a TraceAnalysisStats message.
             * @function verify
             * @memberof perfetto.protos.TraceAnalysisStats
             * @static
             * @param {Object.<string,*>} message Plain object to verify
             * @returns {string|null} `null` if valid, otherwise the reason why it is not
             */
            TraceAnalysisStats.verify = function verify(message) {
                if (typeof message !== "object" || message === null)
                    return "object expected";
                if (message.stat != null && message.hasOwnProperty("stat")) {
                    if (!Array.isArray(message.stat))
                        return "stat: array expected";
                    for (var i = 0; i < message.stat.length; ++i) {
                        var error = $root.perfetto.protos.TraceAnalysisStats.Stat.verify(message.stat[i]);
                        if (error)
                            return "stat." + error;
                    }
                }
                return null;
            };

            /**
             * Creates a TraceAnalysisStats message from a plain object. Also converts values to their respective internal types.
             * @function fromObject
             * @memberof perfetto.protos.TraceAnalysisStats
             * @static
             * @param {Object.<string,*>} object Plain object
             * @returns {perfetto.protos.TraceAnalysisStats} TraceAnalysisStats
             */
            TraceAnalysisStats.fromObject = function fromObject(object) {
                if (object instanceof $root.perfetto.protos.TraceAnalysisStats)
                    return object;
                var message = new $root.perfetto.protos.TraceAnalysisStats();
                if (object.stat) {
                    if (!Array.isArray(object.stat))
                        throw TypeError(".perfetto.protos.TraceAnalysisStats.stat: array expected");
                    message.stat = [];
                    for (var i = 0; i < object.stat.length; ++i) {
                        if (typeof object.stat[i] !== "object")
                            throw TypeError(".perfetto.protos.TraceAnalysisStats.stat: object expected");
                        message.stat[i] = $root.perfetto.protos.TraceAnalysisStats.Stat.fromObject(object.stat[i]);
                    }
                }
                return message;
            };

            /**
             * Creates a plain object from a TraceAnalysisStats message. Also converts values to other types if specified.
             * @function toObject
             * @memberof perfetto.protos.TraceAnalysisStats
             * @static
             * @param {perfetto.protos.TraceAnalysisStats} message TraceAnalysisStats
             * @param {$protobuf.IConversionOptions} [options] Conversion options
             * @returns {Object.<string,*>} Plain object
             */
            TraceAnalysisStats.toObject = function toObject(message, options) {
                if (!options)
                    options = {};
                var object = {};
                if (options.arrays || options.defaults)
                    object.stat = [];
                if (message.stat && message.stat.length) {
                    object.stat = [];
                    for (var j = 0; j < message.stat.length; ++j)
                        object.stat[j] = $root.perfetto.protos.TraceAnalysisStats.Stat.toObject(message.stat[j], options);
                }
                return object;
            };

            /**
             * Converts this TraceAnalysisStats to JSON.
             * @function toJSON
             * @memberof perfetto.protos.TraceAnalysisStats
             * @instance
             * @returns {Object.<string,*>} JSON object
             */
            TraceAnalysisStats.prototype.toJSON = function toJSON() {
                return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
            };

            /**
             * Severity enum.
             * @name perfetto.protos.TraceAnalysisStats.Severity
             * @enum {number}
             * @property {number} SEVERITY_UNKNOWN=0 SEVERITY_UNKNOWN value
             * @property {number} SEVERITY_INFO=1 SEVERITY_INFO value
             * @property {number} SEVERITY_DATA_LOSS=2 SEVERITY_DATA_LOSS value
             * @property {number} SEVERITY_ERROR=3 SEVERITY_ERROR value
             */
            TraceAnalysisStats.Severity = (function() {
                var valuesById = {}, values = Object.create(valuesById);
                values[valuesById[0] = "SEVERITY_UNKNOWN"] = 0;
                values[valuesById[1] = "SEVERITY_INFO"] = 1;
                values[valuesById[2] = "SEVERITY_DATA_LOSS"] = 2;
                values[valuesById[3] = "SEVERITY_ERROR"] = 3;
                return values;
            })();

            /**
             * Source enum.
             * @name perfetto.protos.TraceAnalysisStats.Source
             * @enum {number}
             * @property {number} SOURCE_UNKNOWN=0 SOURCE_UNKNOWN value
             * @property {number} SOURCE_TRACE=1 SOURCE_TRACE value
             * @property {number} SOURCE_ANALYSIS=2 SOURCE_ANALYSIS value
             */
            TraceAnalysisStats.Source = (function() {
                var valuesById = {}, values = Object.create(valuesById);
                values[valuesById[0] = "SOURCE_UNKNOWN"] = 0;
                values[valuesById[1] = "SOURCE_TRACE"] = 1;
                values[valuesById[2] = "SOURCE_ANALYSIS"] = 2;
                return values;
            })();

            TraceAnalysisStats.Stat = (function() {

                /**
                 * Properties of a Stat.
                 * @memberof perfetto.protos.TraceAnalysisStats
                 * @interface IStat
                 * @property {string|null} [name] Stat name
                 * @property {number|null} [idx] Stat idx
                 * @property {perfetto.protos.TraceAnalysisStats.Severity|null} [severity] Stat severity
                 * @property {perfetto.protos.TraceAnalysisStats.Source|null} [source] Stat source
                 * @property {number|null} [count] Stat count
                 */

                /**
                 * Constructs a new Stat.
                 * @memberof perfetto.protos.TraceAnalysisStats
                 * @classdesc Represents a Stat.
                 * @implements IStat
                 * @constructor
                 * @param {perfetto.protos.TraceAnalysisStats.IStat=} [properties] Properties to set
                 */
                function Stat(properties) {
                    if (properties)
                        for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                            if (properties[keys[i]] != null)
                                this[keys[i]] = properties[keys[i]];
                }

                /**
                 * Stat name.
                 * @member {string} name
                 * @memberof perfetto.protos.TraceAnalysisStats.Stat
                 * @instance
                 */
                Stat.prototype.name = "";

                /**
                 * Stat idx.
                 * @member {number} idx
                 * @memberof perfetto.protos.TraceAnalysisStats.Stat
                 * @instance
                 */
                Stat.prototype.idx = 0;

                /**
                 * Stat severity.
                 * @member {perfetto.protos.TraceAnalysisStats.Severity} severity
                 * @memberof perfetto.protos.TraceAnalysisStats.Stat
                 * @instance
                 */
                Stat.prototype.severity = 0;

                /**
                 * Stat source.
                 * @member {perfetto.protos.TraceAnalysisStats.Source} source
                 * @memberof perfetto.protos.TraceAnalysisStats.Stat
                 * @instance
                 */
                Stat.prototype.source = 0;

                /**
                 * Stat count.
                 * @member {number} count
                 * @memberof perfetto.protos.TraceAnalysisStats.Stat
                 * @instance
                 */
                Stat.prototype.count = $util.Long ? $util.Long.fromBits(0,0,false) : 0;

                /**
                 * Creates a new Stat instance using the specified properties.
                 * @function create
                 * @memberof perfetto.protos.TraceAnalysisStats.Stat
                 * @static
                 * @param {perfetto.protos.TraceAnalysisStats.IStat=} [properties] Properties to set
                 * @returns {perfetto.protos.TraceAnalysisStats.Stat} Stat instance
                 */
                Stat.create = function create(properties) {
                    return new Stat(properties);
                };

                /**
                 * Encodes the specified Stat message. Does not implicitly {@link perfetto.protos.TraceAnalysisStats.Stat.verify|verify} messages.
                 * @function encode
                 * @memberof perfetto.protos.TraceAnalysisStats.Stat
                 * @static
                 * @param {perfetto.protos.TraceAnalysisStats.IStat} message Stat message or plain object to encode
                 * @param {$protobuf.Writer} [writer] Writer to encode to
                 * @returns {$protobuf.Writer} Writer
                 */
                Stat.encode = function encode(message, writer) {
                    if (!writer)
                        writer = $Writer.create();
                    if (message.name != null && Object.hasOwnProperty.call(message, "name"))
                        writer.uint32(/* id 1, wireType 2 =*/10).string(message.name);
                    if (message.idx != null && Object.hasOwnProperty.call(message, "idx"))
                        writer.uint32(/* id 2, wireType 0 =*/16).uint32(message.idx);
                    if (message.severity != null && Object.hasOwnProperty.call(message, "severity"))
                        writer.uint32(/* id 3, wireType 0 =*/24).int32(message.severity);
                    if (message.source != null && Object.hasOwnProperty.call(message, "source"))
                        writer.uint32(/* id 4, wireType 0 =*/32).int32(message.source);
                    if (message.count != null && Object.hasOwnProperty.call(message, "count"))
                        writer.uint32(/* id 5, wireType 0 =*/40).int64(message.count);
                    return writer;
                };

                /**
                 * Encodes the specified Stat message, length delimited. Does not implicitly {@link perfetto.protos.TraceAnalysisStats.Stat.verify|verify} messages.
                 * @function encodeDelimited
                 * @memberof perfetto.protos.TraceAnalysisStats.Stat
                 * @static
                 * @param {perfetto.protos.TraceAnalysisStats.IStat} message Stat message or plain object to encode
                 * @param {$protobuf.Writer} [writer] Writer to encode to
                 * @returns {$protobuf.Writer} Writer
                 */
                Stat.encodeDelimited = function encodeDelimited(message, writer) {
                    return this.encode(message, writer).ldelim();
                };

                /**
                 * Decodes a Stat message from the specified reader or buffer.
                 * @function decode
                 * @memberof perfetto.protos.TraceAnalysisStats.Stat
                 * @static
                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                 * @param {number} [length] Message length if known beforehand
                 * @returns {perfetto.protos.TraceAnalysisStats.Stat} Stat
                 * @throws {Error} If the payload is not a reader or valid buffer
                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
                 */
                Stat.decode = function decode(reader, length) {
                    if (!(reader instanceof $Reader))
                        reader = $Reader.create(reader);
                    var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.TraceAnalysisStats.Stat();
                    while (reader.pos < end) {
                        var tag = reader.uint32();
                        switch (tag >>> 3) {
                        case 1:
                            message.name = reader.string();
                            break;
                        case 2:
                            message.idx = reader.uint32();
                            break;
                        case 3:
                            message.severity = reader.int32();
                            break;
                        case 4:
                            message.source = reader.int32();
                            break;
                        case 5:
                            message.count = reader.int64();
                            break;
                        default:
                            reader.skipType(tag & 7);
                            break;
                        }
                    }
                    return message;
                };

                /**
                 * Decodes a Stat message from the specified reader or buffer, length delimited.
                 * @function decodeDelimited
                 * @memberof perfetto.protos.TraceAnalysisStats.Stat
                 * @static
                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                 * @returns {perfetto.protos.TraceAnalysisStats.Stat} Stat
                 * @throws {Error} If the payload is not a reader or valid buffer
                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
                 */
                Stat.decodeDelimited = function decodeDelimited(reader) {
                    if (!(reader instanceof $Reader))
                        reader = new $Reader(reader);
                    return this.decode(reader, reader.uint32());
                };

                /**
                 * Verifies a Stat message.
                 * @function verify
                 * @memberof perfetto.protos.TraceAnalysisStats.Stat
                 * @static
                 * @param {Object.<string,*>} message Plain object to verify
                 * @returns {string|null} `null` if valid, otherwise the reason why it is not
                 */
                Stat.verify = function verify(message) {
                    if (typeof message !== "object" || message === null)
                        return "object expected";
                    if (message.name != null && message.hasOwnProperty("name"))
                        if (!$util.isString(message.name))
                            return "name: string expected";
                    if (message.idx != null && message.hasOwnProperty("idx"))
                        if (!$util.isInteger(message.idx))
                            return "idx: integer expected";
                    if (message.severity != null && message.hasOwnProperty("severity"))
                        switch (message.severity) {
                        default:
                            return "severity: enum value expected";
                        case 0:
                        case 1:
                        case 2:
                        case 3:
                            break;
                        }
                    if (message.source != null && message.hasOwnProperty("source"))
                        switch (message.source) {
                        default:
                            return "source: enum value expected";
                        case 0:
                        case 1:
                        case 2:
                            break;
                        }
                    if (message.count != null && message.hasOwnProperty("count"))
                        if (!$util.isInteger(message.count) && !(message.count && $util.isInteger(message.count.low) && $util.isInteger(message.count.high)))
                            return "count: integer|Long expected";
                    return null;
                };

                /**
                 * Creates a Stat message from a plain object. Also converts values to their respective internal types.
                 * @function fromObject
                 * @memberof perfetto.protos.TraceAnalysisStats.Stat
                 * @static
                 * @param {Object.<string,*>} object Plain object
                 * @returns {perfetto.protos.TraceAnalysisStats.Stat} Stat
                 */
                Stat.fromObject = function fromObject(object) {
                    if (object instanceof $root.perfetto.protos.TraceAnalysisStats.Stat)
                        return object;
                    var message = new $root.perfetto.protos.TraceAnalysisStats.Stat();
                    if (object.name != null)
                        message.name = String(object.name);
                    if (object.idx != null)
                        message.idx = object.idx >>> 0;
                    switch (object.severity) {
                    case "SEVERITY_UNKNOWN":
                    case 0:
                        message.severity = 0;
                        break;
                    case "SEVERITY_INFO":
                    case 1:
                        message.severity = 1;
                        break;
                    case "SEVERITY_DATA_LOSS":
                    case 2:
                        message.severity = 2;
                        break;
                    case "SEVERITY_ERROR":
                    case 3:
                        message.severity = 3;
                        break;
                    }
                    switch (object.source) {
                    case "SOURCE_UNKNOWN":
                    case 0:
                        message.source = 0;
                        break;
                    case "SOURCE_TRACE":
                    case 1:
                        message.source = 1;
                        break;
                    case "SOURCE_ANALYSIS":
                    case 2:
                        message.source = 2;
                        break;
                    }
                    if (object.count != null)
                        if ($util.Long)
                            (message.count = $util.Long.fromValue(object.count)).unsigned = false;
                        else if (typeof object.count === "string")
                            message.count = parseInt(object.count, 10);
                        else if (typeof object.count === "number")
                            message.count = object.count;
                        else if (typeof object.count === "object")
                            message.count = new $util.LongBits(object.count.low >>> 0, object.count.high >>> 0).toNumber();
                    return message;
                };

                /**
                 * Creates a plain object from a Stat message. Also converts values to other types if specified.
                 * @function toObject
                 * @memberof perfetto.protos.TraceAnalysisStats.Stat
                 * @static
                 * @param {perfetto.protos.TraceAnalysisStats.Stat} message Stat
                 * @param {$protobuf.IConversionOptions} [options] Conversion options
                 * @returns {Object.<string,*>} Plain object
                 */
                Stat.toObject = function toObject(message, options) {
                    if (!options)
                        options = {};
                    var object = {};
                    if (options.defaults) {
                        object.name = "";
                        object.idx = 0;
                        object.severity = options.enums === String ? "SEVERITY_UNKNOWN" : 0;
                        object.source = options.enums === String ? "SOURCE_UNKNOWN" : 0;
                        if ($util.Long) {
                            var long = new $util.Long(0, 0, false);
                            object.count = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
                        } else
                            object.count = options.longs === String ? "0" : 0;
                    }
                    if (message.name != null && message.hasOwnProperty("name"))
                        object.name = message.name;
                    if (message.idx != null && message.hasOwnProperty("idx"))
                        object.idx = message.idx;
                    if (message.severity != null && message.hasOwnProperty("severity"))
                        object.severity = options.enums === String ? $root.perfetto.protos.TraceAnalysisStats.Severity[message.severity] : message.severity;
                    if (message.source != null && message.hasOwnProperty("source"))
                        object.source = options.enums === String ? $root.perfetto.protos.TraceAnalysisStats.Source[message.source] : message.source;
                    if (message.count != null && message.hasOwnProperty("count"))
                        if (typeof message.count === "number")
                            object.count = options.longs === String ? String(message.count) : message.count;
                        else
                            object.count = options.longs === String ? $util.Long.prototype.toString.call(message.count) : options.longs === Number ? new $util.LongBits(message.count.low >>> 0, message.count.high >>> 0).toNumber() : message.count;
                    return object;
                };

                /**
                 * Converts this Stat to JSON.
                 * @function toJSON
                 * @memberof perfetto.protos.TraceAnalysisStats.Stat
                 * @instance
                 * @returns {Object.<string,*>} JSON object
                 */
                Stat.prototype.toJSON = function toJSON() {
                    return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
                };

                return Stat;
            })();

            return TraceAnalysisStats;
        })();

        protos.TraceMetrics = (function() {

            /**
             * Properties of a TraceMetrics.
             * @memberof perfetto.protos
             * @interface ITraceMetrics
             * @property {perfetto.protos.IAndroidBatteryMetric|null} [androidBatt] TraceMetrics androidBatt
             * @property {perfetto.protos.IAndroidCpuMetric|null} [androidCpu] TraceMetrics androidCpu
             * @property {perfetto.protos.IAndroidMemoryMetric|null} [androidMem] TraceMetrics androidMem
             * @property {perfetto.protos.IAndroidMemoryUnaggregatedMetric|null} [androidMemUnagg] TraceMetrics androidMemUnagg
             * @property {perfetto.protos.IAndroidPackageList|null} [androidPackageList] TraceMetrics androidPackageList
             * @property {perfetto.protos.IAndroidIonMetric|null} [androidIon] TraceMetrics androidIon
             * @property {perfetto.protos.IAndroidFastrpcMetric|null} [androidFastrpc] TraceMetrics androidFastrpc
             * @property {perfetto.protos.IAndroidLmkMetric|null} [androidLmk] TraceMetrics androidLmk
             * @property {perfetto.protos.IAndroidPowerRails|null} [androidPowrails] TraceMetrics androidPowrails
             * @property {perfetto.protos.IAndroidStartupMetric|null} [androidStartup] TraceMetrics androidStartup
             * @property {perfetto.protos.ITraceMetadata|null} [traceMetadata] TraceMetrics traceMetadata
             * @property {perfetto.protos.ITraceAnalysisStats|null} [traceStats] TraceMetrics traceStats
             * @property {perfetto.protos.IUnsymbolizedFrames|null} [unsymbolizedFrames] TraceMetrics unsymbolizedFrames
             * @property {perfetto.protos.IJavaHeapStats|null} [javaHeapStats] TraceMetrics javaHeapStats
             * @property {perfetto.protos.IJavaHeapHistogram|null} [javaHeapHistogram] TraceMetrics javaHeapHistogram
             * @property {perfetto.protos.IAndroidLmkReasonMetric|null} [androidLmkReason] TraceMetrics androidLmkReason
             * @property {perfetto.protos.IAndroidHwuiMetric|null} [androidHwuiMetric] TraceMetrics androidHwuiMetric
             * @property {perfetto.protos.IAndroidDisplayMetrics|null} [displayMetrics] TraceMetrics displayMetrics
             * @property {perfetto.protos.IAndroidTaskNames|null} [androidTaskNames] TraceMetrics androidTaskNames
             * @property {perfetto.protos.IAndroidThreadTimeInStateMetric|null} [androidThreadTimeInState] TraceMetrics androidThreadTimeInState
             * @property {perfetto.protos.IAndroidSurfaceflingerMetric|null} [androidSurfaceflinger] TraceMetrics androidSurfaceflinger
             * @property {perfetto.protos.IAndroidGpuMetric|null} [androidGpu] TraceMetrics androidGpu
             * @property {perfetto.protos.IAndroidSysUiCujMetrics|null} [androidSysuiCuj] TraceMetrics androidSysuiCuj
             * @property {perfetto.protos.IAndroidHwcomposerMetrics|null} [androidHwcomposer] TraceMetrics androidHwcomposer
             * @property {perfetto.protos.IAndroidJankMetrics|null} [androidJank] TraceMetrics androidJank
             * @property {perfetto.protos.IG2dMetrics|null} [g2d] TraceMetrics g2d
             * @property {perfetto.protos.IAndroidDmaHeapMetric|null} [androidDmaHeap] TraceMetrics androidDmaHeap
             */

            /**
             * Constructs a new TraceMetrics.
             * @memberof perfetto.protos
             * @classdesc Represents a TraceMetrics.
             * @implements ITraceMetrics
             * @constructor
             * @param {perfetto.protos.ITraceMetrics=} [properties] Properties to set
             */
            function TraceMetrics(properties) {
                if (properties)
                    for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                        if (properties[keys[i]] != null)
                            this[keys[i]] = properties[keys[i]];
            }

            /**
             * TraceMetrics androidBatt.
             * @member {perfetto.protos.IAndroidBatteryMetric|null|undefined} androidBatt
             * @memberof perfetto.protos.TraceMetrics
             * @instance
             */
            TraceMetrics.prototype.androidBatt = null;

            /**
             * TraceMetrics androidCpu.
             * @member {perfetto.protos.IAndroidCpuMetric|null|undefined} androidCpu
             * @memberof perfetto.protos.TraceMetrics
             * @instance
             */
            TraceMetrics.prototype.androidCpu = null;

            /**
             * TraceMetrics androidMem.
             * @member {perfetto.protos.IAndroidMemoryMetric|null|undefined} androidMem
             * @memberof perfetto.protos.TraceMetrics
             * @instance
             */
            TraceMetrics.prototype.androidMem = null;

            /**
             * TraceMetrics androidMemUnagg.
             * @member {perfetto.protos.IAndroidMemoryUnaggregatedMetric|null|undefined} androidMemUnagg
             * @memberof perfetto.protos.TraceMetrics
             * @instance
             */
            TraceMetrics.prototype.androidMemUnagg = null;

            /**
             * TraceMetrics androidPackageList.
             * @member {perfetto.protos.IAndroidPackageList|null|undefined} androidPackageList
             * @memberof perfetto.protos.TraceMetrics
             * @instance
             */
            TraceMetrics.prototype.androidPackageList = null;

            /**
             * TraceMetrics androidIon.
             * @member {perfetto.protos.IAndroidIonMetric|null|undefined} androidIon
             * @memberof perfetto.protos.TraceMetrics
             * @instance
             */
            TraceMetrics.prototype.androidIon = null;

            /**
             * TraceMetrics androidFastrpc.
             * @member {perfetto.protos.IAndroidFastrpcMetric|null|undefined} androidFastrpc
             * @memberof perfetto.protos.TraceMetrics
             * @instance
             */
            TraceMetrics.prototype.androidFastrpc = null;

            /**
             * TraceMetrics androidLmk.
             * @member {perfetto.protos.IAndroidLmkMetric|null|undefined} androidLmk
             * @memberof perfetto.protos.TraceMetrics
             * @instance
             */
            TraceMetrics.prototype.androidLmk = null;

            /**
             * TraceMetrics androidPowrails.
             * @member {perfetto.protos.IAndroidPowerRails|null|undefined} androidPowrails
             * @memberof perfetto.protos.TraceMetrics
             * @instance
             */
            TraceMetrics.prototype.androidPowrails = null;

            /**
             * TraceMetrics androidStartup.
             * @member {perfetto.protos.IAndroidStartupMetric|null|undefined} androidStartup
             * @memberof perfetto.protos.TraceMetrics
             * @instance
             */
            TraceMetrics.prototype.androidStartup = null;

            /**
             * TraceMetrics traceMetadata.
             * @member {perfetto.protos.ITraceMetadata|null|undefined} traceMetadata
             * @memberof perfetto.protos.TraceMetrics
             * @instance
             */
            TraceMetrics.prototype.traceMetadata = null;

            /**
             * TraceMetrics traceStats.
             * @member {perfetto.protos.ITraceAnalysisStats|null|undefined} traceStats
             * @memberof perfetto.protos.TraceMetrics
             * @instance
             */
            TraceMetrics.prototype.traceStats = null;

            /**
             * TraceMetrics unsymbolizedFrames.
             * @member {perfetto.protos.IUnsymbolizedFrames|null|undefined} unsymbolizedFrames
             * @memberof perfetto.protos.TraceMetrics
             * @instance
             */
            TraceMetrics.prototype.unsymbolizedFrames = null;

            /**
             * TraceMetrics javaHeapStats.
             * @member {perfetto.protos.IJavaHeapStats|null|undefined} javaHeapStats
             * @memberof perfetto.protos.TraceMetrics
             * @instance
             */
            TraceMetrics.prototype.javaHeapStats = null;

            /**
             * TraceMetrics javaHeapHistogram.
             * @member {perfetto.protos.IJavaHeapHistogram|null|undefined} javaHeapHistogram
             * @memberof perfetto.protos.TraceMetrics
             * @instance
             */
            TraceMetrics.prototype.javaHeapHistogram = null;

            /**
             * TraceMetrics androidLmkReason.
             * @member {perfetto.protos.IAndroidLmkReasonMetric|null|undefined} androidLmkReason
             * @memberof perfetto.protos.TraceMetrics
             * @instance
             */
            TraceMetrics.prototype.androidLmkReason = null;

            /**
             * TraceMetrics androidHwuiMetric.
             * @member {perfetto.protos.IAndroidHwuiMetric|null|undefined} androidHwuiMetric
             * @memberof perfetto.protos.TraceMetrics
             * @instance
             */
            TraceMetrics.prototype.androidHwuiMetric = null;

            /**
             * TraceMetrics displayMetrics.
             * @member {perfetto.protos.IAndroidDisplayMetrics|null|undefined} displayMetrics
             * @memberof perfetto.protos.TraceMetrics
             * @instance
             */
            TraceMetrics.prototype.displayMetrics = null;

            /**
             * TraceMetrics androidTaskNames.
             * @member {perfetto.protos.IAndroidTaskNames|null|undefined} androidTaskNames
             * @memberof perfetto.protos.TraceMetrics
             * @instance
             */
            TraceMetrics.prototype.androidTaskNames = null;

            /**
             * TraceMetrics androidThreadTimeInState.
             * @member {perfetto.protos.IAndroidThreadTimeInStateMetric|null|undefined} androidThreadTimeInState
             * @memberof perfetto.protos.TraceMetrics
             * @instance
             */
            TraceMetrics.prototype.androidThreadTimeInState = null;

            /**
             * TraceMetrics androidSurfaceflinger.
             * @member {perfetto.protos.IAndroidSurfaceflingerMetric|null|undefined} androidSurfaceflinger
             * @memberof perfetto.protos.TraceMetrics
             * @instance
             */
            TraceMetrics.prototype.androidSurfaceflinger = null;

            /**
             * TraceMetrics androidGpu.
             * @member {perfetto.protos.IAndroidGpuMetric|null|undefined} androidGpu
             * @memberof perfetto.protos.TraceMetrics
             * @instance
             */
            TraceMetrics.prototype.androidGpu = null;

            /**
             * TraceMetrics androidSysuiCuj.
             * @member {perfetto.protos.IAndroidSysUiCujMetrics|null|undefined} androidSysuiCuj
             * @memberof perfetto.protos.TraceMetrics
             * @instance
             */
            TraceMetrics.prototype.androidSysuiCuj = null;

            /**
             * TraceMetrics androidHwcomposer.
             * @member {perfetto.protos.IAndroidHwcomposerMetrics|null|undefined} androidHwcomposer
             * @memberof perfetto.protos.TraceMetrics
             * @instance
             */
            TraceMetrics.prototype.androidHwcomposer = null;

            /**
             * TraceMetrics androidJank.
             * @member {perfetto.protos.IAndroidJankMetrics|null|undefined} androidJank
             * @memberof perfetto.protos.TraceMetrics
             * @instance
             */
            TraceMetrics.prototype.androidJank = null;

            /**
             * TraceMetrics g2d.
             * @member {perfetto.protos.IG2dMetrics|null|undefined} g2d
             * @memberof perfetto.protos.TraceMetrics
             * @instance
             */
            TraceMetrics.prototype.g2d = null;

            /**
             * TraceMetrics androidDmaHeap.
             * @member {perfetto.protos.IAndroidDmaHeapMetric|null|undefined} androidDmaHeap
             * @memberof perfetto.protos.TraceMetrics
             * @instance
             */
            TraceMetrics.prototype.androidDmaHeap = null;

            /**
             * Creates a new TraceMetrics instance using the specified properties.
             * @function create
             * @memberof perfetto.protos.TraceMetrics
             * @static
             * @param {perfetto.protos.ITraceMetrics=} [properties] Properties to set
             * @returns {perfetto.protos.TraceMetrics} TraceMetrics instance
             */
            TraceMetrics.create = function create(properties) {
                return new TraceMetrics(properties);
            };

            /**
             * Encodes the specified TraceMetrics message. Does not implicitly {@link perfetto.protos.TraceMetrics.verify|verify} messages.
             * @function encode
             * @memberof perfetto.protos.TraceMetrics
             * @static
             * @param {perfetto.protos.ITraceMetrics} message TraceMetrics message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            TraceMetrics.encode = function encode(message, writer) {
                if (!writer)
                    writer = $Writer.create();
                if (message.androidMem != null && Object.hasOwnProperty.call(message, "androidMem"))
                    $root.perfetto.protos.AndroidMemoryMetric.encode(message.androidMem, writer.uint32(/* id 1, wireType 2 =*/10).fork()).ldelim();
                if (message.androidStartup != null && Object.hasOwnProperty.call(message, "androidStartup"))
                    $root.perfetto.protos.AndroidStartupMetric.encode(message.androidStartup, writer.uint32(/* id 2, wireType 2 =*/18).fork()).ldelim();
                if (message.traceMetadata != null && Object.hasOwnProperty.call(message, "traceMetadata"))
                    $root.perfetto.protos.TraceMetadata.encode(message.traceMetadata, writer.uint32(/* id 3, wireType 2 =*/26).fork()).ldelim();
                if (message.androidBatt != null && Object.hasOwnProperty.call(message, "androidBatt"))
                    $root.perfetto.protos.AndroidBatteryMetric.encode(message.androidBatt, writer.uint32(/* id 5, wireType 2 =*/42).fork()).ldelim();
                if (message.androidCpu != null && Object.hasOwnProperty.call(message, "androidCpu"))
                    $root.perfetto.protos.AndroidCpuMetric.encode(message.androidCpu, writer.uint32(/* id 6, wireType 2 =*/50).fork()).ldelim();
                if (message.androidPowrails != null && Object.hasOwnProperty.call(message, "androidPowrails"))
                    $root.perfetto.protos.AndroidPowerRails.encode(message.androidPowrails, writer.uint32(/* id 7, wireType 2 =*/58).fork()).ldelim();
                if (message.androidLmk != null && Object.hasOwnProperty.call(message, "androidLmk"))
                    $root.perfetto.protos.AndroidLmkMetric.encode(message.androidLmk, writer.uint32(/* id 8, wireType 2 =*/66).fork()).ldelim();
                if (message.androidIon != null && Object.hasOwnProperty.call(message, "androidIon"))
                    $root.perfetto.protos.AndroidIonMetric.encode(message.androidIon, writer.uint32(/* id 9, wireType 2 =*/74).fork()).ldelim();
                if (message.androidMemUnagg != null && Object.hasOwnProperty.call(message, "androidMemUnagg"))
                    $root.perfetto.protos.AndroidMemoryUnaggregatedMetric.encode(message.androidMemUnagg, writer.uint32(/* id 11, wireType 2 =*/90).fork()).ldelim();
                if (message.androidPackageList != null && Object.hasOwnProperty.call(message, "androidPackageList"))
                    $root.perfetto.protos.AndroidPackageList.encode(message.androidPackageList, writer.uint32(/* id 12, wireType 2 =*/98).fork()).ldelim();
                if (message.unsymbolizedFrames != null && Object.hasOwnProperty.call(message, "unsymbolizedFrames"))
                    $root.perfetto.protos.UnsymbolizedFrames.encode(message.unsymbolizedFrames, writer.uint32(/* id 15, wireType 2 =*/122).fork()).ldelim();
                if (message.javaHeapStats != null && Object.hasOwnProperty.call(message, "javaHeapStats"))
                    $root.perfetto.protos.JavaHeapStats.encode(message.javaHeapStats, writer.uint32(/* id 17, wireType 2 =*/138).fork()).ldelim();
                if (message.androidLmkReason != null && Object.hasOwnProperty.call(message, "androidLmkReason"))
                    $root.perfetto.protos.AndroidLmkReasonMetric.encode(message.androidLmkReason, writer.uint32(/* id 18, wireType 2 =*/146).fork()).ldelim();
                if (message.androidHwuiMetric != null && Object.hasOwnProperty.call(message, "androidHwuiMetric"))
                    $root.perfetto.protos.AndroidHwuiMetric.encode(message.androidHwuiMetric, writer.uint32(/* id 20, wireType 2 =*/162).fork()).ldelim();
                if (message.javaHeapHistogram != null && Object.hasOwnProperty.call(message, "javaHeapHistogram"))
                    $root.perfetto.protos.JavaHeapHistogram.encode(message.javaHeapHistogram, writer.uint32(/* id 21, wireType 2 =*/170).fork()).ldelim();
                if (message.displayMetrics != null && Object.hasOwnProperty.call(message, "displayMetrics"))
                    $root.perfetto.protos.AndroidDisplayMetrics.encode(message.displayMetrics, writer.uint32(/* id 22, wireType 2 =*/178).fork()).ldelim();
                if (message.androidTaskNames != null && Object.hasOwnProperty.call(message, "androidTaskNames"))
                    $root.perfetto.protos.AndroidTaskNames.encode(message.androidTaskNames, writer.uint32(/* id 23, wireType 2 =*/186).fork()).ldelim();
                if (message.androidThreadTimeInState != null && Object.hasOwnProperty.call(message, "androidThreadTimeInState"))
                    $root.perfetto.protos.AndroidThreadTimeInStateMetric.encode(message.androidThreadTimeInState, writer.uint32(/* id 24, wireType 2 =*/194).fork()).ldelim();
                if (message.androidSurfaceflinger != null && Object.hasOwnProperty.call(message, "androidSurfaceflinger"))
                    $root.perfetto.protos.AndroidSurfaceflingerMetric.encode(message.androidSurfaceflinger, writer.uint32(/* id 25, wireType 2 =*/202).fork()).ldelim();
                if (message.androidGpu != null && Object.hasOwnProperty.call(message, "androidGpu"))
                    $root.perfetto.protos.AndroidGpuMetric.encode(message.androidGpu, writer.uint32(/* id 26, wireType 2 =*/210).fork()).ldelim();
                if (message.androidSysuiCuj != null && Object.hasOwnProperty.call(message, "androidSysuiCuj"))
                    $root.perfetto.protos.AndroidSysUiCujMetrics.encode(message.androidSysuiCuj, writer.uint32(/* id 27, wireType 2 =*/218).fork()).ldelim();
                if (message.androidHwcomposer != null && Object.hasOwnProperty.call(message, "androidHwcomposer"))
                    $root.perfetto.protos.AndroidHwcomposerMetrics.encode(message.androidHwcomposer, writer.uint32(/* id 28, wireType 2 =*/226).fork()).ldelim();
                if (message.androidJank != null && Object.hasOwnProperty.call(message, "androidJank"))
                    $root.perfetto.protos.AndroidJankMetrics.encode(message.androidJank, writer.uint32(/* id 29, wireType 2 =*/234).fork()).ldelim();
                if (message.g2d != null && Object.hasOwnProperty.call(message, "g2d"))
                    $root.perfetto.protos.G2dMetrics.encode(message.g2d, writer.uint32(/* id 30, wireType 2 =*/242).fork()).ldelim();
                if (message.androidFastrpc != null && Object.hasOwnProperty.call(message, "androidFastrpc"))
                    $root.perfetto.protos.AndroidFastrpcMetric.encode(message.androidFastrpc, writer.uint32(/* id 31, wireType 2 =*/250).fork()).ldelim();
                if (message.androidDmaHeap != null && Object.hasOwnProperty.call(message, "androidDmaHeap"))
                    $root.perfetto.protos.AndroidDmaHeapMetric.encode(message.androidDmaHeap, writer.uint32(/* id 32, wireType 2 =*/258).fork()).ldelim();
                if (message.traceStats != null && Object.hasOwnProperty.call(message, "traceStats"))
                    $root.perfetto.protos.TraceAnalysisStats.encode(message.traceStats, writer.uint32(/* id 33, wireType 2 =*/266).fork()).ldelim();
                return writer;
            };

            /**
             * Encodes the specified TraceMetrics message, length delimited. Does not implicitly {@link perfetto.protos.TraceMetrics.verify|verify} messages.
             * @function encodeDelimited
             * @memberof perfetto.protos.TraceMetrics
             * @static
             * @param {perfetto.protos.ITraceMetrics} message TraceMetrics message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            TraceMetrics.encodeDelimited = function encodeDelimited(message, writer) {
                return this.encode(message, writer).ldelim();
            };

            /**
             * Decodes a TraceMetrics message from the specified reader or buffer.
             * @function decode
             * @memberof perfetto.protos.TraceMetrics
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @param {number} [length] Message length if known beforehand
             * @returns {perfetto.protos.TraceMetrics} TraceMetrics
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            TraceMetrics.decode = function decode(reader, length) {
                if (!(reader instanceof $Reader))
                    reader = $Reader.create(reader);
                var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.TraceMetrics();
                while (reader.pos < end) {
                    var tag = reader.uint32();
                    switch (tag >>> 3) {
                    case 5:
                        message.androidBatt = $root.perfetto.protos.AndroidBatteryMetric.decode(reader, reader.uint32());
                        break;
                    case 6:
                        message.androidCpu = $root.perfetto.protos.AndroidCpuMetric.decode(reader, reader.uint32());
                        break;
                    case 1:
                        message.androidMem = $root.perfetto.protos.AndroidMemoryMetric.decode(reader, reader.uint32());
                        break;
                    case 11:
                        message.androidMemUnagg = $root.perfetto.protos.AndroidMemoryUnaggregatedMetric.decode(reader, reader.uint32());
                        break;
                    case 12:
                        message.androidPackageList = $root.perfetto.protos.AndroidPackageList.decode(reader, reader.uint32());
                        break;
                    case 9:
                        message.androidIon = $root.perfetto.protos.AndroidIonMetric.decode(reader, reader.uint32());
                        break;
                    case 31:
                        message.androidFastrpc = $root.perfetto.protos.AndroidFastrpcMetric.decode(reader, reader.uint32());
                        break;
                    case 8:
                        message.androidLmk = $root.perfetto.protos.AndroidLmkMetric.decode(reader, reader.uint32());
                        break;
                    case 7:
                        message.androidPowrails = $root.perfetto.protos.AndroidPowerRails.decode(reader, reader.uint32());
                        break;
                    case 2:
                        message.androidStartup = $root.perfetto.protos.AndroidStartupMetric.decode(reader, reader.uint32());
                        break;
                    case 3:
                        message.traceMetadata = $root.perfetto.protos.TraceMetadata.decode(reader, reader.uint32());
                        break;
                    case 33:
                        message.traceStats = $root.perfetto.protos.TraceAnalysisStats.decode(reader, reader.uint32());
                        break;
                    case 15:
                        message.unsymbolizedFrames = $root.perfetto.protos.UnsymbolizedFrames.decode(reader, reader.uint32());
                        break;
                    case 17:
                        message.javaHeapStats = $root.perfetto.protos.JavaHeapStats.decode(reader, reader.uint32());
                        break;
                    case 21:
                        message.javaHeapHistogram = $root.perfetto.protos.JavaHeapHistogram.decode(reader, reader.uint32());
                        break;
                    case 18:
                        message.androidLmkReason = $root.perfetto.protos.AndroidLmkReasonMetric.decode(reader, reader.uint32());
                        break;
                    case 20:
                        message.androidHwuiMetric = $root.perfetto.protos.AndroidHwuiMetric.decode(reader, reader.uint32());
                        break;
                    case 22:
                        message.displayMetrics = $root.perfetto.protos.AndroidDisplayMetrics.decode(reader, reader.uint32());
                        break;
                    case 23:
                        message.androidTaskNames = $root.perfetto.protos.AndroidTaskNames.decode(reader, reader.uint32());
                        break;
                    case 24:
                        message.androidThreadTimeInState = $root.perfetto.protos.AndroidThreadTimeInStateMetric.decode(reader, reader.uint32());
                        break;
                    case 25:
                        message.androidSurfaceflinger = $root.perfetto.protos.AndroidSurfaceflingerMetric.decode(reader, reader.uint32());
                        break;
                    case 26:
                        message.androidGpu = $root.perfetto.protos.AndroidGpuMetric.decode(reader, reader.uint32());
                        break;
                    case 27:
                        message.androidSysuiCuj = $root.perfetto.protos.AndroidSysUiCujMetrics.decode(reader, reader.uint32());
                        break;
                    case 28:
                        message.androidHwcomposer = $root.perfetto.protos.AndroidHwcomposerMetrics.decode(reader, reader.uint32());
                        break;
                    case 29:
                        message.androidJank = $root.perfetto.protos.AndroidJankMetrics.decode(reader, reader.uint32());
                        break;
                    case 30:
                        message.g2d = $root.perfetto.protos.G2dMetrics.decode(reader, reader.uint32());
                        break;
                    case 32:
                        message.androidDmaHeap = $root.perfetto.protos.AndroidDmaHeapMetric.decode(reader, reader.uint32());
                        break;
                    default:
                        reader.skipType(tag & 7);
                        break;
                    }
                }
                return message;
            };

            /**
             * Decodes a TraceMetrics message from the specified reader or buffer, length delimited.
             * @function decodeDelimited
             * @memberof perfetto.protos.TraceMetrics
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @returns {perfetto.protos.TraceMetrics} TraceMetrics
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            TraceMetrics.decodeDelimited = function decodeDelimited(reader) {
                if (!(reader instanceof $Reader))
                    reader = new $Reader(reader);
                return this.decode(reader, reader.uint32());
            };

            /**
             * Verifies a TraceMetrics message.
             * @function verify
             * @memberof perfetto.protos.TraceMetrics
             * @static
             * @param {Object.<string,*>} message Plain object to verify
             * @returns {string|null} `null` if valid, otherwise the reason why it is not
             */
            TraceMetrics.verify = function verify(message) {
                if (typeof message !== "object" || message === null)
                    return "object expected";
                if (message.androidBatt != null && message.hasOwnProperty("androidBatt")) {
                    var error = $root.perfetto.protos.AndroidBatteryMetric.verify(message.androidBatt);
                    if (error)
                        return "androidBatt." + error;
                }
                if (message.androidCpu != null && message.hasOwnProperty("androidCpu")) {
                    var error = $root.perfetto.protos.AndroidCpuMetric.verify(message.androidCpu);
                    if (error)
                        return "androidCpu." + error;
                }
                if (message.androidMem != null && message.hasOwnProperty("androidMem")) {
                    var error = $root.perfetto.protos.AndroidMemoryMetric.verify(message.androidMem);
                    if (error)
                        return "androidMem." + error;
                }
                if (message.androidMemUnagg != null && message.hasOwnProperty("androidMemUnagg")) {
                    var error = $root.perfetto.protos.AndroidMemoryUnaggregatedMetric.verify(message.androidMemUnagg);
                    if (error)
                        return "androidMemUnagg." + error;
                }
                if (message.androidPackageList != null && message.hasOwnProperty("androidPackageList")) {
                    var error = $root.perfetto.protos.AndroidPackageList.verify(message.androidPackageList);
                    if (error)
                        return "androidPackageList." + error;
                }
                if (message.androidIon != null && message.hasOwnProperty("androidIon")) {
                    var error = $root.perfetto.protos.AndroidIonMetric.verify(message.androidIon);
                    if (error)
                        return "androidIon." + error;
                }
                if (message.androidFastrpc != null && message.hasOwnProperty("androidFastrpc")) {
                    var error = $root.perfetto.protos.AndroidFastrpcMetric.verify(message.androidFastrpc);
                    if (error)
                        return "androidFastrpc." + error;
                }
                if (message.androidLmk != null && message.hasOwnProperty("androidLmk")) {
                    var error = $root.perfetto.protos.AndroidLmkMetric.verify(message.androidLmk);
                    if (error)
                        return "androidLmk." + error;
                }
                if (message.androidPowrails != null && message.hasOwnProperty("androidPowrails")) {
                    var error = $root.perfetto.protos.AndroidPowerRails.verify(message.androidPowrails);
                    if (error)
                        return "androidPowrails." + error;
                }
                if (message.androidStartup != null && message.hasOwnProperty("androidStartup")) {
                    var error = $root.perfetto.protos.AndroidStartupMetric.verify(message.androidStartup);
                    if (error)
                        return "androidStartup." + error;
                }
                if (message.traceMetadata != null && message.hasOwnProperty("traceMetadata")) {
                    var error = $root.perfetto.protos.TraceMetadata.verify(message.traceMetadata);
                    if (error)
                        return "traceMetadata." + error;
                }
                if (message.traceStats != null && message.hasOwnProperty("traceStats")) {
                    var error = $root.perfetto.protos.TraceAnalysisStats.verify(message.traceStats);
                    if (error)
                        return "traceStats." + error;
                }
                if (message.unsymbolizedFrames != null && message.hasOwnProperty("unsymbolizedFrames")) {
                    var error = $root.perfetto.protos.UnsymbolizedFrames.verify(message.unsymbolizedFrames);
                    if (error)
                        return "unsymbolizedFrames." + error;
                }
                if (message.javaHeapStats != null && message.hasOwnProperty("javaHeapStats")) {
                    var error = $root.perfetto.protos.JavaHeapStats.verify(message.javaHeapStats);
                    if (error)
                        return "javaHeapStats." + error;
                }
                if (message.javaHeapHistogram != null && message.hasOwnProperty("javaHeapHistogram")) {
                    var error = $root.perfetto.protos.JavaHeapHistogram.verify(message.javaHeapHistogram);
                    if (error)
                        return "javaHeapHistogram." + error;
                }
                if (message.androidLmkReason != null && message.hasOwnProperty("androidLmkReason")) {
                    var error = $root.perfetto.protos.AndroidLmkReasonMetric.verify(message.androidLmkReason);
                    if (error)
                        return "androidLmkReason." + error;
                }
                if (message.androidHwuiMetric != null && message.hasOwnProperty("androidHwuiMetric")) {
                    var error = $root.perfetto.protos.AndroidHwuiMetric.verify(message.androidHwuiMetric);
                    if (error)
                        return "androidHwuiMetric." + error;
                }
                if (message.displayMetrics != null && message.hasOwnProperty("displayMetrics")) {
                    var error = $root.perfetto.protos.AndroidDisplayMetrics.verify(message.displayMetrics);
                    if (error)
                        return "displayMetrics." + error;
                }
                if (message.androidTaskNames != null && message.hasOwnProperty("androidTaskNames")) {
                    var error = $root.perfetto.protos.AndroidTaskNames.verify(message.androidTaskNames);
                    if (error)
                        return "androidTaskNames." + error;
                }
                if (message.androidThreadTimeInState != null && message.hasOwnProperty("androidThreadTimeInState")) {
                    var error = $root.perfetto.protos.AndroidThreadTimeInStateMetric.verify(message.androidThreadTimeInState);
                    if (error)
                        return "androidThreadTimeInState." + error;
                }
                if (message.androidSurfaceflinger != null && message.hasOwnProperty("androidSurfaceflinger")) {
                    var error = $root.perfetto.protos.AndroidSurfaceflingerMetric.verify(message.androidSurfaceflinger);
                    if (error)
                        return "androidSurfaceflinger." + error;
                }
                if (message.androidGpu != null && message.hasOwnProperty("androidGpu")) {
                    var error = $root.perfetto.protos.AndroidGpuMetric.verify(message.androidGpu);
                    if (error)
                        return "androidGpu." + error;
                }
                if (message.androidSysuiCuj != null && message.hasOwnProperty("androidSysuiCuj")) {
                    var error = $root.perfetto.protos.AndroidSysUiCujMetrics.verify(message.androidSysuiCuj);
                    if (error)
                        return "androidSysuiCuj." + error;
                }
                if (message.androidHwcomposer != null && message.hasOwnProperty("androidHwcomposer")) {
                    var error = $root.perfetto.protos.AndroidHwcomposerMetrics.verify(message.androidHwcomposer);
                    if (error)
                        return "androidHwcomposer." + error;
                }
                if (message.androidJank != null && message.hasOwnProperty("androidJank")) {
                    var error = $root.perfetto.protos.AndroidJankMetrics.verify(message.androidJank);
                    if (error)
                        return "androidJank." + error;
                }
                if (message.g2d != null && message.hasOwnProperty("g2d")) {
                    var error = $root.perfetto.protos.G2dMetrics.verify(message.g2d);
                    if (error)
                        return "g2d." + error;
                }
                if (message.androidDmaHeap != null && message.hasOwnProperty("androidDmaHeap")) {
                    var error = $root.perfetto.protos.AndroidDmaHeapMetric.verify(message.androidDmaHeap);
                    if (error)
                        return "androidDmaHeap." + error;
                }
                return null;
            };

            /**
             * Creates a TraceMetrics message from a plain object. Also converts values to their respective internal types.
             * @function fromObject
             * @memberof perfetto.protos.TraceMetrics
             * @static
             * @param {Object.<string,*>} object Plain object
             * @returns {perfetto.protos.TraceMetrics} TraceMetrics
             */
            TraceMetrics.fromObject = function fromObject(object) {
                if (object instanceof $root.perfetto.protos.TraceMetrics)
                    return object;
                var message = new $root.perfetto.protos.TraceMetrics();
                if (object.androidBatt != null) {
                    if (typeof object.androidBatt !== "object")
                        throw TypeError(".perfetto.protos.TraceMetrics.androidBatt: object expected");
                    message.androidBatt = $root.perfetto.protos.AndroidBatteryMetric.fromObject(object.androidBatt);
                }
                if (object.androidCpu != null) {
                    if (typeof object.androidCpu !== "object")
                        throw TypeError(".perfetto.protos.TraceMetrics.androidCpu: object expected");
                    message.androidCpu = $root.perfetto.protos.AndroidCpuMetric.fromObject(object.androidCpu);
                }
                if (object.androidMem != null) {
                    if (typeof object.androidMem !== "object")
                        throw TypeError(".perfetto.protos.TraceMetrics.androidMem: object expected");
                    message.androidMem = $root.perfetto.protos.AndroidMemoryMetric.fromObject(object.androidMem);
                }
                if (object.androidMemUnagg != null) {
                    if (typeof object.androidMemUnagg !== "object")
                        throw TypeError(".perfetto.protos.TraceMetrics.androidMemUnagg: object expected");
                    message.androidMemUnagg = $root.perfetto.protos.AndroidMemoryUnaggregatedMetric.fromObject(object.androidMemUnagg);
                }
                if (object.androidPackageList != null) {
                    if (typeof object.androidPackageList !== "object")
                        throw TypeError(".perfetto.protos.TraceMetrics.androidPackageList: object expected");
                    message.androidPackageList = $root.perfetto.protos.AndroidPackageList.fromObject(object.androidPackageList);
                }
                if (object.androidIon != null) {
                    if (typeof object.androidIon !== "object")
                        throw TypeError(".perfetto.protos.TraceMetrics.androidIon: object expected");
                    message.androidIon = $root.perfetto.protos.AndroidIonMetric.fromObject(object.androidIon);
                }
                if (object.androidFastrpc != null) {
                    if (typeof object.androidFastrpc !== "object")
                        throw TypeError(".perfetto.protos.TraceMetrics.androidFastrpc: object expected");
                    message.androidFastrpc = $root.perfetto.protos.AndroidFastrpcMetric.fromObject(object.androidFastrpc);
                }
                if (object.androidLmk != null) {
                    if (typeof object.androidLmk !== "object")
                        throw TypeError(".perfetto.protos.TraceMetrics.androidLmk: object expected");
                    message.androidLmk = $root.perfetto.protos.AndroidLmkMetric.fromObject(object.androidLmk);
                }
                if (object.androidPowrails != null) {
                    if (typeof object.androidPowrails !== "object")
                        throw TypeError(".perfetto.protos.TraceMetrics.androidPowrails: object expected");
                    message.androidPowrails = $root.perfetto.protos.AndroidPowerRails.fromObject(object.androidPowrails);
                }
                if (object.androidStartup != null) {
                    if (typeof object.androidStartup !== "object")
                        throw TypeError(".perfetto.protos.TraceMetrics.androidStartup: object expected");
                    message.androidStartup = $root.perfetto.protos.AndroidStartupMetric.fromObject(object.androidStartup);
                }
                if (object.traceMetadata != null) {
                    if (typeof object.traceMetadata !== "object")
                        throw TypeError(".perfetto.protos.TraceMetrics.traceMetadata: object expected");
                    message.traceMetadata = $root.perfetto.protos.TraceMetadata.fromObject(object.traceMetadata);
                }
                if (object.traceStats != null) {
                    if (typeof object.traceStats !== "object")
                        throw TypeError(".perfetto.protos.TraceMetrics.traceStats: object expected");
                    message.traceStats = $root.perfetto.protos.TraceAnalysisStats.fromObject(object.traceStats);
                }
                if (object.unsymbolizedFrames != null) {
                    if (typeof object.unsymbolizedFrames !== "object")
                        throw TypeError(".perfetto.protos.TraceMetrics.unsymbolizedFrames: object expected");
                    message.unsymbolizedFrames = $root.perfetto.protos.UnsymbolizedFrames.fromObject(object.unsymbolizedFrames);
                }
                if (object.javaHeapStats != null) {
                    if (typeof object.javaHeapStats !== "object")
                        throw TypeError(".perfetto.protos.TraceMetrics.javaHeapStats: object expected");
                    message.javaHeapStats = $root.perfetto.protos.JavaHeapStats.fromObject(object.javaHeapStats);
                }
                if (object.javaHeapHistogram != null) {
                    if (typeof object.javaHeapHistogram !== "object")
                        throw TypeError(".perfetto.protos.TraceMetrics.javaHeapHistogram: object expected");
                    message.javaHeapHistogram = $root.perfetto.protos.JavaHeapHistogram.fromObject(object.javaHeapHistogram);
                }
                if (object.androidLmkReason != null) {
                    if (typeof object.androidLmkReason !== "object")
                        throw TypeError(".perfetto.protos.TraceMetrics.androidLmkReason: object expected");
                    message.androidLmkReason = $root.perfetto.protos.AndroidLmkReasonMetric.fromObject(object.androidLmkReason);
                }
                if (object.androidHwuiMetric != null) {
                    if (typeof object.androidHwuiMetric !== "object")
                        throw TypeError(".perfetto.protos.TraceMetrics.androidHwuiMetric: object expected");
                    message.androidHwuiMetric = $root.perfetto.protos.AndroidHwuiMetric.fromObject(object.androidHwuiMetric);
                }
                if (object.displayMetrics != null) {
                    if (typeof object.displayMetrics !== "object")
                        throw TypeError(".perfetto.protos.TraceMetrics.displayMetrics: object expected");
                    message.displayMetrics = $root.perfetto.protos.AndroidDisplayMetrics.fromObject(object.displayMetrics);
                }
                if (object.androidTaskNames != null) {
                    if (typeof object.androidTaskNames !== "object")
                        throw TypeError(".perfetto.protos.TraceMetrics.androidTaskNames: object expected");
                    message.androidTaskNames = $root.perfetto.protos.AndroidTaskNames.fromObject(object.androidTaskNames);
                }
                if (object.androidThreadTimeInState != null) {
                    if (typeof object.androidThreadTimeInState !== "object")
                        throw TypeError(".perfetto.protos.TraceMetrics.androidThreadTimeInState: object expected");
                    message.androidThreadTimeInState = $root.perfetto.protos.AndroidThreadTimeInStateMetric.fromObject(object.androidThreadTimeInState);
                }
                if (object.androidSurfaceflinger != null) {
                    if (typeof object.androidSurfaceflinger !== "object")
                        throw TypeError(".perfetto.protos.TraceMetrics.androidSurfaceflinger: object expected");
                    message.androidSurfaceflinger = $root.perfetto.protos.AndroidSurfaceflingerMetric.fromObject(object.androidSurfaceflinger);
                }
                if (object.androidGpu != null) {
                    if (typeof object.androidGpu !== "object")
                        throw TypeError(".perfetto.protos.TraceMetrics.androidGpu: object expected");
                    message.androidGpu = $root.perfetto.protos.AndroidGpuMetric.fromObject(object.androidGpu);
                }
                if (object.androidSysuiCuj != null) {
                    if (typeof object.androidSysuiCuj !== "object")
                        throw TypeError(".perfetto.protos.TraceMetrics.androidSysuiCuj: object expected");
                    message.androidSysuiCuj = $root.perfetto.protos.AndroidSysUiCujMetrics.fromObject(object.androidSysuiCuj);
                }
                if (object.androidHwcomposer != null) {
                    if (typeof object.androidHwcomposer !== "object")
                        throw TypeError(".perfetto.protos.TraceMetrics.androidHwcomposer: object expected");
                    message.androidHwcomposer = $root.perfetto.protos.AndroidHwcomposerMetrics.fromObject(object.androidHwcomposer);
                }
                if (object.androidJank != null) {
                    if (typeof object.androidJank !== "object")
                        throw TypeError(".perfetto.protos.TraceMetrics.androidJank: object expected");
                    message.androidJank = $root.perfetto.protos.AndroidJankMetrics.fromObject(object.androidJank);
                }
                if (object.g2d != null) {
                    if (typeof object.g2d !== "object")
                        throw TypeError(".perfetto.protos.TraceMetrics.g2d: object expected");
                    message.g2d = $root.perfetto.protos.G2dMetrics.fromObject(object.g2d);
                }
                if (object.androidDmaHeap != null) {
                    if (typeof object.androidDmaHeap !== "object")
                        throw TypeError(".perfetto.protos.TraceMetrics.androidDmaHeap: object expected");
                    message.androidDmaHeap = $root.perfetto.protos.AndroidDmaHeapMetric.fromObject(object.androidDmaHeap);
                }
                return message;
            };

            /**
             * Creates a plain object from a TraceMetrics message. Also converts values to other types if specified.
             * @function toObject
             * @memberof perfetto.protos.TraceMetrics
             * @static
             * @param {perfetto.protos.TraceMetrics} message TraceMetrics
             * @param {$protobuf.IConversionOptions} [options] Conversion options
             * @returns {Object.<string,*>} Plain object
             */
            TraceMetrics.toObject = function toObject(message, options) {
                if (!options)
                    options = {};
                var object = {};
                if (options.defaults) {
                    object.androidMem = null;
                    object.androidStartup = null;
                    object.traceMetadata = null;
                    object.androidBatt = null;
                    object.androidCpu = null;
                    object.androidPowrails = null;
                    object.androidLmk = null;
                    object.androidIon = null;
                    object.androidMemUnagg = null;
                    object.androidPackageList = null;
                    object.unsymbolizedFrames = null;
                    object.javaHeapStats = null;
                    object.androidLmkReason = null;
                    object.androidHwuiMetric = null;
                    object.javaHeapHistogram = null;
                    object.displayMetrics = null;
                    object.androidTaskNames = null;
                    object.androidThreadTimeInState = null;
                    object.androidSurfaceflinger = null;
                    object.androidGpu = null;
                    object.androidSysuiCuj = null;
                    object.androidHwcomposer = null;
                    object.androidJank = null;
                    object.g2d = null;
                    object.androidFastrpc = null;
                    object.androidDmaHeap = null;
                    object.traceStats = null;
                }
                if (message.androidMem != null && message.hasOwnProperty("androidMem"))
                    object.androidMem = $root.perfetto.protos.AndroidMemoryMetric.toObject(message.androidMem, options);
                if (message.androidStartup != null && message.hasOwnProperty("androidStartup"))
                    object.androidStartup = $root.perfetto.protos.AndroidStartupMetric.toObject(message.androidStartup, options);
                if (message.traceMetadata != null && message.hasOwnProperty("traceMetadata"))
                    object.traceMetadata = $root.perfetto.protos.TraceMetadata.toObject(message.traceMetadata, options);
                if (message.androidBatt != null && message.hasOwnProperty("androidBatt"))
                    object.androidBatt = $root.perfetto.protos.AndroidBatteryMetric.toObject(message.androidBatt, options);
                if (message.androidCpu != null && message.hasOwnProperty("androidCpu"))
                    object.androidCpu = $root.perfetto.protos.AndroidCpuMetric.toObject(message.androidCpu, options);
                if (message.androidPowrails != null && message.hasOwnProperty("androidPowrails"))
                    object.androidPowrails = $root.perfetto.protos.AndroidPowerRails.toObject(message.androidPowrails, options);
                if (message.androidLmk != null && message.hasOwnProperty("androidLmk"))
                    object.androidLmk = $root.perfetto.protos.AndroidLmkMetric.toObject(message.androidLmk, options);
                if (message.androidIon != null && message.hasOwnProperty("androidIon"))
                    object.androidIon = $root.perfetto.protos.AndroidIonMetric.toObject(message.androidIon, options);
                if (message.androidMemUnagg != null && message.hasOwnProperty("androidMemUnagg"))
                    object.androidMemUnagg = $root.perfetto.protos.AndroidMemoryUnaggregatedMetric.toObject(message.androidMemUnagg, options);
                if (message.androidPackageList != null && message.hasOwnProperty("androidPackageList"))
                    object.androidPackageList = $root.perfetto.protos.AndroidPackageList.toObject(message.androidPackageList, options);
                if (message.unsymbolizedFrames != null && message.hasOwnProperty("unsymbolizedFrames"))
                    object.unsymbolizedFrames = $root.perfetto.protos.UnsymbolizedFrames.toObject(message.unsymbolizedFrames, options);
                if (message.javaHeapStats != null && message.hasOwnProperty("javaHeapStats"))
                    object.javaHeapStats = $root.perfetto.protos.JavaHeapStats.toObject(message.javaHeapStats, options);
                if (message.androidLmkReason != null && message.hasOwnProperty("androidLmkReason"))
                    object.androidLmkReason = $root.perfetto.protos.AndroidLmkReasonMetric.toObject(message.androidLmkReason, options);
                if (message.androidHwuiMetric != null && message.hasOwnProperty("androidHwuiMetric"))
                    object.androidHwuiMetric = $root.perfetto.protos.AndroidHwuiMetric.toObject(message.androidHwuiMetric, options);
                if (message.javaHeapHistogram != null && message.hasOwnProperty("javaHeapHistogram"))
                    object.javaHeapHistogram = $root.perfetto.protos.JavaHeapHistogram.toObject(message.javaHeapHistogram, options);
                if (message.displayMetrics != null && message.hasOwnProperty("displayMetrics"))
                    object.displayMetrics = $root.perfetto.protos.AndroidDisplayMetrics.toObject(message.displayMetrics, options);
                if (message.androidTaskNames != null && message.hasOwnProperty("androidTaskNames"))
                    object.androidTaskNames = $root.perfetto.protos.AndroidTaskNames.toObject(message.androidTaskNames, options);
                if (message.androidThreadTimeInState != null && message.hasOwnProperty("androidThreadTimeInState"))
                    object.androidThreadTimeInState = $root.perfetto.protos.AndroidThreadTimeInStateMetric.toObject(message.androidThreadTimeInState, options);
                if (message.androidSurfaceflinger != null && message.hasOwnProperty("androidSurfaceflinger"))
                    object.androidSurfaceflinger = $root.perfetto.protos.AndroidSurfaceflingerMetric.toObject(message.androidSurfaceflinger, options);
                if (message.androidGpu != null && message.hasOwnProperty("androidGpu"))
                    object.androidGpu = $root.perfetto.protos.AndroidGpuMetric.toObject(message.androidGpu, options);
                if (message.androidSysuiCuj != null && message.hasOwnProperty("androidSysuiCuj"))
                    object.androidSysuiCuj = $root.perfetto.protos.AndroidSysUiCujMetrics.toObject(message.androidSysuiCuj, options);
                if (message.androidHwcomposer != null && message.hasOwnProperty("androidHwcomposer"))
                    object.androidHwcomposer = $root.perfetto.protos.AndroidHwcomposerMetrics.toObject(message.androidHwcomposer, options);
                if (message.androidJank != null && message.hasOwnProperty("androidJank"))
                    object.androidJank = $root.perfetto.protos.AndroidJankMetrics.toObject(message.androidJank, options);
                if (message.g2d != null && message.hasOwnProperty("g2d"))
                    object.g2d = $root.perfetto.protos.G2dMetrics.toObject(message.g2d, options);
                if (message.androidFastrpc != null && message.hasOwnProperty("androidFastrpc"))
                    object.androidFastrpc = $root.perfetto.protos.AndroidFastrpcMetric.toObject(message.androidFastrpc, options);
                if (message.androidDmaHeap != null && message.hasOwnProperty("androidDmaHeap"))
                    object.androidDmaHeap = $root.perfetto.protos.AndroidDmaHeapMetric.toObject(message.androidDmaHeap, options);
                if (message.traceStats != null && message.hasOwnProperty("traceStats"))
                    object.traceStats = $root.perfetto.protos.TraceAnalysisStats.toObject(message.traceStats, options);
                return object;
            };

            /**
             * Converts this TraceMetrics to JSON.
             * @function toJSON
             * @memberof perfetto.protos.TraceMetrics
             * @instance
             * @returns {Object.<string,*>} JSON object
             */
            TraceMetrics.prototype.toJSON = function toJSON() {
                return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
            };

            return TraceMetrics;
        })();

        protos.AndroidBatteryMetric = (function() {

            /**
             * Properties of an AndroidBatteryMetric.
             * @memberof perfetto.protos
             * @interface IAndroidBatteryMetric
             * @property {Array.<perfetto.protos.AndroidBatteryMetric.IBatteryCounters>|null} [batteryCounters] AndroidBatteryMetric batteryCounters
             * @property {perfetto.protos.AndroidBatteryMetric.IBatteryAggregates|null} [batteryAggregates] AndroidBatteryMetric batteryAggregates
             * @property {Array.<perfetto.protos.AndroidBatteryMetric.ISuspendPeriod>|null} [suspendPeriod] AndroidBatteryMetric suspendPeriod
             */

            /**
             * Constructs a new AndroidBatteryMetric.
             * @memberof perfetto.protos
             * @classdesc Represents an AndroidBatteryMetric.
             * @implements IAndroidBatteryMetric
             * @constructor
             * @param {perfetto.protos.IAndroidBatteryMetric=} [properties] Properties to set
             */
            function AndroidBatteryMetric(properties) {
                this.batteryCounters = [];
                this.suspendPeriod = [];
                if (properties)
                    for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                        if (properties[keys[i]] != null)
                            this[keys[i]] = properties[keys[i]];
            }

            /**
             * AndroidBatteryMetric batteryCounters.
             * @member {Array.<perfetto.protos.AndroidBatteryMetric.IBatteryCounters>} batteryCounters
             * @memberof perfetto.protos.AndroidBatteryMetric
             * @instance
             */
            AndroidBatteryMetric.prototype.batteryCounters = $util.emptyArray;

            /**
             * AndroidBatteryMetric batteryAggregates.
             * @member {perfetto.protos.AndroidBatteryMetric.IBatteryAggregates|null|undefined} batteryAggregates
             * @memberof perfetto.protos.AndroidBatteryMetric
             * @instance
             */
            AndroidBatteryMetric.prototype.batteryAggregates = null;

            /**
             * AndroidBatteryMetric suspendPeriod.
             * @member {Array.<perfetto.protos.AndroidBatteryMetric.ISuspendPeriod>} suspendPeriod
             * @memberof perfetto.protos.AndroidBatteryMetric
             * @instance
             */
            AndroidBatteryMetric.prototype.suspendPeriod = $util.emptyArray;

            /**
             * Creates a new AndroidBatteryMetric instance using the specified properties.
             * @function create
             * @memberof perfetto.protos.AndroidBatteryMetric
             * @static
             * @param {perfetto.protos.IAndroidBatteryMetric=} [properties] Properties to set
             * @returns {perfetto.protos.AndroidBatteryMetric} AndroidBatteryMetric instance
             */
            AndroidBatteryMetric.create = function create(properties) {
                return new AndroidBatteryMetric(properties);
            };

            /**
             * Encodes the specified AndroidBatteryMetric message. Does not implicitly {@link perfetto.protos.AndroidBatteryMetric.verify|verify} messages.
             * @function encode
             * @memberof perfetto.protos.AndroidBatteryMetric
             * @static
             * @param {perfetto.protos.IAndroidBatteryMetric} message AndroidBatteryMetric message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            AndroidBatteryMetric.encode = function encode(message, writer) {
                if (!writer)
                    writer = $Writer.create();
                if (message.batteryCounters != null && message.batteryCounters.length)
                    for (var i = 0; i < message.batteryCounters.length; ++i)
                        $root.perfetto.protos.AndroidBatteryMetric.BatteryCounters.encode(message.batteryCounters[i], writer.uint32(/* id 1, wireType 2 =*/10).fork()).ldelim();
                if (message.batteryAggregates != null && Object.hasOwnProperty.call(message, "batteryAggregates"))
                    $root.perfetto.protos.AndroidBatteryMetric.BatteryAggregates.encode(message.batteryAggregates, writer.uint32(/* id 2, wireType 2 =*/18).fork()).ldelim();
                if (message.suspendPeriod != null && message.suspendPeriod.length)
                    for (var i = 0; i < message.suspendPeriod.length; ++i)
                        $root.perfetto.protos.AndroidBatteryMetric.SuspendPeriod.encode(message.suspendPeriod[i], writer.uint32(/* id 3, wireType 2 =*/26).fork()).ldelim();
                return writer;
            };

            /**
             * Encodes the specified AndroidBatteryMetric message, length delimited. Does not implicitly {@link perfetto.protos.AndroidBatteryMetric.verify|verify} messages.
             * @function encodeDelimited
             * @memberof perfetto.protos.AndroidBatteryMetric
             * @static
             * @param {perfetto.protos.IAndroidBatteryMetric} message AndroidBatteryMetric message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            AndroidBatteryMetric.encodeDelimited = function encodeDelimited(message, writer) {
                return this.encode(message, writer).ldelim();
            };

            /**
             * Decodes an AndroidBatteryMetric message from the specified reader or buffer.
             * @function decode
             * @memberof perfetto.protos.AndroidBatteryMetric
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @param {number} [length] Message length if known beforehand
             * @returns {perfetto.protos.AndroidBatteryMetric} AndroidBatteryMetric
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            AndroidBatteryMetric.decode = function decode(reader, length) {
                if (!(reader instanceof $Reader))
                    reader = $Reader.create(reader);
                var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.AndroidBatteryMetric();
                while (reader.pos < end) {
                    var tag = reader.uint32();
                    switch (tag >>> 3) {
                    case 1:
                        if (!(message.batteryCounters && message.batteryCounters.length))
                            message.batteryCounters = [];
                        message.batteryCounters.push($root.perfetto.protos.AndroidBatteryMetric.BatteryCounters.decode(reader, reader.uint32()));
                        break;
                    case 2:
                        message.batteryAggregates = $root.perfetto.protos.AndroidBatteryMetric.BatteryAggregates.decode(reader, reader.uint32());
                        break;
                    case 3:
                        if (!(message.suspendPeriod && message.suspendPeriod.length))
                            message.suspendPeriod = [];
                        message.suspendPeriod.push($root.perfetto.protos.AndroidBatteryMetric.SuspendPeriod.decode(reader, reader.uint32()));
                        break;
                    default:
                        reader.skipType(tag & 7);
                        break;
                    }
                }
                return message;
            };

            /**
             * Decodes an AndroidBatteryMetric message from the specified reader or buffer, length delimited.
             * @function decodeDelimited
             * @memberof perfetto.protos.AndroidBatteryMetric
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @returns {perfetto.protos.AndroidBatteryMetric} AndroidBatteryMetric
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            AndroidBatteryMetric.decodeDelimited = function decodeDelimited(reader) {
                if (!(reader instanceof $Reader))
                    reader = new $Reader(reader);
                return this.decode(reader, reader.uint32());
            };

            /**
             * Verifies an AndroidBatteryMetric message.
             * @function verify
             * @memberof perfetto.protos.AndroidBatteryMetric
             * @static
             * @param {Object.<string,*>} message Plain object to verify
             * @returns {string|null} `null` if valid, otherwise the reason why it is not
             */
            AndroidBatteryMetric.verify = function verify(message) {
                if (typeof message !== "object" || message === null)
                    return "object expected";
                if (message.batteryCounters != null && message.hasOwnProperty("batteryCounters")) {
                    if (!Array.isArray(message.batteryCounters))
                        return "batteryCounters: array expected";
                    for (var i = 0; i < message.batteryCounters.length; ++i) {
                        var error = $root.perfetto.protos.AndroidBatteryMetric.BatteryCounters.verify(message.batteryCounters[i]);
                        if (error)
                            return "batteryCounters." + error;
                    }
                }
                if (message.batteryAggregates != null && message.hasOwnProperty("batteryAggregates")) {
                    var error = $root.perfetto.protos.AndroidBatteryMetric.BatteryAggregates.verify(message.batteryAggregates);
                    if (error)
                        return "batteryAggregates." + error;
                }
                if (message.suspendPeriod != null && message.hasOwnProperty("suspendPeriod")) {
                    if (!Array.isArray(message.suspendPeriod))
                        return "suspendPeriod: array expected";
                    for (var i = 0; i < message.suspendPeriod.length; ++i) {
                        var error = $root.perfetto.protos.AndroidBatteryMetric.SuspendPeriod.verify(message.suspendPeriod[i]);
                        if (error)
                            return "suspendPeriod." + error;
                    }
                }
                return null;
            };

            /**
             * Creates an AndroidBatteryMetric message from a plain object. Also converts values to their respective internal types.
             * @function fromObject
             * @memberof perfetto.protos.AndroidBatteryMetric
             * @static
             * @param {Object.<string,*>} object Plain object
             * @returns {perfetto.protos.AndroidBatteryMetric} AndroidBatteryMetric
             */
            AndroidBatteryMetric.fromObject = function fromObject(object) {
                if (object instanceof $root.perfetto.protos.AndroidBatteryMetric)
                    return object;
                var message = new $root.perfetto.protos.AndroidBatteryMetric();
                if (object.batteryCounters) {
                    if (!Array.isArray(object.batteryCounters))
                        throw TypeError(".perfetto.protos.AndroidBatteryMetric.batteryCounters: array expected");
                    message.batteryCounters = [];
                    for (var i = 0; i < object.batteryCounters.length; ++i) {
                        if (typeof object.batteryCounters[i] !== "object")
                            throw TypeError(".perfetto.protos.AndroidBatteryMetric.batteryCounters: object expected");
                        message.batteryCounters[i] = $root.perfetto.protos.AndroidBatteryMetric.BatteryCounters.fromObject(object.batteryCounters[i]);
                    }
                }
                if (object.batteryAggregates != null) {
                    if (typeof object.batteryAggregates !== "object")
                        throw TypeError(".perfetto.protos.AndroidBatteryMetric.batteryAggregates: object expected");
                    message.batteryAggregates = $root.perfetto.protos.AndroidBatteryMetric.BatteryAggregates.fromObject(object.batteryAggregates);
                }
                if (object.suspendPeriod) {
                    if (!Array.isArray(object.suspendPeriod))
                        throw TypeError(".perfetto.protos.AndroidBatteryMetric.suspendPeriod: array expected");
                    message.suspendPeriod = [];
                    for (var i = 0; i < object.suspendPeriod.length; ++i) {
                        if (typeof object.suspendPeriod[i] !== "object")
                            throw TypeError(".perfetto.protos.AndroidBatteryMetric.suspendPeriod: object expected");
                        message.suspendPeriod[i] = $root.perfetto.protos.AndroidBatteryMetric.SuspendPeriod.fromObject(object.suspendPeriod[i]);
                    }
                }
                return message;
            };

            /**
             * Creates a plain object from an AndroidBatteryMetric message. Also converts values to other types if specified.
             * @function toObject
             * @memberof perfetto.protos.AndroidBatteryMetric
             * @static
             * @param {perfetto.protos.AndroidBatteryMetric} message AndroidBatteryMetric
             * @param {$protobuf.IConversionOptions} [options] Conversion options
             * @returns {Object.<string,*>} Plain object
             */
            AndroidBatteryMetric.toObject = function toObject(message, options) {
                if (!options)
                    options = {};
                var object = {};
                if (options.arrays || options.defaults) {
                    object.batteryCounters = [];
                    object.suspendPeriod = [];
                }
                if (options.defaults)
                    object.batteryAggregates = null;
                if (message.batteryCounters && message.batteryCounters.length) {
                    object.batteryCounters = [];
                    for (var j = 0; j < message.batteryCounters.length; ++j)
                        object.batteryCounters[j] = $root.perfetto.protos.AndroidBatteryMetric.BatteryCounters.toObject(message.batteryCounters[j], options);
                }
                if (message.batteryAggregates != null && message.hasOwnProperty("batteryAggregates"))
                    object.batteryAggregates = $root.perfetto.protos.AndroidBatteryMetric.BatteryAggregates.toObject(message.batteryAggregates, options);
                if (message.suspendPeriod && message.suspendPeriod.length) {
                    object.suspendPeriod = [];
                    for (var j = 0; j < message.suspendPeriod.length; ++j)
                        object.suspendPeriod[j] = $root.perfetto.protos.AndroidBatteryMetric.SuspendPeriod.toObject(message.suspendPeriod[j], options);
                }
                return object;
            };

            /**
             * Converts this AndroidBatteryMetric to JSON.
             * @function toJSON
             * @memberof perfetto.protos.AndroidBatteryMetric
             * @instance
             * @returns {Object.<string,*>} JSON object
             */
            AndroidBatteryMetric.prototype.toJSON = function toJSON() {
                return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
            };

            AndroidBatteryMetric.BatteryCounters = (function() {

                /**
                 * Properties of a BatteryCounters.
                 * @memberof perfetto.protos.AndroidBatteryMetric
                 * @interface IBatteryCounters
                 * @property {number|null} [timestampNs] BatteryCounters timestampNs
                 * @property {number|null} [chargeCounterUah] BatteryCounters chargeCounterUah
                 * @property {number|null} [capacityPercent] BatteryCounters capacityPercent
                 * @property {number|null} [currentUa] BatteryCounters currentUa
                 * @property {number|null} [currentAvgUa] BatteryCounters currentAvgUa
                 */

                /**
                 * Constructs a new BatteryCounters.
                 * @memberof perfetto.protos.AndroidBatteryMetric
                 * @classdesc Represents a BatteryCounters.
                 * @implements IBatteryCounters
                 * @constructor
                 * @param {perfetto.protos.AndroidBatteryMetric.IBatteryCounters=} [properties] Properties to set
                 */
                function BatteryCounters(properties) {
                    if (properties)
                        for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                            if (properties[keys[i]] != null)
                                this[keys[i]] = properties[keys[i]];
                }

                /**
                 * BatteryCounters timestampNs.
                 * @member {number} timestampNs
                 * @memberof perfetto.protos.AndroidBatteryMetric.BatteryCounters
                 * @instance
                 */
                BatteryCounters.prototype.timestampNs = $util.Long ? $util.Long.fromBits(0,0,false) : 0;

                /**
                 * BatteryCounters chargeCounterUah.
                 * @member {number} chargeCounterUah
                 * @memberof perfetto.protos.AndroidBatteryMetric.BatteryCounters
                 * @instance
                 */
                BatteryCounters.prototype.chargeCounterUah = 0;

                /**
                 * BatteryCounters capacityPercent.
                 * @member {number} capacityPercent
                 * @memberof perfetto.protos.AndroidBatteryMetric.BatteryCounters
                 * @instance
                 */
                BatteryCounters.prototype.capacityPercent = 0;

                /**
                 * BatteryCounters currentUa.
                 * @member {number} currentUa
                 * @memberof perfetto.protos.AndroidBatteryMetric.BatteryCounters
                 * @instance
                 */
                BatteryCounters.prototype.currentUa = 0;

                /**
                 * BatteryCounters currentAvgUa.
                 * @member {number} currentAvgUa
                 * @memberof perfetto.protos.AndroidBatteryMetric.BatteryCounters
                 * @instance
                 */
                BatteryCounters.prototype.currentAvgUa = 0;

                /**
                 * Creates a new BatteryCounters instance using the specified properties.
                 * @function create
                 * @memberof perfetto.protos.AndroidBatteryMetric.BatteryCounters
                 * @static
                 * @param {perfetto.protos.AndroidBatteryMetric.IBatteryCounters=} [properties] Properties to set
                 * @returns {perfetto.protos.AndroidBatteryMetric.BatteryCounters} BatteryCounters instance
                 */
                BatteryCounters.create = function create(properties) {
                    return new BatteryCounters(properties);
                };

                /**
                 * Encodes the specified BatteryCounters message. Does not implicitly {@link perfetto.protos.AndroidBatteryMetric.BatteryCounters.verify|verify} messages.
                 * @function encode
                 * @memberof perfetto.protos.AndroidBatteryMetric.BatteryCounters
                 * @static
                 * @param {perfetto.protos.AndroidBatteryMetric.IBatteryCounters} message BatteryCounters message or plain object to encode
                 * @param {$protobuf.Writer} [writer] Writer to encode to
                 * @returns {$protobuf.Writer} Writer
                 */
                BatteryCounters.encode = function encode(message, writer) {
                    if (!writer)
                        writer = $Writer.create();
                    if (message.timestampNs != null && Object.hasOwnProperty.call(message, "timestampNs"))
                        writer.uint32(/* id 1, wireType 0 =*/8).int64(message.timestampNs);
                    if (message.chargeCounterUah != null && Object.hasOwnProperty.call(message, "chargeCounterUah"))
                        writer.uint32(/* id 2, wireType 1 =*/17).double(message.chargeCounterUah);
                    if (message.capacityPercent != null && Object.hasOwnProperty.call(message, "capacityPercent"))
                        writer.uint32(/* id 3, wireType 5 =*/29).float(message.capacityPercent);
                    if (message.currentUa != null && Object.hasOwnProperty.call(message, "currentUa"))
                        writer.uint32(/* id 4, wireType 1 =*/33).double(message.currentUa);
                    if (message.currentAvgUa != null && Object.hasOwnProperty.call(message, "currentAvgUa"))
                        writer.uint32(/* id 5, wireType 1 =*/41).double(message.currentAvgUa);
                    return writer;
                };

                /**
                 * Encodes the specified BatteryCounters message, length delimited. Does not implicitly {@link perfetto.protos.AndroidBatteryMetric.BatteryCounters.verify|verify} messages.
                 * @function encodeDelimited
                 * @memberof perfetto.protos.AndroidBatteryMetric.BatteryCounters
                 * @static
                 * @param {perfetto.protos.AndroidBatteryMetric.IBatteryCounters} message BatteryCounters message or plain object to encode
                 * @param {$protobuf.Writer} [writer] Writer to encode to
                 * @returns {$protobuf.Writer} Writer
                 */
                BatteryCounters.encodeDelimited = function encodeDelimited(message, writer) {
                    return this.encode(message, writer).ldelim();
                };

                /**
                 * Decodes a BatteryCounters message from the specified reader or buffer.
                 * @function decode
                 * @memberof perfetto.protos.AndroidBatteryMetric.BatteryCounters
                 * @static
                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                 * @param {number} [length] Message length if known beforehand
                 * @returns {perfetto.protos.AndroidBatteryMetric.BatteryCounters} BatteryCounters
                 * @throws {Error} If the payload is not a reader or valid buffer
                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
                 */
                BatteryCounters.decode = function decode(reader, length) {
                    if (!(reader instanceof $Reader))
                        reader = $Reader.create(reader);
                    var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.AndroidBatteryMetric.BatteryCounters();
                    while (reader.pos < end) {
                        var tag = reader.uint32();
                        switch (tag >>> 3) {
                        case 1:
                            message.timestampNs = reader.int64();
                            break;
                        case 2:
                            message.chargeCounterUah = reader.double();
                            break;
                        case 3:
                            message.capacityPercent = reader.float();
                            break;
                        case 4:
                            message.currentUa = reader.double();
                            break;
                        case 5:
                            message.currentAvgUa = reader.double();
                            break;
                        default:
                            reader.skipType(tag & 7);
                            break;
                        }
                    }
                    return message;
                };

                /**
                 * Decodes a BatteryCounters message from the specified reader or buffer, length delimited.
                 * @function decodeDelimited
                 * @memberof perfetto.protos.AndroidBatteryMetric.BatteryCounters
                 * @static
                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                 * @returns {perfetto.protos.AndroidBatteryMetric.BatteryCounters} BatteryCounters
                 * @throws {Error} If the payload is not a reader or valid buffer
                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
                 */
                BatteryCounters.decodeDelimited = function decodeDelimited(reader) {
                    if (!(reader instanceof $Reader))
                        reader = new $Reader(reader);
                    return this.decode(reader, reader.uint32());
                };

                /**
                 * Verifies a BatteryCounters message.
                 * @function verify
                 * @memberof perfetto.protos.AndroidBatteryMetric.BatteryCounters
                 * @static
                 * @param {Object.<string,*>} message Plain object to verify
                 * @returns {string|null} `null` if valid, otherwise the reason why it is not
                 */
                BatteryCounters.verify = function verify(message) {
                    if (typeof message !== "object" || message === null)
                        return "object expected";
                    if (message.timestampNs != null && message.hasOwnProperty("timestampNs"))
                        if (!$util.isInteger(message.timestampNs) && !(message.timestampNs && $util.isInteger(message.timestampNs.low) && $util.isInteger(message.timestampNs.high)))
                            return "timestampNs: integer|Long expected";
                    if (message.chargeCounterUah != null && message.hasOwnProperty("chargeCounterUah"))
                        if (typeof message.chargeCounterUah !== "number")
                            return "chargeCounterUah: number expected";
                    if (message.capacityPercent != null && message.hasOwnProperty("capacityPercent"))
                        if (typeof message.capacityPercent !== "number")
                            return "capacityPercent: number expected";
                    if (message.currentUa != null && message.hasOwnProperty("currentUa"))
                        if (typeof message.currentUa !== "number")
                            return "currentUa: number expected";
                    if (message.currentAvgUa != null && message.hasOwnProperty("currentAvgUa"))
                        if (typeof message.currentAvgUa !== "number")
                            return "currentAvgUa: number expected";
                    return null;
                };

                /**
                 * Creates a BatteryCounters message from a plain object. Also converts values to their respective internal types.
                 * @function fromObject
                 * @memberof perfetto.protos.AndroidBatteryMetric.BatteryCounters
                 * @static
                 * @param {Object.<string,*>} object Plain object
                 * @returns {perfetto.protos.AndroidBatteryMetric.BatteryCounters} BatteryCounters
                 */
                BatteryCounters.fromObject = function fromObject(object) {
                    if (object instanceof $root.perfetto.protos.AndroidBatteryMetric.BatteryCounters)
                        return object;
                    var message = new $root.perfetto.protos.AndroidBatteryMetric.BatteryCounters();
                    if (object.timestampNs != null)
                        if ($util.Long)
                            (message.timestampNs = $util.Long.fromValue(object.timestampNs)).unsigned = false;
                        else if (typeof object.timestampNs === "string")
                            message.timestampNs = parseInt(object.timestampNs, 10);
                        else if (typeof object.timestampNs === "number")
                            message.timestampNs = object.timestampNs;
                        else if (typeof object.timestampNs === "object")
                            message.timestampNs = new $util.LongBits(object.timestampNs.low >>> 0, object.timestampNs.high >>> 0).toNumber();
                    if (object.chargeCounterUah != null)
                        message.chargeCounterUah = Number(object.chargeCounterUah);
                    if (object.capacityPercent != null)
                        message.capacityPercent = Number(object.capacityPercent);
                    if (object.currentUa != null)
                        message.currentUa = Number(object.currentUa);
                    if (object.currentAvgUa != null)
                        message.currentAvgUa = Number(object.currentAvgUa);
                    return message;
                };

                /**
                 * Creates a plain object from a BatteryCounters message. Also converts values to other types if specified.
                 * @function toObject
                 * @memberof perfetto.protos.AndroidBatteryMetric.BatteryCounters
                 * @static
                 * @param {perfetto.protos.AndroidBatteryMetric.BatteryCounters} message BatteryCounters
                 * @param {$protobuf.IConversionOptions} [options] Conversion options
                 * @returns {Object.<string,*>} Plain object
                 */
                BatteryCounters.toObject = function toObject(message, options) {
                    if (!options)
                        options = {};
                    var object = {};
                    if (options.defaults) {
                        if ($util.Long) {
                            var long = new $util.Long(0, 0, false);
                            object.timestampNs = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
                        } else
                            object.timestampNs = options.longs === String ? "0" : 0;
                        object.chargeCounterUah = 0;
                        object.capacityPercent = 0;
                        object.currentUa = 0;
                        object.currentAvgUa = 0;
                    }
                    if (message.timestampNs != null && message.hasOwnProperty("timestampNs"))
                        if (typeof message.timestampNs === "number")
                            object.timestampNs = options.longs === String ? String(message.timestampNs) : message.timestampNs;
                        else
                            object.timestampNs = options.longs === String ? $util.Long.prototype.toString.call(message.timestampNs) : options.longs === Number ? new $util.LongBits(message.timestampNs.low >>> 0, message.timestampNs.high >>> 0).toNumber() : message.timestampNs;
                    if (message.chargeCounterUah != null && message.hasOwnProperty("chargeCounterUah"))
                        object.chargeCounterUah = options.json && !isFinite(message.chargeCounterUah) ? String(message.chargeCounterUah) : message.chargeCounterUah;
                    if (message.capacityPercent != null && message.hasOwnProperty("capacityPercent"))
                        object.capacityPercent = options.json && !isFinite(message.capacityPercent) ? String(message.capacityPercent) : message.capacityPercent;
                    if (message.currentUa != null && message.hasOwnProperty("currentUa"))
                        object.currentUa = options.json && !isFinite(message.currentUa) ? String(message.currentUa) : message.currentUa;
                    if (message.currentAvgUa != null && message.hasOwnProperty("currentAvgUa"))
                        object.currentAvgUa = options.json && !isFinite(message.currentAvgUa) ? String(message.currentAvgUa) : message.currentAvgUa;
                    return object;
                };

                /**
                 * Converts this BatteryCounters to JSON.
                 * @function toJSON
                 * @memberof perfetto.protos.AndroidBatteryMetric.BatteryCounters
                 * @instance
                 * @returns {Object.<string,*>} JSON object
                 */
                BatteryCounters.prototype.toJSON = function toJSON() {
                    return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
                };

                return BatteryCounters;
            })();

            AndroidBatteryMetric.BatteryAggregates = (function() {

                /**
                 * Properties of a BatteryAggregates.
                 * @memberof perfetto.protos.AndroidBatteryMetric
                 * @interface IBatteryAggregates
                 * @property {number|null} [totalScreenOffNs] BatteryAggregates totalScreenOffNs
                 * @property {number|null} [totalScreenOnNs] BatteryAggregates totalScreenOnNs
                 * @property {number|null} [totalScreenDozeNs] BatteryAggregates totalScreenDozeNs
                 * @property {number|null} [totalWakelockNs] BatteryAggregates totalWakelockNs
                 * @property {number|null} [sleepNs] BatteryAggregates sleepNs
                 * @property {number|null} [sleepScreenOffNs] BatteryAggregates sleepScreenOffNs
                 * @property {number|null} [sleepScreenOnNs] BatteryAggregates sleepScreenOnNs
                 * @property {number|null} [sleepScreenDozeNs] BatteryAggregates sleepScreenDozeNs
                 */

                /**
                 * Constructs a new BatteryAggregates.
                 * @memberof perfetto.protos.AndroidBatteryMetric
                 * @classdesc Represents a BatteryAggregates.
                 * @implements IBatteryAggregates
                 * @constructor
                 * @param {perfetto.protos.AndroidBatteryMetric.IBatteryAggregates=} [properties] Properties to set
                 */
                function BatteryAggregates(properties) {
                    if (properties)
                        for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                            if (properties[keys[i]] != null)
                                this[keys[i]] = properties[keys[i]];
                }

                /**
                 * BatteryAggregates totalScreenOffNs.
                 * @member {number} totalScreenOffNs
                 * @memberof perfetto.protos.AndroidBatteryMetric.BatteryAggregates
                 * @instance
                 */
                BatteryAggregates.prototype.totalScreenOffNs = $util.Long ? $util.Long.fromBits(0,0,false) : 0;

                /**
                 * BatteryAggregates totalScreenOnNs.
                 * @member {number} totalScreenOnNs
                 * @memberof perfetto.protos.AndroidBatteryMetric.BatteryAggregates
                 * @instance
                 */
                BatteryAggregates.prototype.totalScreenOnNs = $util.Long ? $util.Long.fromBits(0,0,false) : 0;

                /**
                 * BatteryAggregates totalScreenDozeNs.
                 * @member {number} totalScreenDozeNs
                 * @memberof perfetto.protos.AndroidBatteryMetric.BatteryAggregates
                 * @instance
                 */
                BatteryAggregates.prototype.totalScreenDozeNs = $util.Long ? $util.Long.fromBits(0,0,false) : 0;

                /**
                 * BatteryAggregates totalWakelockNs.
                 * @member {number} totalWakelockNs
                 * @memberof perfetto.protos.AndroidBatteryMetric.BatteryAggregates
                 * @instance
                 */
                BatteryAggregates.prototype.totalWakelockNs = $util.Long ? $util.Long.fromBits(0,0,false) : 0;

                /**
                 * BatteryAggregates sleepNs.
                 * @member {number} sleepNs
                 * @memberof perfetto.protos.AndroidBatteryMetric.BatteryAggregates
                 * @instance
                 */
                BatteryAggregates.prototype.sleepNs = $util.Long ? $util.Long.fromBits(0,0,false) : 0;

                /**
                 * BatteryAggregates sleepScreenOffNs.
                 * @member {number} sleepScreenOffNs
                 * @memberof perfetto.protos.AndroidBatteryMetric.BatteryAggregates
                 * @instance
                 */
                BatteryAggregates.prototype.sleepScreenOffNs = $util.Long ? $util.Long.fromBits(0,0,false) : 0;

                /**
                 * BatteryAggregates sleepScreenOnNs.
                 * @member {number} sleepScreenOnNs
                 * @memberof perfetto.protos.AndroidBatteryMetric.BatteryAggregates
                 * @instance
                 */
                BatteryAggregates.prototype.sleepScreenOnNs = $util.Long ? $util.Long.fromBits(0,0,false) : 0;

                /**
                 * BatteryAggregates sleepScreenDozeNs.
                 * @member {number} sleepScreenDozeNs
                 * @memberof perfetto.protos.AndroidBatteryMetric.BatteryAggregates
                 * @instance
                 */
                BatteryAggregates.prototype.sleepScreenDozeNs = $util.Long ? $util.Long.fromBits(0,0,false) : 0;

                /**
                 * Creates a new BatteryAggregates instance using the specified properties.
                 * @function create
                 * @memberof perfetto.protos.AndroidBatteryMetric.BatteryAggregates
                 * @static
                 * @param {perfetto.protos.AndroidBatteryMetric.IBatteryAggregates=} [properties] Properties to set
                 * @returns {perfetto.protos.AndroidBatteryMetric.BatteryAggregates} BatteryAggregates instance
                 */
                BatteryAggregates.create = function create(properties) {
                    return new BatteryAggregates(properties);
                };

                /**
                 * Encodes the specified BatteryAggregates message. Does not implicitly {@link perfetto.protos.AndroidBatteryMetric.BatteryAggregates.verify|verify} messages.
                 * @function encode
                 * @memberof perfetto.protos.AndroidBatteryMetric.BatteryAggregates
                 * @static
                 * @param {perfetto.protos.AndroidBatteryMetric.IBatteryAggregates} message BatteryAggregates message or plain object to encode
                 * @param {$protobuf.Writer} [writer] Writer to encode to
                 * @returns {$protobuf.Writer} Writer
                 */
                BatteryAggregates.encode = function encode(message, writer) {
                    if (!writer)
                        writer = $Writer.create();
                    if (message.totalScreenOffNs != null && Object.hasOwnProperty.call(message, "totalScreenOffNs"))
                        writer.uint32(/* id 1, wireType 0 =*/8).int64(message.totalScreenOffNs);
                    if (message.totalScreenOnNs != null && Object.hasOwnProperty.call(message, "totalScreenOnNs"))
                        writer.uint32(/* id 2, wireType 0 =*/16).int64(message.totalScreenOnNs);
                    if (message.totalScreenDozeNs != null && Object.hasOwnProperty.call(message, "totalScreenDozeNs"))
                        writer.uint32(/* id 3, wireType 0 =*/24).int64(message.totalScreenDozeNs);
                    if (message.totalWakelockNs != null && Object.hasOwnProperty.call(message, "totalWakelockNs"))
                        writer.uint32(/* id 4, wireType 0 =*/32).int64(message.totalWakelockNs);
                    if (message.sleepNs != null && Object.hasOwnProperty.call(message, "sleepNs"))
                        writer.uint32(/* id 5, wireType 0 =*/40).int64(message.sleepNs);
                    if (message.sleepScreenOffNs != null && Object.hasOwnProperty.call(message, "sleepScreenOffNs"))
                        writer.uint32(/* id 6, wireType 0 =*/48).int64(message.sleepScreenOffNs);
                    if (message.sleepScreenOnNs != null && Object.hasOwnProperty.call(message, "sleepScreenOnNs"))
                        writer.uint32(/* id 7, wireType 0 =*/56).int64(message.sleepScreenOnNs);
                    if (message.sleepScreenDozeNs != null && Object.hasOwnProperty.call(message, "sleepScreenDozeNs"))
                        writer.uint32(/* id 8, wireType 0 =*/64).int64(message.sleepScreenDozeNs);
                    return writer;
                };

                /**
                 * Encodes the specified BatteryAggregates message, length delimited. Does not implicitly {@link perfetto.protos.AndroidBatteryMetric.BatteryAggregates.verify|verify} messages.
                 * @function encodeDelimited
                 * @memberof perfetto.protos.AndroidBatteryMetric.BatteryAggregates
                 * @static
                 * @param {perfetto.protos.AndroidBatteryMetric.IBatteryAggregates} message BatteryAggregates message or plain object to encode
                 * @param {$protobuf.Writer} [writer] Writer to encode to
                 * @returns {$protobuf.Writer} Writer
                 */
                BatteryAggregates.encodeDelimited = function encodeDelimited(message, writer) {
                    return this.encode(message, writer).ldelim();
                };

                /**
                 * Decodes a BatteryAggregates message from the specified reader or buffer.
                 * @function decode
                 * @memberof perfetto.protos.AndroidBatteryMetric.BatteryAggregates
                 * @static
                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                 * @param {number} [length] Message length if known beforehand
                 * @returns {perfetto.protos.AndroidBatteryMetric.BatteryAggregates} BatteryAggregates
                 * @throws {Error} If the payload is not a reader or valid buffer
                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
                 */
                BatteryAggregates.decode = function decode(reader, length) {
                    if (!(reader instanceof $Reader))
                        reader = $Reader.create(reader);
                    var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.AndroidBatteryMetric.BatteryAggregates();
                    while (reader.pos < end) {
                        var tag = reader.uint32();
                        switch (tag >>> 3) {
                        case 1:
                            message.totalScreenOffNs = reader.int64();
                            break;
                        case 2:
                            message.totalScreenOnNs = reader.int64();
                            break;
                        case 3:
                            message.totalScreenDozeNs = reader.int64();
                            break;
                        case 4:
                            message.totalWakelockNs = reader.int64();
                            break;
                        case 5:
                            message.sleepNs = reader.int64();
                            break;
                        case 6:
                            message.sleepScreenOffNs = reader.int64();
                            break;
                        case 7:
                            message.sleepScreenOnNs = reader.int64();
                            break;
                        case 8:
                            message.sleepScreenDozeNs = reader.int64();
                            break;
                        default:
                            reader.skipType(tag & 7);
                            break;
                        }
                    }
                    return message;
                };

                /**
                 * Decodes a BatteryAggregates message from the specified reader or buffer, length delimited.
                 * @function decodeDelimited
                 * @memberof perfetto.protos.AndroidBatteryMetric.BatteryAggregates
                 * @static
                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                 * @returns {perfetto.protos.AndroidBatteryMetric.BatteryAggregates} BatteryAggregates
                 * @throws {Error} If the payload is not a reader or valid buffer
                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
                 */
                BatteryAggregates.decodeDelimited = function decodeDelimited(reader) {
                    if (!(reader instanceof $Reader))
                        reader = new $Reader(reader);
                    return this.decode(reader, reader.uint32());
                };

                /**
                 * Verifies a BatteryAggregates message.
                 * @function verify
                 * @memberof perfetto.protos.AndroidBatteryMetric.BatteryAggregates
                 * @static
                 * @param {Object.<string,*>} message Plain object to verify
                 * @returns {string|null} `null` if valid, otherwise the reason why it is not
                 */
                BatteryAggregates.verify = function verify(message) {
                    if (typeof message !== "object" || message === null)
                        return "object expected";
                    if (message.totalScreenOffNs != null && message.hasOwnProperty("totalScreenOffNs"))
                        if (!$util.isInteger(message.totalScreenOffNs) && !(message.totalScreenOffNs && $util.isInteger(message.totalScreenOffNs.low) && $util.isInteger(message.totalScreenOffNs.high)))
                            return "totalScreenOffNs: integer|Long expected";
                    if (message.totalScreenOnNs != null && message.hasOwnProperty("totalScreenOnNs"))
                        if (!$util.isInteger(message.totalScreenOnNs) && !(message.totalScreenOnNs && $util.isInteger(message.totalScreenOnNs.low) && $util.isInteger(message.totalScreenOnNs.high)))
                            return "totalScreenOnNs: integer|Long expected";
                    if (message.totalScreenDozeNs != null && message.hasOwnProperty("totalScreenDozeNs"))
                        if (!$util.isInteger(message.totalScreenDozeNs) && !(message.totalScreenDozeNs && $util.isInteger(message.totalScreenDozeNs.low) && $util.isInteger(message.totalScreenDozeNs.high)))
                            return "totalScreenDozeNs: integer|Long expected";
                    if (message.totalWakelockNs != null && message.hasOwnProperty("totalWakelockNs"))
                        if (!$util.isInteger(message.totalWakelockNs) && !(message.totalWakelockNs && $util.isInteger(message.totalWakelockNs.low) && $util.isInteger(message.totalWakelockNs.high)))
                            return "totalWakelockNs: integer|Long expected";
                    if (message.sleepNs != null && message.hasOwnProperty("sleepNs"))
                        if (!$util.isInteger(message.sleepNs) && !(message.sleepNs && $util.isInteger(message.sleepNs.low) && $util.isInteger(message.sleepNs.high)))
                            return "sleepNs: integer|Long expected";
                    if (message.sleepScreenOffNs != null && message.hasOwnProperty("sleepScreenOffNs"))
                        if (!$util.isInteger(message.sleepScreenOffNs) && !(message.sleepScreenOffNs && $util.isInteger(message.sleepScreenOffNs.low) && $util.isInteger(message.sleepScreenOffNs.high)))
                            return "sleepScreenOffNs: integer|Long expected";
                    if (message.sleepScreenOnNs != null && message.hasOwnProperty("sleepScreenOnNs"))
                        if (!$util.isInteger(message.sleepScreenOnNs) && !(message.sleepScreenOnNs && $util.isInteger(message.sleepScreenOnNs.low) && $util.isInteger(message.sleepScreenOnNs.high)))
                            return "sleepScreenOnNs: integer|Long expected";
                    if (message.sleepScreenDozeNs != null && message.hasOwnProperty("sleepScreenDozeNs"))
                        if (!$util.isInteger(message.sleepScreenDozeNs) && !(message.sleepScreenDozeNs && $util.isInteger(message.sleepScreenDozeNs.low) && $util.isInteger(message.sleepScreenDozeNs.high)))
                            return "sleepScreenDozeNs: integer|Long expected";
                    return null;
                };

                /**
                 * Creates a BatteryAggregates message from a plain object. Also converts values to their respective internal types.
                 * @function fromObject
                 * @memberof perfetto.protos.AndroidBatteryMetric.BatteryAggregates
                 * @static
                 * @param {Object.<string,*>} object Plain object
                 * @returns {perfetto.protos.AndroidBatteryMetric.BatteryAggregates} BatteryAggregates
                 */
                BatteryAggregates.fromObject = function fromObject(object) {
                    if (object instanceof $root.perfetto.protos.AndroidBatteryMetric.BatteryAggregates)
                        return object;
                    var message = new $root.perfetto.protos.AndroidBatteryMetric.BatteryAggregates();
                    if (object.totalScreenOffNs != null)
                        if ($util.Long)
                            (message.totalScreenOffNs = $util.Long.fromValue(object.totalScreenOffNs)).unsigned = false;
                        else if (typeof object.totalScreenOffNs === "string")
                            message.totalScreenOffNs = parseInt(object.totalScreenOffNs, 10);
                        else if (typeof object.totalScreenOffNs === "number")
                            message.totalScreenOffNs = object.totalScreenOffNs;
                        else if (typeof object.totalScreenOffNs === "object")
                            message.totalScreenOffNs = new $util.LongBits(object.totalScreenOffNs.low >>> 0, object.totalScreenOffNs.high >>> 0).toNumber();
                    if (object.totalScreenOnNs != null)
                        if ($util.Long)
                            (message.totalScreenOnNs = $util.Long.fromValue(object.totalScreenOnNs)).unsigned = false;
                        else if (typeof object.totalScreenOnNs === "string")
                            message.totalScreenOnNs = parseInt(object.totalScreenOnNs, 10);
                        else if (typeof object.totalScreenOnNs === "number")
                            message.totalScreenOnNs = object.totalScreenOnNs;
                        else if (typeof object.totalScreenOnNs === "object")
                            message.totalScreenOnNs = new $util.LongBits(object.totalScreenOnNs.low >>> 0, object.totalScreenOnNs.high >>> 0).toNumber();
                    if (object.totalScreenDozeNs != null)
                        if ($util.Long)
                            (message.totalScreenDozeNs = $util.Long.fromValue(object.totalScreenDozeNs)).unsigned = false;
                        else if (typeof object.totalScreenDozeNs === "string")
                            message.totalScreenDozeNs = parseInt(object.totalScreenDozeNs, 10);
                        else if (typeof object.totalScreenDozeNs === "number")
                            message.totalScreenDozeNs = object.totalScreenDozeNs;
                        else if (typeof object.totalScreenDozeNs === "object")
                            message.totalScreenDozeNs = new $util.LongBits(object.totalScreenDozeNs.low >>> 0, object.totalScreenDozeNs.high >>> 0).toNumber();
                    if (object.totalWakelockNs != null)
                        if ($util.Long)
                            (message.totalWakelockNs = $util.Long.fromValue(object.totalWakelockNs)).unsigned = false;
                        else if (typeof object.totalWakelockNs === "string")
                            message.totalWakelockNs = parseInt(object.totalWakelockNs, 10);
                        else if (typeof object.totalWakelockNs === "number")
                            message.totalWakelockNs = object.totalWakelockNs;
                        else if (typeof object.totalWakelockNs === "object")
                            message.totalWakelockNs = new $util.LongBits(object.totalWakelockNs.low >>> 0, object.totalWakelockNs.high >>> 0).toNumber();
                    if (object.sleepNs != null)
                        if ($util.Long)
                            (message.sleepNs = $util.Long.fromValue(object.sleepNs)).unsigned = false;
                        else if (typeof object.sleepNs === "string")
                            message.sleepNs = parseInt(object.sleepNs, 10);
                        else if (typeof object.sleepNs === "number")
                            message.sleepNs = object.sleepNs;
                        else if (typeof object.sleepNs === "object")
                            message.sleepNs = new $util.LongBits(object.sleepNs.low >>> 0, object.sleepNs.high >>> 0).toNumber();
                    if (object.sleepScreenOffNs != null)
                        if ($util.Long)
                            (message.sleepScreenOffNs = $util.Long.fromValue(object.sleepScreenOffNs)).unsigned = false;
                        else if (typeof object.sleepScreenOffNs === "string")
                            message.sleepScreenOffNs = parseInt(object.sleepScreenOffNs, 10);
                        else if (typeof object.sleepScreenOffNs === "number")
                            message.sleepScreenOffNs = object.sleepScreenOffNs;
                        else if (typeof object.sleepScreenOffNs === "object")
                            message.sleepScreenOffNs = new $util.LongBits(object.sleepScreenOffNs.low >>> 0, object.sleepScreenOffNs.high >>> 0).toNumber();
                    if (object.sleepScreenOnNs != null)
                        if ($util.Long)
                            (message.sleepScreenOnNs = $util.Long.fromValue(object.sleepScreenOnNs)).unsigned = false;
                        else if (typeof object.sleepScreenOnNs === "string")
                            message.sleepScreenOnNs = parseInt(object.sleepScreenOnNs, 10);
                        else if (typeof object.sleepScreenOnNs === "number")
                            message.sleepScreenOnNs = object.sleepScreenOnNs;
                        else if (typeof object.sleepScreenOnNs === "object")
                            message.sleepScreenOnNs = new $util.LongBits(object.sleepScreenOnNs.low >>> 0, object.sleepScreenOnNs.high >>> 0).toNumber();
                    if (object.sleepScreenDozeNs != null)
                        if ($util.Long)
                            (message.sleepScreenDozeNs = $util.Long.fromValue(object.sleepScreenDozeNs)).unsigned = false;
                        else if (typeof object.sleepScreenDozeNs === "string")
                            message.sleepScreenDozeNs = parseInt(object.sleepScreenDozeNs, 10);
                        else if (typeof object.sleepScreenDozeNs === "number")
                            message.sleepScreenDozeNs = object.sleepScreenDozeNs;
                        else if (typeof object.sleepScreenDozeNs === "object")
                            message.sleepScreenDozeNs = new $util.LongBits(object.sleepScreenDozeNs.low >>> 0, object.sleepScreenDozeNs.high >>> 0).toNumber();
                    return message;
                };

                /**
                 * Creates a plain object from a BatteryAggregates message. Also converts values to other types if specified.
                 * @function toObject
                 * @memberof perfetto.protos.AndroidBatteryMetric.BatteryAggregates
                 * @static
                 * @param {perfetto.protos.AndroidBatteryMetric.BatteryAggregates} message BatteryAggregates
                 * @param {$protobuf.IConversionOptions} [options] Conversion options
                 * @returns {Object.<string,*>} Plain object
                 */
                BatteryAggregates.toObject = function toObject(message, options) {
                    if (!options)
                        options = {};
                    var object = {};
                    if (options.defaults) {
                        if ($util.Long) {
                            var long = new $util.Long(0, 0, false);
                            object.totalScreenOffNs = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
                        } else
                            object.totalScreenOffNs = options.longs === String ? "0" : 0;
                        if ($util.Long) {
                            var long = new $util.Long(0, 0, false);
                            object.totalScreenOnNs = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
                        } else
                            object.totalScreenOnNs = options.longs === String ? "0" : 0;
                        if ($util.Long) {
                            var long = new $util.Long(0, 0, false);
                            object.totalScreenDozeNs = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
                        } else
                            object.totalScreenDozeNs = options.longs === String ? "0" : 0;
                        if ($util.Long) {
                            var long = new $util.Long(0, 0, false);
                            object.totalWakelockNs = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
                        } else
                            object.totalWakelockNs = options.longs === String ? "0" : 0;
                        if ($util.Long) {
                            var long = new $util.Long(0, 0, false);
                            object.sleepNs = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
                        } else
                            object.sleepNs = options.longs === String ? "0" : 0;
                        if ($util.Long) {
                            var long = new $util.Long(0, 0, false);
                            object.sleepScreenOffNs = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
                        } else
                            object.sleepScreenOffNs = options.longs === String ? "0" : 0;
                        if ($util.Long) {
                            var long = new $util.Long(0, 0, false);
                            object.sleepScreenOnNs = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
                        } else
                            object.sleepScreenOnNs = options.longs === String ? "0" : 0;
                        if ($util.Long) {
                            var long = new $util.Long(0, 0, false);
                            object.sleepScreenDozeNs = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
                        } else
                            object.sleepScreenDozeNs = options.longs === String ? "0" : 0;
                    }
                    if (message.totalScreenOffNs != null && message.hasOwnProperty("totalScreenOffNs"))
                        if (typeof message.totalScreenOffNs === "number")
                            object.totalScreenOffNs = options.longs === String ? String(message.totalScreenOffNs) : message.totalScreenOffNs;
                        else
                            object.totalScreenOffNs = options.longs === String ? $util.Long.prototype.toString.call(message.totalScreenOffNs) : options.longs === Number ? new $util.LongBits(message.totalScreenOffNs.low >>> 0, message.totalScreenOffNs.high >>> 0).toNumber() : message.totalScreenOffNs;
                    if (message.totalScreenOnNs != null && message.hasOwnProperty("totalScreenOnNs"))
                        if (typeof message.totalScreenOnNs === "number")
                            object.totalScreenOnNs = options.longs === String ? String(message.totalScreenOnNs) : message.totalScreenOnNs;
                        else
                            object.totalScreenOnNs = options.longs === String ? $util.Long.prototype.toString.call(message.totalScreenOnNs) : options.longs === Number ? new $util.LongBits(message.totalScreenOnNs.low >>> 0, message.totalScreenOnNs.high >>> 0).toNumber() : message.totalScreenOnNs;
                    if (message.totalScreenDozeNs != null && message.hasOwnProperty("totalScreenDozeNs"))
                        if (typeof message.totalScreenDozeNs === "number")
                            object.totalScreenDozeNs = options.longs === String ? String(message.totalScreenDozeNs) : message.totalScreenDozeNs;
                        else
                            object.totalScreenDozeNs = options.longs === String ? $util.Long.prototype.toString.call(message.totalScreenDozeNs) : options.longs === Number ? new $util.LongBits(message.totalScreenDozeNs.low >>> 0, message.totalScreenDozeNs.high >>> 0).toNumber() : message.totalScreenDozeNs;
                    if (message.totalWakelockNs != null && message.hasOwnProperty("totalWakelockNs"))
                        if (typeof message.totalWakelockNs === "number")
                            object.totalWakelockNs = options.longs === String ? String(message.totalWakelockNs) : message.totalWakelockNs;
                        else
                            object.totalWakelockNs = options.longs === String ? $util.Long.prototype.toString.call(message.totalWakelockNs) : options.longs === Number ? new $util.LongBits(message.totalWakelockNs.low >>> 0, message.totalWakelockNs.high >>> 0).toNumber() : message.totalWakelockNs;
                    if (message.sleepNs != null && message.hasOwnProperty("sleepNs"))
                        if (typeof message.sleepNs === "number")
                            object.sleepNs = options.longs === String ? String(message.sleepNs) : message.sleepNs;
                        else
                            object.sleepNs = options.longs === String ? $util.Long.prototype.toString.call(message.sleepNs) : options.longs === Number ? new $util.LongBits(message.sleepNs.low >>> 0, message.sleepNs.high >>> 0).toNumber() : message.sleepNs;
                    if (message.sleepScreenOffNs != null && message.hasOwnProperty("sleepScreenOffNs"))
                        if (typeof message.sleepScreenOffNs === "number")
                            object.sleepScreenOffNs = options.longs === String ? String(message.sleepScreenOffNs) : message.sleepScreenOffNs;
                        else
                            object.sleepScreenOffNs = options.longs === String ? $util.Long.prototype.toString.call(message.sleepScreenOffNs) : options.longs === Number ? new $util.LongBits(message.sleepScreenOffNs.low >>> 0, message.sleepScreenOffNs.high >>> 0).toNumber() : message.sleepScreenOffNs;
                    if (message.sleepScreenOnNs != null && message.hasOwnProperty("sleepScreenOnNs"))
                        if (typeof message.sleepScreenOnNs === "number")
                            object.sleepScreenOnNs = options.longs === String ? String(message.sleepScreenOnNs) : message.sleepScreenOnNs;
                        else
                            object.sleepScreenOnNs = options.longs === String ? $util.Long.prototype.toString.call(message.sleepScreenOnNs) : options.longs === Number ? new $util.LongBits(message.sleepScreenOnNs.low >>> 0, message.sleepScreenOnNs.high >>> 0).toNumber() : message.sleepScreenOnNs;
                    if (message.sleepScreenDozeNs != null && message.hasOwnProperty("sleepScreenDozeNs"))
                        if (typeof message.sleepScreenDozeNs === "number")
                            object.sleepScreenDozeNs = options.longs === String ? String(message.sleepScreenDozeNs) : message.sleepScreenDozeNs;
                        else
                            object.sleepScreenDozeNs = options.longs === String ? $util.Long.prototype.toString.call(message.sleepScreenDozeNs) : options.longs === Number ? new $util.LongBits(message.sleepScreenDozeNs.low >>> 0, message.sleepScreenDozeNs.high >>> 0).toNumber() : message.sleepScreenDozeNs;
                    return object;
                };

                /**
                 * Converts this BatteryAggregates to JSON.
                 * @function toJSON
                 * @memberof perfetto.protos.AndroidBatteryMetric.BatteryAggregates
                 * @instance
                 * @returns {Object.<string,*>} JSON object
                 */
                BatteryAggregates.prototype.toJSON = function toJSON() {
                    return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
                };

                return BatteryAggregates;
            })();

            AndroidBatteryMetric.SuspendPeriod = (function() {

                /**
                 * Properties of a SuspendPeriod.
                 * @memberof perfetto.protos.AndroidBatteryMetric
                 * @interface ISuspendPeriod
                 * @property {number|null} [timestampNs] SuspendPeriod timestampNs
                 * @property {number|null} [durationNs] SuspendPeriod durationNs
                 */

                /**
                 * Constructs a new SuspendPeriod.
                 * @memberof perfetto.protos.AndroidBatteryMetric
                 * @classdesc Represents a SuspendPeriod.
                 * @implements ISuspendPeriod
                 * @constructor
                 * @param {perfetto.protos.AndroidBatteryMetric.ISuspendPeriod=} [properties] Properties to set
                 */
                function SuspendPeriod(properties) {
                    if (properties)
                        for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                            if (properties[keys[i]] != null)
                                this[keys[i]] = properties[keys[i]];
                }

                /**
                 * SuspendPeriod timestampNs.
                 * @member {number} timestampNs
                 * @memberof perfetto.protos.AndroidBatteryMetric.SuspendPeriod
                 * @instance
                 */
                SuspendPeriod.prototype.timestampNs = $util.Long ? $util.Long.fromBits(0,0,false) : 0;

                /**
                 * SuspendPeriod durationNs.
                 * @member {number} durationNs
                 * @memberof perfetto.protos.AndroidBatteryMetric.SuspendPeriod
                 * @instance
                 */
                SuspendPeriod.prototype.durationNs = $util.Long ? $util.Long.fromBits(0,0,false) : 0;

                /**
                 * Creates a new SuspendPeriod instance using the specified properties.
                 * @function create
                 * @memberof perfetto.protos.AndroidBatteryMetric.SuspendPeriod
                 * @static
                 * @param {perfetto.protos.AndroidBatteryMetric.ISuspendPeriod=} [properties] Properties to set
                 * @returns {perfetto.protos.AndroidBatteryMetric.SuspendPeriod} SuspendPeriod instance
                 */
                SuspendPeriod.create = function create(properties) {
                    return new SuspendPeriod(properties);
                };

                /**
                 * Encodes the specified SuspendPeriod message. Does not implicitly {@link perfetto.protos.AndroidBatteryMetric.SuspendPeriod.verify|verify} messages.
                 * @function encode
                 * @memberof perfetto.protos.AndroidBatteryMetric.SuspendPeriod
                 * @static
                 * @param {perfetto.protos.AndroidBatteryMetric.ISuspendPeriod} message SuspendPeriod message or plain object to encode
                 * @param {$protobuf.Writer} [writer] Writer to encode to
                 * @returns {$protobuf.Writer} Writer
                 */
                SuspendPeriod.encode = function encode(message, writer) {
                    if (!writer)
                        writer = $Writer.create();
                    if (message.timestampNs != null && Object.hasOwnProperty.call(message, "timestampNs"))
                        writer.uint32(/* id 1, wireType 0 =*/8).int64(message.timestampNs);
                    if (message.durationNs != null && Object.hasOwnProperty.call(message, "durationNs"))
                        writer.uint32(/* id 2, wireType 0 =*/16).int64(message.durationNs);
                    return writer;
                };

                /**
                 * Encodes the specified SuspendPeriod message, length delimited. Does not implicitly {@link perfetto.protos.AndroidBatteryMetric.SuspendPeriod.verify|verify} messages.
                 * @function encodeDelimited
                 * @memberof perfetto.protos.AndroidBatteryMetric.SuspendPeriod
                 * @static
                 * @param {perfetto.protos.AndroidBatteryMetric.ISuspendPeriod} message SuspendPeriod message or plain object to encode
                 * @param {$protobuf.Writer} [writer] Writer to encode to
                 * @returns {$protobuf.Writer} Writer
                 */
                SuspendPeriod.encodeDelimited = function encodeDelimited(message, writer) {
                    return this.encode(message, writer).ldelim();
                };

                /**
                 * Decodes a SuspendPeriod message from the specified reader or buffer.
                 * @function decode
                 * @memberof perfetto.protos.AndroidBatteryMetric.SuspendPeriod
                 * @static
                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                 * @param {number} [length] Message length if known beforehand
                 * @returns {perfetto.protos.AndroidBatteryMetric.SuspendPeriod} SuspendPeriod
                 * @throws {Error} If the payload is not a reader or valid buffer
                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
                 */
                SuspendPeriod.decode = function decode(reader, length) {
                    if (!(reader instanceof $Reader))
                        reader = $Reader.create(reader);
                    var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.AndroidBatteryMetric.SuspendPeriod();
                    while (reader.pos < end) {
                        var tag = reader.uint32();
                        switch (tag >>> 3) {
                        case 1:
                            message.timestampNs = reader.int64();
                            break;
                        case 2:
                            message.durationNs = reader.int64();
                            break;
                        default:
                            reader.skipType(tag & 7);
                            break;
                        }
                    }
                    return message;
                };

                /**
                 * Decodes a SuspendPeriod message from the specified reader or buffer, length delimited.
                 * @function decodeDelimited
                 * @memberof perfetto.protos.AndroidBatteryMetric.SuspendPeriod
                 * @static
                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                 * @returns {perfetto.protos.AndroidBatteryMetric.SuspendPeriod} SuspendPeriod
                 * @throws {Error} If the payload is not a reader or valid buffer
                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
                 */
                SuspendPeriod.decodeDelimited = function decodeDelimited(reader) {
                    if (!(reader instanceof $Reader))
                        reader = new $Reader(reader);
                    return this.decode(reader, reader.uint32());
                };

                /**
                 * Verifies a SuspendPeriod message.
                 * @function verify
                 * @memberof perfetto.protos.AndroidBatteryMetric.SuspendPeriod
                 * @static
                 * @param {Object.<string,*>} message Plain object to verify
                 * @returns {string|null} `null` if valid, otherwise the reason why it is not
                 */
                SuspendPeriod.verify = function verify(message) {
                    if (typeof message !== "object" || message === null)
                        return "object expected";
                    if (message.timestampNs != null && message.hasOwnProperty("timestampNs"))
                        if (!$util.isInteger(message.timestampNs) && !(message.timestampNs && $util.isInteger(message.timestampNs.low) && $util.isInteger(message.timestampNs.high)))
                            return "timestampNs: integer|Long expected";
                    if (message.durationNs != null && message.hasOwnProperty("durationNs"))
                        if (!$util.isInteger(message.durationNs) && !(message.durationNs && $util.isInteger(message.durationNs.low) && $util.isInteger(message.durationNs.high)))
                            return "durationNs: integer|Long expected";
                    return null;
                };

                /**
                 * Creates a SuspendPeriod message from a plain object. Also converts values to their respective internal types.
                 * @function fromObject
                 * @memberof perfetto.protos.AndroidBatteryMetric.SuspendPeriod
                 * @static
                 * @param {Object.<string,*>} object Plain object
                 * @returns {perfetto.protos.AndroidBatteryMetric.SuspendPeriod} SuspendPeriod
                 */
                SuspendPeriod.fromObject = function fromObject(object) {
                    if (object instanceof $root.perfetto.protos.AndroidBatteryMetric.SuspendPeriod)
                        return object;
                    var message = new $root.perfetto.protos.AndroidBatteryMetric.SuspendPeriod();
                    if (object.timestampNs != null)
                        if ($util.Long)
                            (message.timestampNs = $util.Long.fromValue(object.timestampNs)).unsigned = false;
                        else if (typeof object.timestampNs === "string")
                            message.timestampNs = parseInt(object.timestampNs, 10);
                        else if (typeof object.timestampNs === "number")
                            message.timestampNs = object.timestampNs;
                        else if (typeof object.timestampNs === "object")
                            message.timestampNs = new $util.LongBits(object.timestampNs.low >>> 0, object.timestampNs.high >>> 0).toNumber();
                    if (object.durationNs != null)
                        if ($util.Long)
                            (message.durationNs = $util.Long.fromValue(object.durationNs)).unsigned = false;
                        else if (typeof object.durationNs === "string")
                            message.durationNs = parseInt(object.durationNs, 10);
                        else if (typeof object.durationNs === "number")
                            message.durationNs = object.durationNs;
                        else if (typeof object.durationNs === "object")
                            message.durationNs = new $util.LongBits(object.durationNs.low >>> 0, object.durationNs.high >>> 0).toNumber();
                    return message;
                };

                /**
                 * Creates a plain object from a SuspendPeriod message. Also converts values to other types if specified.
                 * @function toObject
                 * @memberof perfetto.protos.AndroidBatteryMetric.SuspendPeriod
                 * @static
                 * @param {perfetto.protos.AndroidBatteryMetric.SuspendPeriod} message SuspendPeriod
                 * @param {$protobuf.IConversionOptions} [options] Conversion options
                 * @returns {Object.<string,*>} Plain object
                 */
                SuspendPeriod.toObject = function toObject(message, options) {
                    if (!options)
                        options = {};
                    var object = {};
                    if (options.defaults) {
                        if ($util.Long) {
                            var long = new $util.Long(0, 0, false);
                            object.timestampNs = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
                        } else
                            object.timestampNs = options.longs === String ? "0" : 0;
                        if ($util.Long) {
                            var long = new $util.Long(0, 0, false);
                            object.durationNs = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
                        } else
                            object.durationNs = options.longs === String ? "0" : 0;
                    }
                    if (message.timestampNs != null && message.hasOwnProperty("timestampNs"))
                        if (typeof message.timestampNs === "number")
                            object.timestampNs = options.longs === String ? String(message.timestampNs) : message.timestampNs;
                        else
                            object.timestampNs = options.longs === String ? $util.Long.prototype.toString.call(message.timestampNs) : options.longs === Number ? new $util.LongBits(message.timestampNs.low >>> 0, message.timestampNs.high >>> 0).toNumber() : message.timestampNs;
                    if (message.durationNs != null && message.hasOwnProperty("durationNs"))
                        if (typeof message.durationNs === "number")
                            object.durationNs = options.longs === String ? String(message.durationNs) : message.durationNs;
                        else
                            object.durationNs = options.longs === String ? $util.Long.prototype.toString.call(message.durationNs) : options.longs === Number ? new $util.LongBits(message.durationNs.low >>> 0, message.durationNs.high >>> 0).toNumber() : message.durationNs;
                    return object;
                };

                /**
                 * Converts this SuspendPeriod to JSON.
                 * @function toJSON
                 * @memberof perfetto.protos.AndroidBatteryMetric.SuspendPeriod
                 * @instance
                 * @returns {Object.<string,*>} JSON object
                 */
                SuspendPeriod.prototype.toJSON = function toJSON() {
                    return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
                };

                return SuspendPeriod;
            })();

            return AndroidBatteryMetric;
        })();

        protos.AndroidCpuMetric = (function() {

            /**
             * Properties of an AndroidCpuMetric.
             * @memberof perfetto.protos
             * @interface IAndroidCpuMetric
             * @property {Array.<perfetto.protos.AndroidCpuMetric.IProcess>|null} [processInfo] AndroidCpuMetric processInfo
             */

            /**
             * Constructs a new AndroidCpuMetric.
             * @memberof perfetto.protos
             * @classdesc Represents an AndroidCpuMetric.
             * @implements IAndroidCpuMetric
             * @constructor
             * @param {perfetto.protos.IAndroidCpuMetric=} [properties] Properties to set
             */
            function AndroidCpuMetric(properties) {
                this.processInfo = [];
                if (properties)
                    for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                        if (properties[keys[i]] != null)
                            this[keys[i]] = properties[keys[i]];
            }

            /**
             * AndroidCpuMetric processInfo.
             * @member {Array.<perfetto.protos.AndroidCpuMetric.IProcess>} processInfo
             * @memberof perfetto.protos.AndroidCpuMetric
             * @instance
             */
            AndroidCpuMetric.prototype.processInfo = $util.emptyArray;

            /**
             * Creates a new AndroidCpuMetric instance using the specified properties.
             * @function create
             * @memberof perfetto.protos.AndroidCpuMetric
             * @static
             * @param {perfetto.protos.IAndroidCpuMetric=} [properties] Properties to set
             * @returns {perfetto.protos.AndroidCpuMetric} AndroidCpuMetric instance
             */
            AndroidCpuMetric.create = function create(properties) {
                return new AndroidCpuMetric(properties);
            };

            /**
             * Encodes the specified AndroidCpuMetric message. Does not implicitly {@link perfetto.protos.AndroidCpuMetric.verify|verify} messages.
             * @function encode
             * @memberof perfetto.protos.AndroidCpuMetric
             * @static
             * @param {perfetto.protos.IAndroidCpuMetric} message AndroidCpuMetric message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            AndroidCpuMetric.encode = function encode(message, writer) {
                if (!writer)
                    writer = $Writer.create();
                if (message.processInfo != null && message.processInfo.length)
                    for (var i = 0; i < message.processInfo.length; ++i)
                        $root.perfetto.protos.AndroidCpuMetric.Process.encode(message.processInfo[i], writer.uint32(/* id 1, wireType 2 =*/10).fork()).ldelim();
                return writer;
            };

            /**
             * Encodes the specified AndroidCpuMetric message, length delimited. Does not implicitly {@link perfetto.protos.AndroidCpuMetric.verify|verify} messages.
             * @function encodeDelimited
             * @memberof perfetto.protos.AndroidCpuMetric
             * @static
             * @param {perfetto.protos.IAndroidCpuMetric} message AndroidCpuMetric message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            AndroidCpuMetric.encodeDelimited = function encodeDelimited(message, writer) {
                return this.encode(message, writer).ldelim();
            };

            /**
             * Decodes an AndroidCpuMetric message from the specified reader or buffer.
             * @function decode
             * @memberof perfetto.protos.AndroidCpuMetric
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @param {number} [length] Message length if known beforehand
             * @returns {perfetto.protos.AndroidCpuMetric} AndroidCpuMetric
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            AndroidCpuMetric.decode = function decode(reader, length) {
                if (!(reader instanceof $Reader))
                    reader = $Reader.create(reader);
                var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.AndroidCpuMetric();
                while (reader.pos < end) {
                    var tag = reader.uint32();
                    switch (tag >>> 3) {
                    case 1:
                        if (!(message.processInfo && message.processInfo.length))
                            message.processInfo = [];
                        message.processInfo.push($root.perfetto.protos.AndroidCpuMetric.Process.decode(reader, reader.uint32()));
                        break;
                    default:
                        reader.skipType(tag & 7);
                        break;
                    }
                }
                return message;
            };

            /**
             * Decodes an AndroidCpuMetric message from the specified reader or buffer, length delimited.
             * @function decodeDelimited
             * @memberof perfetto.protos.AndroidCpuMetric
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @returns {perfetto.protos.AndroidCpuMetric} AndroidCpuMetric
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            AndroidCpuMetric.decodeDelimited = function decodeDelimited(reader) {
                if (!(reader instanceof $Reader))
                    reader = new $Reader(reader);
                return this.decode(reader, reader.uint32());
            };

            /**
             * Verifies an AndroidCpuMetric message.
             * @function verify
             * @memberof perfetto.protos.AndroidCpuMetric
             * @static
             * @param {Object.<string,*>} message Plain object to verify
             * @returns {string|null} `null` if valid, otherwise the reason why it is not
             */
            AndroidCpuMetric.verify = function verify(message) {
                if (typeof message !== "object" || message === null)
                    return "object expected";
                if (message.processInfo != null && message.hasOwnProperty("processInfo")) {
                    if (!Array.isArray(message.processInfo))
                        return "processInfo: array expected";
                    for (var i = 0; i < message.processInfo.length; ++i) {
                        var error = $root.perfetto.protos.AndroidCpuMetric.Process.verify(message.processInfo[i]);
                        if (error)
                            return "processInfo." + error;
                    }
                }
                return null;
            };

            /**
             * Creates an AndroidCpuMetric message from a plain object. Also converts values to their respective internal types.
             * @function fromObject
             * @memberof perfetto.protos.AndroidCpuMetric
             * @static
             * @param {Object.<string,*>} object Plain object
             * @returns {perfetto.protos.AndroidCpuMetric} AndroidCpuMetric
             */
            AndroidCpuMetric.fromObject = function fromObject(object) {
                if (object instanceof $root.perfetto.protos.AndroidCpuMetric)
                    return object;
                var message = new $root.perfetto.protos.AndroidCpuMetric();
                if (object.processInfo) {
                    if (!Array.isArray(object.processInfo))
                        throw TypeError(".perfetto.protos.AndroidCpuMetric.processInfo: array expected");
                    message.processInfo = [];
                    for (var i = 0; i < object.processInfo.length; ++i) {
                        if (typeof object.processInfo[i] !== "object")
                            throw TypeError(".perfetto.protos.AndroidCpuMetric.processInfo: object expected");
                        message.processInfo[i] = $root.perfetto.protos.AndroidCpuMetric.Process.fromObject(object.processInfo[i]);
                    }
                }
                return message;
            };

            /**
             * Creates a plain object from an AndroidCpuMetric message. Also converts values to other types if specified.
             * @function toObject
             * @memberof perfetto.protos.AndroidCpuMetric
             * @static
             * @param {perfetto.protos.AndroidCpuMetric} message AndroidCpuMetric
             * @param {$protobuf.IConversionOptions} [options] Conversion options
             * @returns {Object.<string,*>} Plain object
             */
            AndroidCpuMetric.toObject = function toObject(message, options) {
                if (!options)
                    options = {};
                var object = {};
                if (options.arrays || options.defaults)
                    object.processInfo = [];
                if (message.processInfo && message.processInfo.length) {
                    object.processInfo = [];
                    for (var j = 0; j < message.processInfo.length; ++j)
                        object.processInfo[j] = $root.perfetto.protos.AndroidCpuMetric.Process.toObject(message.processInfo[j], options);
                }
                return object;
            };

            /**
             * Converts this AndroidCpuMetric to JSON.
             * @function toJSON
             * @memberof perfetto.protos.AndroidCpuMetric
             * @instance
             * @returns {Object.<string,*>} JSON object
             */
            AndroidCpuMetric.prototype.toJSON = function toJSON() {
                return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
            };

            AndroidCpuMetric.Metrics = (function() {

                /**
                 * Properties of a Metrics.
                 * @memberof perfetto.protos.AndroidCpuMetric
                 * @interface IMetrics
                 * @property {number|null} [mcycles] Metrics mcycles
                 * @property {number|null} [runtimeNs] Metrics runtimeNs
                 * @property {number|null} [minFreqKhz] Metrics minFreqKhz
                 * @property {number|null} [maxFreqKhz] Metrics maxFreqKhz
                 * @property {number|null} [avgFreqKhz] Metrics avgFreqKhz
                 */

                /**
                 * Constructs a new Metrics.
                 * @memberof perfetto.protos.AndroidCpuMetric
                 * @classdesc Represents a Metrics.
                 * @implements IMetrics
                 * @constructor
                 * @param {perfetto.protos.AndroidCpuMetric.IMetrics=} [properties] Properties to set
                 */
                function Metrics(properties) {
                    if (properties)
                        for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                            if (properties[keys[i]] != null)
                                this[keys[i]] = properties[keys[i]];
                }

                /**
                 * Metrics mcycles.
                 * @member {number} mcycles
                 * @memberof perfetto.protos.AndroidCpuMetric.Metrics
                 * @instance
                 */
                Metrics.prototype.mcycles = $util.Long ? $util.Long.fromBits(0,0,false) : 0;

                /**
                 * Metrics runtimeNs.
                 * @member {number} runtimeNs
                 * @memberof perfetto.protos.AndroidCpuMetric.Metrics
                 * @instance
                 */
                Metrics.prototype.runtimeNs = $util.Long ? $util.Long.fromBits(0,0,false) : 0;

                /**
                 * Metrics minFreqKhz.
                 * @member {number} minFreqKhz
                 * @memberof perfetto.protos.AndroidCpuMetric.Metrics
                 * @instance
                 */
                Metrics.prototype.minFreqKhz = $util.Long ? $util.Long.fromBits(0,0,false) : 0;

                /**
                 * Metrics maxFreqKhz.
                 * @member {number} maxFreqKhz
                 * @memberof perfetto.protos.AndroidCpuMetric.Metrics
                 * @instance
                 */
                Metrics.prototype.maxFreqKhz = $util.Long ? $util.Long.fromBits(0,0,false) : 0;

                /**
                 * Metrics avgFreqKhz.
                 * @member {number} avgFreqKhz
                 * @memberof perfetto.protos.AndroidCpuMetric.Metrics
                 * @instance
                 */
                Metrics.prototype.avgFreqKhz = $util.Long ? $util.Long.fromBits(0,0,false) : 0;

                /**
                 * Creates a new Metrics instance using the specified properties.
                 * @function create
                 * @memberof perfetto.protos.AndroidCpuMetric.Metrics
                 * @static
                 * @param {perfetto.protos.AndroidCpuMetric.IMetrics=} [properties] Properties to set
                 * @returns {perfetto.protos.AndroidCpuMetric.Metrics} Metrics instance
                 */
                Metrics.create = function create(properties) {
                    return new Metrics(properties);
                };

                /**
                 * Encodes the specified Metrics message. Does not implicitly {@link perfetto.protos.AndroidCpuMetric.Metrics.verify|verify} messages.
                 * @function encode
                 * @memberof perfetto.protos.AndroidCpuMetric.Metrics
                 * @static
                 * @param {perfetto.protos.AndroidCpuMetric.IMetrics} message Metrics message or plain object to encode
                 * @param {$protobuf.Writer} [writer] Writer to encode to
                 * @returns {$protobuf.Writer} Writer
                 */
                Metrics.encode = function encode(message, writer) {
                    if (!writer)
                        writer = $Writer.create();
                    if (message.mcycles != null && Object.hasOwnProperty.call(message, "mcycles"))
                        writer.uint32(/* id 1, wireType 0 =*/8).int64(message.mcycles);
                    if (message.runtimeNs != null && Object.hasOwnProperty.call(message, "runtimeNs"))
                        writer.uint32(/* id 2, wireType 0 =*/16).int64(message.runtimeNs);
                    if (message.minFreqKhz != null && Object.hasOwnProperty.call(message, "minFreqKhz"))
                        writer.uint32(/* id 3, wireType 0 =*/24).int64(message.minFreqKhz);
                    if (message.maxFreqKhz != null && Object.hasOwnProperty.call(message, "maxFreqKhz"))
                        writer.uint32(/* id 4, wireType 0 =*/32).int64(message.maxFreqKhz);
                    if (message.avgFreqKhz != null && Object.hasOwnProperty.call(message, "avgFreqKhz"))
                        writer.uint32(/* id 5, wireType 0 =*/40).int64(message.avgFreqKhz);
                    return writer;
                };

                /**
                 * Encodes the specified Metrics message, length delimited. Does not implicitly {@link perfetto.protos.AndroidCpuMetric.Metrics.verify|verify} messages.
                 * @function encodeDelimited
                 * @memberof perfetto.protos.AndroidCpuMetric.Metrics
                 * @static
                 * @param {perfetto.protos.AndroidCpuMetric.IMetrics} message Metrics message or plain object to encode
                 * @param {$protobuf.Writer} [writer] Writer to encode to
                 * @returns {$protobuf.Writer} Writer
                 */
                Metrics.encodeDelimited = function encodeDelimited(message, writer) {
                    return this.encode(message, writer).ldelim();
                };

                /**
                 * Decodes a Metrics message from the specified reader or buffer.
                 * @function decode
                 * @memberof perfetto.protos.AndroidCpuMetric.Metrics
                 * @static
                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                 * @param {number} [length] Message length if known beforehand
                 * @returns {perfetto.protos.AndroidCpuMetric.Metrics} Metrics
                 * @throws {Error} If the payload is not a reader or valid buffer
                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
                 */
                Metrics.decode = function decode(reader, length) {
                    if (!(reader instanceof $Reader))
                        reader = $Reader.create(reader);
                    var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.AndroidCpuMetric.Metrics();
                    while (reader.pos < end) {
                        var tag = reader.uint32();
                        switch (tag >>> 3) {
                        case 1:
                            message.mcycles = reader.int64();
                            break;
                        case 2:
                            message.runtimeNs = reader.int64();
                            break;
                        case 3:
                            message.minFreqKhz = reader.int64();
                            break;
                        case 4:
                            message.maxFreqKhz = reader.int64();
                            break;
                        case 5:
                            message.avgFreqKhz = reader.int64();
                            break;
                        default:
                            reader.skipType(tag & 7);
                            break;
                        }
                    }
                    return message;
                };

                /**
                 * Decodes a Metrics message from the specified reader or buffer, length delimited.
                 * @function decodeDelimited
                 * @memberof perfetto.protos.AndroidCpuMetric.Metrics
                 * @static
                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                 * @returns {perfetto.protos.AndroidCpuMetric.Metrics} Metrics
                 * @throws {Error} If the payload is not a reader or valid buffer
                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
                 */
                Metrics.decodeDelimited = function decodeDelimited(reader) {
                    if (!(reader instanceof $Reader))
                        reader = new $Reader(reader);
                    return this.decode(reader, reader.uint32());
                };

                /**
                 * Verifies a Metrics message.
                 * @function verify
                 * @memberof perfetto.protos.AndroidCpuMetric.Metrics
                 * @static
                 * @param {Object.<string,*>} message Plain object to verify
                 * @returns {string|null} `null` if valid, otherwise the reason why it is not
                 */
                Metrics.verify = function verify(message) {
                    if (typeof message !== "object" || message === null)
                        return "object expected";
                    if (message.mcycles != null && message.hasOwnProperty("mcycles"))
                        if (!$util.isInteger(message.mcycles) && !(message.mcycles && $util.isInteger(message.mcycles.low) && $util.isInteger(message.mcycles.high)))
                            return "mcycles: integer|Long expected";
                    if (message.runtimeNs != null && message.hasOwnProperty("runtimeNs"))
                        if (!$util.isInteger(message.runtimeNs) && !(message.runtimeNs && $util.isInteger(message.runtimeNs.low) && $util.isInteger(message.runtimeNs.high)))
                            return "runtimeNs: integer|Long expected";
                    if (message.minFreqKhz != null && message.hasOwnProperty("minFreqKhz"))
                        if (!$util.isInteger(message.minFreqKhz) && !(message.minFreqKhz && $util.isInteger(message.minFreqKhz.low) && $util.isInteger(message.minFreqKhz.high)))
                            return "minFreqKhz: integer|Long expected";
                    if (message.maxFreqKhz != null && message.hasOwnProperty("maxFreqKhz"))
                        if (!$util.isInteger(message.maxFreqKhz) && !(message.maxFreqKhz && $util.isInteger(message.maxFreqKhz.low) && $util.isInteger(message.maxFreqKhz.high)))
                            return "maxFreqKhz: integer|Long expected";
                    if (message.avgFreqKhz != null && message.hasOwnProperty("avgFreqKhz"))
                        if (!$util.isInteger(message.avgFreqKhz) && !(message.avgFreqKhz && $util.isInteger(message.avgFreqKhz.low) && $util.isInteger(message.avgFreqKhz.high)))
                            return "avgFreqKhz: integer|Long expected";
                    return null;
                };

                /**
                 * Creates a Metrics message from a plain object. Also converts values to their respective internal types.
                 * @function fromObject
                 * @memberof perfetto.protos.AndroidCpuMetric.Metrics
                 * @static
                 * @param {Object.<string,*>} object Plain object
                 * @returns {perfetto.protos.AndroidCpuMetric.Metrics} Metrics
                 */
                Metrics.fromObject = function fromObject(object) {
                    if (object instanceof $root.perfetto.protos.AndroidCpuMetric.Metrics)
                        return object;
                    var message = new $root.perfetto.protos.AndroidCpuMetric.Metrics();
                    if (object.mcycles != null)
                        if ($util.Long)
                            (message.mcycles = $util.Long.fromValue(object.mcycles)).unsigned = false;
                        else if (typeof object.mcycles === "string")
                            message.mcycles = parseInt(object.mcycles, 10);
                        else if (typeof object.mcycles === "number")
                            message.mcycles = object.mcycles;
                        else if (typeof object.mcycles === "object")
                            message.mcycles = new $util.LongBits(object.mcycles.low >>> 0, object.mcycles.high >>> 0).toNumber();
                    if (object.runtimeNs != null)
                        if ($util.Long)
                            (message.runtimeNs = $util.Long.fromValue(object.runtimeNs)).unsigned = false;
                        else if (typeof object.runtimeNs === "string")
                            message.runtimeNs = parseInt(object.runtimeNs, 10);
                        else if (typeof object.runtimeNs === "number")
                            message.runtimeNs = object.runtimeNs;
                        else if (typeof object.runtimeNs === "object")
                            message.runtimeNs = new $util.LongBits(object.runtimeNs.low >>> 0, object.runtimeNs.high >>> 0).toNumber();
                    if (object.minFreqKhz != null)
                        if ($util.Long)
                            (message.minFreqKhz = $util.Long.fromValue(object.minFreqKhz)).unsigned = false;
                        else if (typeof object.minFreqKhz === "string")
                            message.minFreqKhz = parseInt(object.minFreqKhz, 10);
                        else if (typeof object.minFreqKhz === "number")
                            message.minFreqKhz = object.minFreqKhz;
                        else if (typeof object.minFreqKhz === "object")
                            message.minFreqKhz = new $util.LongBits(object.minFreqKhz.low >>> 0, object.minFreqKhz.high >>> 0).toNumber();
                    if (object.maxFreqKhz != null)
                        if ($util.Long)
                            (message.maxFreqKhz = $util.Long.fromValue(object.maxFreqKhz)).unsigned = false;
                        else if (typeof object.maxFreqKhz === "string")
                            message.maxFreqKhz = parseInt(object.maxFreqKhz, 10);
                        else if (typeof object.maxFreqKhz === "number")
                            message.maxFreqKhz = object.maxFreqKhz;
                        else if (typeof object.maxFreqKhz === "object")
                            message.maxFreqKhz = new $util.LongBits(object.maxFreqKhz.low >>> 0, object.maxFreqKhz.high >>> 0).toNumber();
                    if (object.avgFreqKhz != null)
                        if ($util.Long)
                            (message.avgFreqKhz = $util.Long.fromValue(object.avgFreqKhz)).unsigned = false;
                        else if (typeof object.avgFreqKhz === "string")
                            message.avgFreqKhz = parseInt(object.avgFreqKhz, 10);
                        else if (typeof object.avgFreqKhz === "number")
                            message.avgFreqKhz = object.avgFreqKhz;
                        else if (typeof object.avgFreqKhz === "object")
                            message.avgFreqKhz = new $util.LongBits(object.avgFreqKhz.low >>> 0, object.avgFreqKhz.high >>> 0).toNumber();
                    return message;
                };

                /**
                 * Creates a plain object from a Metrics message. Also converts values to other types if specified.
                 * @function toObject
                 * @memberof perfetto.protos.AndroidCpuMetric.Metrics
                 * @static
                 * @param {perfetto.protos.AndroidCpuMetric.Metrics} message Metrics
                 * @param {$protobuf.IConversionOptions} [options] Conversion options
                 * @returns {Object.<string,*>} Plain object
                 */
                Metrics.toObject = function toObject(message, options) {
                    if (!options)
                        options = {};
                    var object = {};
                    if (options.defaults) {
                        if ($util.Long) {
                            var long = new $util.Long(0, 0, false);
                            object.mcycles = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
                        } else
                            object.mcycles = options.longs === String ? "0" : 0;
                        if ($util.Long) {
                            var long = new $util.Long(0, 0, false);
                            object.runtimeNs = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
                        } else
                            object.runtimeNs = options.longs === String ? "0" : 0;
                        if ($util.Long) {
                            var long = new $util.Long(0, 0, false);
                            object.minFreqKhz = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
                        } else
                            object.minFreqKhz = options.longs === String ? "0" : 0;
                        if ($util.Long) {
                            var long = new $util.Long(0, 0, false);
                            object.maxFreqKhz = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
                        } else
                            object.maxFreqKhz = options.longs === String ? "0" : 0;
                        if ($util.Long) {
                            var long = new $util.Long(0, 0, false);
                            object.avgFreqKhz = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
                        } else
                            object.avgFreqKhz = options.longs === String ? "0" : 0;
                    }
                    if (message.mcycles != null && message.hasOwnProperty("mcycles"))
                        if (typeof message.mcycles === "number")
                            object.mcycles = options.longs === String ? String(message.mcycles) : message.mcycles;
                        else
                            object.mcycles = options.longs === String ? $util.Long.prototype.toString.call(message.mcycles) : options.longs === Number ? new $util.LongBits(message.mcycles.low >>> 0, message.mcycles.high >>> 0).toNumber() : message.mcycles;
                    if (message.runtimeNs != null && message.hasOwnProperty("runtimeNs"))
                        if (typeof message.runtimeNs === "number")
                            object.runtimeNs = options.longs === String ? String(message.runtimeNs) : message.runtimeNs;
                        else
                            object.runtimeNs = options.longs === String ? $util.Long.prototype.toString.call(message.runtimeNs) : options.longs === Number ? new $util.LongBits(message.runtimeNs.low >>> 0, message.runtimeNs.high >>> 0).toNumber() : message.runtimeNs;
                    if (message.minFreqKhz != null && message.hasOwnProperty("minFreqKhz"))
                        if (typeof message.minFreqKhz === "number")
                            object.minFreqKhz = options.longs === String ? String(message.minFreqKhz) : message.minFreqKhz;
                        else
                            object.minFreqKhz = options.longs === String ? $util.Long.prototype.toString.call(message.minFreqKhz) : options.longs === Number ? new $util.LongBits(message.minFreqKhz.low >>> 0, message.minFreqKhz.high >>> 0).toNumber() : message.minFreqKhz;
                    if (message.maxFreqKhz != null && message.hasOwnProperty("maxFreqKhz"))
                        if (typeof message.maxFreqKhz === "number")
                            object.maxFreqKhz = options.longs === String ? String(message.maxFreqKhz) : message.maxFreqKhz;
                        else
                            object.maxFreqKhz = options.longs === String ? $util.Long.prototype.toString.call(message.maxFreqKhz) : options.longs === Number ? new $util.LongBits(message.maxFreqKhz.low >>> 0, message.maxFreqKhz.high >>> 0).toNumber() : message.maxFreqKhz;
                    if (message.avgFreqKhz != null && message.hasOwnProperty("avgFreqKhz"))
                        if (typeof message.avgFreqKhz === "number")
                            object.avgFreqKhz = options.longs === String ? String(message.avgFreqKhz) : message.avgFreqKhz;
                        else
                            object.avgFreqKhz = options.longs === String ? $util.Long.prototype.toString.call(message.avgFreqKhz) : options.longs === Number ? new $util.LongBits(message.avgFreqKhz.low >>> 0, message.avgFreqKhz.high >>> 0).toNumber() : message.avgFreqKhz;
                    return object;
                };

                /**
                 * Converts this Metrics to JSON.
                 * @function toJSON
                 * @memberof perfetto.protos.AndroidCpuMetric.Metrics
                 * @instance
                 * @returns {Object.<string,*>} JSON object
                 */
                Metrics.prototype.toJSON = function toJSON() {
                    return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
                };

                return Metrics;
            })();

            AndroidCpuMetric.CoreData = (function() {

                /**
                 * Properties of a CoreData.
                 * @memberof perfetto.protos.AndroidCpuMetric
                 * @interface ICoreData
                 * @property {number|null} [id] CoreData id
                 * @property {perfetto.protos.AndroidCpuMetric.IMetrics|null} [metrics] CoreData metrics
                 */

                /**
                 * Constructs a new CoreData.
                 * @memberof perfetto.protos.AndroidCpuMetric
                 * @classdesc Represents a CoreData.
                 * @implements ICoreData
                 * @constructor
                 * @param {perfetto.protos.AndroidCpuMetric.ICoreData=} [properties] Properties to set
                 */
                function CoreData(properties) {
                    if (properties)
                        for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                            if (properties[keys[i]] != null)
                                this[keys[i]] = properties[keys[i]];
                }

                /**
                 * CoreData id.
                 * @member {number} id
                 * @memberof perfetto.protos.AndroidCpuMetric.CoreData
                 * @instance
                 */
                CoreData.prototype.id = 0;

                /**
                 * CoreData metrics.
                 * @member {perfetto.protos.AndroidCpuMetric.IMetrics|null|undefined} metrics
                 * @memberof perfetto.protos.AndroidCpuMetric.CoreData
                 * @instance
                 */
                CoreData.prototype.metrics = null;

                /**
                 * Creates a new CoreData instance using the specified properties.
                 * @function create
                 * @memberof perfetto.protos.AndroidCpuMetric.CoreData
                 * @static
                 * @param {perfetto.protos.AndroidCpuMetric.ICoreData=} [properties] Properties to set
                 * @returns {perfetto.protos.AndroidCpuMetric.CoreData} CoreData instance
                 */
                CoreData.create = function create(properties) {
                    return new CoreData(properties);
                };

                /**
                 * Encodes the specified CoreData message. Does not implicitly {@link perfetto.protos.AndroidCpuMetric.CoreData.verify|verify} messages.
                 * @function encode
                 * @memberof perfetto.protos.AndroidCpuMetric.CoreData
                 * @static
                 * @param {perfetto.protos.AndroidCpuMetric.ICoreData} message CoreData message or plain object to encode
                 * @param {$protobuf.Writer} [writer] Writer to encode to
                 * @returns {$protobuf.Writer} Writer
                 */
                CoreData.encode = function encode(message, writer) {
                    if (!writer)
                        writer = $Writer.create();
                    if (message.id != null && Object.hasOwnProperty.call(message, "id"))
                        writer.uint32(/* id 1, wireType 0 =*/8).uint32(message.id);
                    if (message.metrics != null && Object.hasOwnProperty.call(message, "metrics"))
                        $root.perfetto.protos.AndroidCpuMetric.Metrics.encode(message.metrics, writer.uint32(/* id 6, wireType 2 =*/50).fork()).ldelim();
                    return writer;
                };

                /**
                 * Encodes the specified CoreData message, length delimited. Does not implicitly {@link perfetto.protos.AndroidCpuMetric.CoreData.verify|verify} messages.
                 * @function encodeDelimited
                 * @memberof perfetto.protos.AndroidCpuMetric.CoreData
                 * @static
                 * @param {perfetto.protos.AndroidCpuMetric.ICoreData} message CoreData message or plain object to encode
                 * @param {$protobuf.Writer} [writer] Writer to encode to
                 * @returns {$protobuf.Writer} Writer
                 */
                CoreData.encodeDelimited = function encodeDelimited(message, writer) {
                    return this.encode(message, writer).ldelim();
                };

                /**
                 * Decodes a CoreData message from the specified reader or buffer.
                 * @function decode
                 * @memberof perfetto.protos.AndroidCpuMetric.CoreData
                 * @static
                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                 * @param {number} [length] Message length if known beforehand
                 * @returns {perfetto.protos.AndroidCpuMetric.CoreData} CoreData
                 * @throws {Error} If the payload is not a reader or valid buffer
                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
                 */
                CoreData.decode = function decode(reader, length) {
                    if (!(reader instanceof $Reader))
                        reader = $Reader.create(reader);
                    var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.AndroidCpuMetric.CoreData();
                    while (reader.pos < end) {
                        var tag = reader.uint32();
                        switch (tag >>> 3) {
                        case 1:
                            message.id = reader.uint32();
                            break;
                        case 6:
                            message.metrics = $root.perfetto.protos.AndroidCpuMetric.Metrics.decode(reader, reader.uint32());
                            break;
                        default:
                            reader.skipType(tag & 7);
                            break;
                        }
                    }
                    return message;
                };

                /**
                 * Decodes a CoreData message from the specified reader or buffer, length delimited.
                 * @function decodeDelimited
                 * @memberof perfetto.protos.AndroidCpuMetric.CoreData
                 * @static
                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                 * @returns {perfetto.protos.AndroidCpuMetric.CoreData} CoreData
                 * @throws {Error} If the payload is not a reader or valid buffer
                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
                 */
                CoreData.decodeDelimited = function decodeDelimited(reader) {
                    if (!(reader instanceof $Reader))
                        reader = new $Reader(reader);
                    return this.decode(reader, reader.uint32());
                };

                /**
                 * Verifies a CoreData message.
                 * @function verify
                 * @memberof perfetto.protos.AndroidCpuMetric.CoreData
                 * @static
                 * @param {Object.<string,*>} message Plain object to verify
                 * @returns {string|null} `null` if valid, otherwise the reason why it is not
                 */
                CoreData.verify = function verify(message) {
                    if (typeof message !== "object" || message === null)
                        return "object expected";
                    if (message.id != null && message.hasOwnProperty("id"))
                        if (!$util.isInteger(message.id))
                            return "id: integer expected";
                    if (message.metrics != null && message.hasOwnProperty("metrics")) {
                        var error = $root.perfetto.protos.AndroidCpuMetric.Metrics.verify(message.metrics);
                        if (error)
                            return "metrics." + error;
                    }
                    return null;
                };

                /**
                 * Creates a CoreData message from a plain object. Also converts values to their respective internal types.
                 * @function fromObject
                 * @memberof perfetto.protos.AndroidCpuMetric.CoreData
                 * @static
                 * @param {Object.<string,*>} object Plain object
                 * @returns {perfetto.protos.AndroidCpuMetric.CoreData} CoreData
                 */
                CoreData.fromObject = function fromObject(object) {
                    if (object instanceof $root.perfetto.protos.AndroidCpuMetric.CoreData)
                        return object;
                    var message = new $root.perfetto.protos.AndroidCpuMetric.CoreData();
                    if (object.id != null)
                        message.id = object.id >>> 0;
                    if (object.metrics != null) {
                        if (typeof object.metrics !== "object")
                            throw TypeError(".perfetto.protos.AndroidCpuMetric.CoreData.metrics: object expected");
                        message.metrics = $root.perfetto.protos.AndroidCpuMetric.Metrics.fromObject(object.metrics);
                    }
                    return message;
                };

                /**
                 * Creates a plain object from a CoreData message. Also converts values to other types if specified.
                 * @function toObject
                 * @memberof perfetto.protos.AndroidCpuMetric.CoreData
                 * @static
                 * @param {perfetto.protos.AndroidCpuMetric.CoreData} message CoreData
                 * @param {$protobuf.IConversionOptions} [options] Conversion options
                 * @returns {Object.<string,*>} Plain object
                 */
                CoreData.toObject = function toObject(message, options) {
                    if (!options)
                        options = {};
                    var object = {};
                    if (options.defaults) {
                        object.id = 0;
                        object.metrics = null;
                    }
                    if (message.id != null && message.hasOwnProperty("id"))
                        object.id = message.id;
                    if (message.metrics != null && message.hasOwnProperty("metrics"))
                        object.metrics = $root.perfetto.protos.AndroidCpuMetric.Metrics.toObject(message.metrics, options);
                    return object;
                };

                /**
                 * Converts this CoreData to JSON.
                 * @function toJSON
                 * @memberof perfetto.protos.AndroidCpuMetric.CoreData
                 * @instance
                 * @returns {Object.<string,*>} JSON object
                 */
                CoreData.prototype.toJSON = function toJSON() {
                    return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
                };

                return CoreData;
            })();

            AndroidCpuMetric.CoreTypeData = (function() {

                /**
                 * Properties of a CoreTypeData.
                 * @memberof perfetto.protos.AndroidCpuMetric
                 * @interface ICoreTypeData
                 * @property {string|null} [type] CoreTypeData type
                 * @property {perfetto.protos.AndroidCpuMetric.IMetrics|null} [metrics] CoreTypeData metrics
                 */

                /**
                 * Constructs a new CoreTypeData.
                 * @memberof perfetto.protos.AndroidCpuMetric
                 * @classdesc Represents a CoreTypeData.
                 * @implements ICoreTypeData
                 * @constructor
                 * @param {perfetto.protos.AndroidCpuMetric.ICoreTypeData=} [properties] Properties to set
                 */
                function CoreTypeData(properties) {
                    if (properties)
                        for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                            if (properties[keys[i]] != null)
                                this[keys[i]] = properties[keys[i]];
                }

                /**
                 * CoreTypeData type.
                 * @member {string} type
                 * @memberof perfetto.protos.AndroidCpuMetric.CoreTypeData
                 * @instance
                 */
                CoreTypeData.prototype.type = "";

                /**
                 * CoreTypeData metrics.
                 * @member {perfetto.protos.AndroidCpuMetric.IMetrics|null|undefined} metrics
                 * @memberof perfetto.protos.AndroidCpuMetric.CoreTypeData
                 * @instance
                 */
                CoreTypeData.prototype.metrics = null;

                /**
                 * Creates a new CoreTypeData instance using the specified properties.
                 * @function create
                 * @memberof perfetto.protos.AndroidCpuMetric.CoreTypeData
                 * @static
                 * @param {perfetto.protos.AndroidCpuMetric.ICoreTypeData=} [properties] Properties to set
                 * @returns {perfetto.protos.AndroidCpuMetric.CoreTypeData} CoreTypeData instance
                 */
                CoreTypeData.create = function create(properties) {
                    return new CoreTypeData(properties);
                };

                /**
                 * Encodes the specified CoreTypeData message. Does not implicitly {@link perfetto.protos.AndroidCpuMetric.CoreTypeData.verify|verify} messages.
                 * @function encode
                 * @memberof perfetto.protos.AndroidCpuMetric.CoreTypeData
                 * @static
                 * @param {perfetto.protos.AndroidCpuMetric.ICoreTypeData} message CoreTypeData message or plain object to encode
                 * @param {$protobuf.Writer} [writer] Writer to encode to
                 * @returns {$protobuf.Writer} Writer
                 */
                CoreTypeData.encode = function encode(message, writer) {
                    if (!writer)
                        writer = $Writer.create();
                    if (message.type != null && Object.hasOwnProperty.call(message, "type"))
                        writer.uint32(/* id 1, wireType 2 =*/10).string(message.type);
                    if (message.metrics != null && Object.hasOwnProperty.call(message, "metrics"))
                        $root.perfetto.protos.AndroidCpuMetric.Metrics.encode(message.metrics, writer.uint32(/* id 2, wireType 2 =*/18).fork()).ldelim();
                    return writer;
                };

                /**
                 * Encodes the specified CoreTypeData message, length delimited. Does not implicitly {@link perfetto.protos.AndroidCpuMetric.CoreTypeData.verify|verify} messages.
                 * @function encodeDelimited
                 * @memberof perfetto.protos.AndroidCpuMetric.CoreTypeData
                 * @static
                 * @param {perfetto.protos.AndroidCpuMetric.ICoreTypeData} message CoreTypeData message or plain object to encode
                 * @param {$protobuf.Writer} [writer] Writer to encode to
                 * @returns {$protobuf.Writer} Writer
                 */
                CoreTypeData.encodeDelimited = function encodeDelimited(message, writer) {
                    return this.encode(message, writer).ldelim();
                };

                /**
                 * Decodes a CoreTypeData message from the specified reader or buffer.
                 * @function decode
                 * @memberof perfetto.protos.AndroidCpuMetric.CoreTypeData
                 * @static
                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                 * @param {number} [length] Message length if known beforehand
                 * @returns {perfetto.protos.AndroidCpuMetric.CoreTypeData} CoreTypeData
                 * @throws {Error} If the payload is not a reader or valid buffer
                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
                 */
                CoreTypeData.decode = function decode(reader, length) {
                    if (!(reader instanceof $Reader))
                        reader = $Reader.create(reader);
                    var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.AndroidCpuMetric.CoreTypeData();
                    while (reader.pos < end) {
                        var tag = reader.uint32();
                        switch (tag >>> 3) {
                        case 1:
                            message.type = reader.string();
                            break;
                        case 2:
                            message.metrics = $root.perfetto.protos.AndroidCpuMetric.Metrics.decode(reader, reader.uint32());
                            break;
                        default:
                            reader.skipType(tag & 7);
                            break;
                        }
                    }
                    return message;
                };

                /**
                 * Decodes a CoreTypeData message from the specified reader or buffer, length delimited.
                 * @function decodeDelimited
                 * @memberof perfetto.protos.AndroidCpuMetric.CoreTypeData
                 * @static
                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                 * @returns {perfetto.protos.AndroidCpuMetric.CoreTypeData} CoreTypeData
                 * @throws {Error} If the payload is not a reader or valid buffer
                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
                 */
                CoreTypeData.decodeDelimited = function decodeDelimited(reader) {
                    if (!(reader instanceof $Reader))
                        reader = new $Reader(reader);
                    return this.decode(reader, reader.uint32());
                };

                /**
                 * Verifies a CoreTypeData message.
                 * @function verify
                 * @memberof perfetto.protos.AndroidCpuMetric.CoreTypeData
                 * @static
                 * @param {Object.<string,*>} message Plain object to verify
                 * @returns {string|null} `null` if valid, otherwise the reason why it is not
                 */
                CoreTypeData.verify = function verify(message) {
                    if (typeof message !== "object" || message === null)
                        return "object expected";
                    if (message.type != null && message.hasOwnProperty("type"))
                        if (!$util.isString(message.type))
                            return "type: string expected";
                    if (message.metrics != null && message.hasOwnProperty("metrics")) {
                        var error = $root.perfetto.protos.AndroidCpuMetric.Metrics.verify(message.metrics);
                        if (error)
                            return "metrics." + error;
                    }
                    return null;
                };

                /**
                 * Creates a CoreTypeData message from a plain object. Also converts values to their respective internal types.
                 * @function fromObject
                 * @memberof perfetto.protos.AndroidCpuMetric.CoreTypeData
                 * @static
                 * @param {Object.<string,*>} object Plain object
                 * @returns {perfetto.protos.AndroidCpuMetric.CoreTypeData} CoreTypeData
                 */
                CoreTypeData.fromObject = function fromObject(object) {
                    if (object instanceof $root.perfetto.protos.AndroidCpuMetric.CoreTypeData)
                        return object;
                    var message = new $root.perfetto.protos.AndroidCpuMetric.CoreTypeData();
                    if (object.type != null)
                        message.type = String(object.type);
                    if (object.metrics != null) {
                        if (typeof object.metrics !== "object")
                            throw TypeError(".perfetto.protos.AndroidCpuMetric.CoreTypeData.metrics: object expected");
                        message.metrics = $root.perfetto.protos.AndroidCpuMetric.Metrics.fromObject(object.metrics);
                    }
                    return message;
                };

                /**
                 * Creates a plain object from a CoreTypeData message. Also converts values to other types if specified.
                 * @function toObject
                 * @memberof perfetto.protos.AndroidCpuMetric.CoreTypeData
                 * @static
                 * @param {perfetto.protos.AndroidCpuMetric.CoreTypeData} message CoreTypeData
                 * @param {$protobuf.IConversionOptions} [options] Conversion options
                 * @returns {Object.<string,*>} Plain object
                 */
                CoreTypeData.toObject = function toObject(message, options) {
                    if (!options)
                        options = {};
                    var object = {};
                    if (options.defaults) {
                        object.type = "";
                        object.metrics = null;
                    }
                    if (message.type != null && message.hasOwnProperty("type"))
                        object.type = message.type;
                    if (message.metrics != null && message.hasOwnProperty("metrics"))
                        object.metrics = $root.perfetto.protos.AndroidCpuMetric.Metrics.toObject(message.metrics, options);
                    return object;
                };

                /**
                 * Converts this CoreTypeData to JSON.
                 * @function toJSON
                 * @memberof perfetto.protos.AndroidCpuMetric.CoreTypeData
                 * @instance
                 * @returns {Object.<string,*>} JSON object
                 */
                CoreTypeData.prototype.toJSON = function toJSON() {
                    return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
                };

                return CoreTypeData;
            })();

            AndroidCpuMetric.Thread = (function() {

                /**
                 * Properties of a Thread.
                 * @memberof perfetto.protos.AndroidCpuMetric
                 * @interface IThread
                 * @property {string|null} [name] Thread name
                 * @property {perfetto.protos.AndroidCpuMetric.IMetrics|null} [metrics] Thread metrics
                 * @property {Array.<perfetto.protos.AndroidCpuMetric.ICoreData>|null} [core] Thread core
                 * @property {Array.<perfetto.protos.AndroidCpuMetric.ICoreTypeData>|null} [coreType] Thread coreType
                 */

                /**
                 * Constructs a new Thread.
                 * @memberof perfetto.protos.AndroidCpuMetric
                 * @classdesc Represents a Thread.
                 * @implements IThread
                 * @constructor
                 * @param {perfetto.protos.AndroidCpuMetric.IThread=} [properties] Properties to set
                 */
                function Thread(properties) {
                    this.core = [];
                    this.coreType = [];
                    if (properties)
                        for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                            if (properties[keys[i]] != null)
                                this[keys[i]] = properties[keys[i]];
                }

                /**
                 * Thread name.
                 * @member {string} name
                 * @memberof perfetto.protos.AndroidCpuMetric.Thread
                 * @instance
                 */
                Thread.prototype.name = "";

                /**
                 * Thread metrics.
                 * @member {perfetto.protos.AndroidCpuMetric.IMetrics|null|undefined} metrics
                 * @memberof perfetto.protos.AndroidCpuMetric.Thread
                 * @instance
                 */
                Thread.prototype.metrics = null;

                /**
                 * Thread core.
                 * @member {Array.<perfetto.protos.AndroidCpuMetric.ICoreData>} core
                 * @memberof perfetto.protos.AndroidCpuMetric.Thread
                 * @instance
                 */
                Thread.prototype.core = $util.emptyArray;

                /**
                 * Thread coreType.
                 * @member {Array.<perfetto.protos.AndroidCpuMetric.ICoreTypeData>} coreType
                 * @memberof perfetto.protos.AndroidCpuMetric.Thread
                 * @instance
                 */
                Thread.prototype.coreType = $util.emptyArray;

                /**
                 * Creates a new Thread instance using the specified properties.
                 * @function create
                 * @memberof perfetto.protos.AndroidCpuMetric.Thread
                 * @static
                 * @param {perfetto.protos.AndroidCpuMetric.IThread=} [properties] Properties to set
                 * @returns {perfetto.protos.AndroidCpuMetric.Thread} Thread instance
                 */
                Thread.create = function create(properties) {
                    return new Thread(properties);
                };

                /**
                 * Encodes the specified Thread message. Does not implicitly {@link perfetto.protos.AndroidCpuMetric.Thread.verify|verify} messages.
                 * @function encode
                 * @memberof perfetto.protos.AndroidCpuMetric.Thread
                 * @static
                 * @param {perfetto.protos.AndroidCpuMetric.IThread} message Thread message or plain object to encode
                 * @param {$protobuf.Writer} [writer] Writer to encode to
                 * @returns {$protobuf.Writer} Writer
                 */
                Thread.encode = function encode(message, writer) {
                    if (!writer)
                        writer = $Writer.create();
                    if (message.name != null && Object.hasOwnProperty.call(message, "name"))
                        writer.uint32(/* id 1, wireType 2 =*/10).string(message.name);
                    if (message.core != null && message.core.length)
                        for (var i = 0; i < message.core.length; ++i)
                            $root.perfetto.protos.AndroidCpuMetric.CoreData.encode(message.core[i], writer.uint32(/* id 2, wireType 2 =*/18).fork()).ldelim();
                    if (message.metrics != null && Object.hasOwnProperty.call(message, "metrics"))
                        $root.perfetto.protos.AndroidCpuMetric.Metrics.encode(message.metrics, writer.uint32(/* id 4, wireType 2 =*/34).fork()).ldelim();
                    if (message.coreType != null && message.coreType.length)
                        for (var i = 0; i < message.coreType.length; ++i)
                            $root.perfetto.protos.AndroidCpuMetric.CoreTypeData.encode(message.coreType[i], writer.uint32(/* id 5, wireType 2 =*/42).fork()).ldelim();
                    return writer;
                };

                /**
                 * Encodes the specified Thread message, length delimited. Does not implicitly {@link perfetto.protos.AndroidCpuMetric.Thread.verify|verify} messages.
                 * @function encodeDelimited
                 * @memberof perfetto.protos.AndroidCpuMetric.Thread
                 * @static
                 * @param {perfetto.protos.AndroidCpuMetric.IThread} message Thread message or plain object to encode
                 * @param {$protobuf.Writer} [writer] Writer to encode to
                 * @returns {$protobuf.Writer} Writer
                 */
                Thread.encodeDelimited = function encodeDelimited(message, writer) {
                    return this.encode(message, writer).ldelim();
                };

                /**
                 * Decodes a Thread message from the specified reader or buffer.
                 * @function decode
                 * @memberof perfetto.protos.AndroidCpuMetric.Thread
                 * @static
                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                 * @param {number} [length] Message length if known beforehand
                 * @returns {perfetto.protos.AndroidCpuMetric.Thread} Thread
                 * @throws {Error} If the payload is not a reader or valid buffer
                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
                 */
                Thread.decode = function decode(reader, length) {
                    if (!(reader instanceof $Reader))
                        reader = $Reader.create(reader);
                    var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.AndroidCpuMetric.Thread();
                    while (reader.pos < end) {
                        var tag = reader.uint32();
                        switch (tag >>> 3) {
                        case 1:
                            message.name = reader.string();
                            break;
                        case 4:
                            message.metrics = $root.perfetto.protos.AndroidCpuMetric.Metrics.decode(reader, reader.uint32());
                            break;
                        case 2:
                            if (!(message.core && message.core.length))
                                message.core = [];
                            message.core.push($root.perfetto.protos.AndroidCpuMetric.CoreData.decode(reader, reader.uint32()));
                            break;
                        case 5:
                            if (!(message.coreType && message.coreType.length))
                                message.coreType = [];
                            message.coreType.push($root.perfetto.protos.AndroidCpuMetric.CoreTypeData.decode(reader, reader.uint32()));
                            break;
                        default:
                            reader.skipType(tag & 7);
                            break;
                        }
                    }
                    return message;
                };

                /**
                 * Decodes a Thread message from the specified reader or buffer, length delimited.
                 * @function decodeDelimited
                 * @memberof perfetto.protos.AndroidCpuMetric.Thread
                 * @static
                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                 * @returns {perfetto.protos.AndroidCpuMetric.Thread} Thread
                 * @throws {Error} If the payload is not a reader or valid buffer
                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
                 */
                Thread.decodeDelimited = function decodeDelimited(reader) {
                    if (!(reader instanceof $Reader))
                        reader = new $Reader(reader);
                    return this.decode(reader, reader.uint32());
                };

                /**
                 * Verifies a Thread message.
                 * @function verify
                 * @memberof perfetto.protos.AndroidCpuMetric.Thread
                 * @static
                 * @param {Object.<string,*>} message Plain object to verify
                 * @returns {string|null} `null` if valid, otherwise the reason why it is not
                 */
                Thread.verify = function verify(message) {
                    if (typeof message !== "object" || message === null)
                        return "object expected";
                    if (message.name != null && message.hasOwnProperty("name"))
                        if (!$util.isString(message.name))
                            return "name: string expected";
                    if (message.metrics != null && message.hasOwnProperty("metrics")) {
                        var error = $root.perfetto.protos.AndroidCpuMetric.Metrics.verify(message.metrics);
                        if (error)
                            return "metrics." + error;
                    }
                    if (message.core != null && message.hasOwnProperty("core")) {
                        if (!Array.isArray(message.core))
                            return "core: array expected";
                        for (var i = 0; i < message.core.length; ++i) {
                            var error = $root.perfetto.protos.AndroidCpuMetric.CoreData.verify(message.core[i]);
                            if (error)
                                return "core." + error;
                        }
                    }
                    if (message.coreType != null && message.hasOwnProperty("coreType")) {
                        if (!Array.isArray(message.coreType))
                            return "coreType: array expected";
                        for (var i = 0; i < message.coreType.length; ++i) {
                            var error = $root.perfetto.protos.AndroidCpuMetric.CoreTypeData.verify(message.coreType[i]);
                            if (error)
                                return "coreType." + error;
                        }
                    }
                    return null;
                };

                /**
                 * Creates a Thread message from a plain object. Also converts values to their respective internal types.
                 * @function fromObject
                 * @memberof perfetto.protos.AndroidCpuMetric.Thread
                 * @static
                 * @param {Object.<string,*>} object Plain object
                 * @returns {perfetto.protos.AndroidCpuMetric.Thread} Thread
                 */
                Thread.fromObject = function fromObject(object) {
                    if (object instanceof $root.perfetto.protos.AndroidCpuMetric.Thread)
                        return object;
                    var message = new $root.perfetto.protos.AndroidCpuMetric.Thread();
                    if (object.name != null)
                        message.name = String(object.name);
                    if (object.metrics != null) {
                        if (typeof object.metrics !== "object")
                            throw TypeError(".perfetto.protos.AndroidCpuMetric.Thread.metrics: object expected");
                        message.metrics = $root.perfetto.protos.AndroidCpuMetric.Metrics.fromObject(object.metrics);
                    }
                    if (object.core) {
                        if (!Array.isArray(object.core))
                            throw TypeError(".perfetto.protos.AndroidCpuMetric.Thread.core: array expected");
                        message.core = [];
                        for (var i = 0; i < object.core.length; ++i) {
                            if (typeof object.core[i] !== "object")
                                throw TypeError(".perfetto.protos.AndroidCpuMetric.Thread.core: object expected");
                            message.core[i] = $root.perfetto.protos.AndroidCpuMetric.CoreData.fromObject(object.core[i]);
                        }
                    }
                    if (object.coreType) {
                        if (!Array.isArray(object.coreType))
                            throw TypeError(".perfetto.protos.AndroidCpuMetric.Thread.coreType: array expected");
                        message.coreType = [];
                        for (var i = 0; i < object.coreType.length; ++i) {
                            if (typeof object.coreType[i] !== "object")
                                throw TypeError(".perfetto.protos.AndroidCpuMetric.Thread.coreType: object expected");
                            message.coreType[i] = $root.perfetto.protos.AndroidCpuMetric.CoreTypeData.fromObject(object.coreType[i]);
                        }
                    }
                    return message;
                };

                /**
                 * Creates a plain object from a Thread message. Also converts values to other types if specified.
                 * @function toObject
                 * @memberof perfetto.protos.AndroidCpuMetric.Thread
                 * @static
                 * @param {perfetto.protos.AndroidCpuMetric.Thread} message Thread
                 * @param {$protobuf.IConversionOptions} [options] Conversion options
                 * @returns {Object.<string,*>} Plain object
                 */
                Thread.toObject = function toObject(message, options) {
                    if (!options)
                        options = {};
                    var object = {};
                    if (options.arrays || options.defaults) {
                        object.core = [];
                        object.coreType = [];
                    }
                    if (options.defaults) {
                        object.name = "";
                        object.metrics = null;
                    }
                    if (message.name != null && message.hasOwnProperty("name"))
                        object.name = message.name;
                    if (message.core && message.core.length) {
                        object.core = [];
                        for (var j = 0; j < message.core.length; ++j)
                            object.core[j] = $root.perfetto.protos.AndroidCpuMetric.CoreData.toObject(message.core[j], options);
                    }
                    if (message.metrics != null && message.hasOwnProperty("metrics"))
                        object.metrics = $root.perfetto.protos.AndroidCpuMetric.Metrics.toObject(message.metrics, options);
                    if (message.coreType && message.coreType.length) {
                        object.coreType = [];
                        for (var j = 0; j < message.coreType.length; ++j)
                            object.coreType[j] = $root.perfetto.protos.AndroidCpuMetric.CoreTypeData.toObject(message.coreType[j], options);
                    }
                    return object;
                };

                /**
                 * Converts this Thread to JSON.
                 * @function toJSON
                 * @memberof perfetto.protos.AndroidCpuMetric.Thread
                 * @instance
                 * @returns {Object.<string,*>} JSON object
                 */
                Thread.prototype.toJSON = function toJSON() {
                    return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
                };

                return Thread;
            })();

            AndroidCpuMetric.Process = (function() {

                /**
                 * Properties of a Process.
                 * @memberof perfetto.protos.AndroidCpuMetric
                 * @interface IProcess
                 * @property {string|null} [name] Process name
                 * @property {perfetto.protos.AndroidCpuMetric.IMetrics|null} [metrics] Process metrics
                 * @property {Array.<perfetto.protos.AndroidCpuMetric.IThread>|null} [threads] Process threads
                 * @property {Array.<perfetto.protos.AndroidCpuMetric.ICoreData>|null} [core] Process core
                 * @property {Array.<perfetto.protos.AndroidCpuMetric.ICoreTypeData>|null} [coreType] Process coreType
                 */

                /**
                 * Constructs a new Process.
                 * @memberof perfetto.protos.AndroidCpuMetric
                 * @classdesc Represents a Process.
                 * @implements IProcess
                 * @constructor
                 * @param {perfetto.protos.AndroidCpuMetric.IProcess=} [properties] Properties to set
                 */
                function Process(properties) {
                    this.threads = [];
                    this.core = [];
                    this.coreType = [];
                    if (properties)
                        for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                            if (properties[keys[i]] != null)
                                this[keys[i]] = properties[keys[i]];
                }

                /**
                 * Process name.
                 * @member {string} name
                 * @memberof perfetto.protos.AndroidCpuMetric.Process
                 * @instance
                 */
                Process.prototype.name = "";

                /**
                 * Process metrics.
                 * @member {perfetto.protos.AndroidCpuMetric.IMetrics|null|undefined} metrics
                 * @memberof perfetto.protos.AndroidCpuMetric.Process
                 * @instance
                 */
                Process.prototype.metrics = null;

                /**
                 * Process threads.
                 * @member {Array.<perfetto.protos.AndroidCpuMetric.IThread>} threads
                 * @memberof perfetto.protos.AndroidCpuMetric.Process
                 * @instance
                 */
                Process.prototype.threads = $util.emptyArray;

                /**
                 * Process core.
                 * @member {Array.<perfetto.protos.AndroidCpuMetric.ICoreData>} core
                 * @memberof perfetto.protos.AndroidCpuMetric.Process
                 * @instance
                 */
                Process.prototype.core = $util.emptyArray;

                /**
                 * Process coreType.
                 * @member {Array.<perfetto.protos.AndroidCpuMetric.ICoreTypeData>} coreType
                 * @memberof perfetto.protos.AndroidCpuMetric.Process
                 * @instance
                 */
                Process.prototype.coreType = $util.emptyArray;

                /**
                 * Creates a new Process instance using the specified properties.
                 * @function create
                 * @memberof perfetto.protos.AndroidCpuMetric.Process
                 * @static
                 * @param {perfetto.protos.AndroidCpuMetric.IProcess=} [properties] Properties to set
                 * @returns {perfetto.protos.AndroidCpuMetric.Process} Process instance
                 */
                Process.create = function create(properties) {
                    return new Process(properties);
                };

                /**
                 * Encodes the specified Process message. Does not implicitly {@link perfetto.protos.AndroidCpuMetric.Process.verify|verify} messages.
                 * @function encode
                 * @memberof perfetto.protos.AndroidCpuMetric.Process
                 * @static
                 * @param {perfetto.protos.AndroidCpuMetric.IProcess} message Process message or plain object to encode
                 * @param {$protobuf.Writer} [writer] Writer to encode to
                 * @returns {$protobuf.Writer} Writer
                 */
                Process.encode = function encode(message, writer) {
                    if (!writer)
                        writer = $Writer.create();
                    if (message.name != null && Object.hasOwnProperty.call(message, "name"))
                        writer.uint32(/* id 1, wireType 2 =*/10).string(message.name);
                    if (message.metrics != null && Object.hasOwnProperty.call(message, "metrics"))
                        $root.perfetto.protos.AndroidCpuMetric.Metrics.encode(message.metrics, writer.uint32(/* id 4, wireType 2 =*/34).fork()).ldelim();
                    if (message.coreType != null && message.coreType.length)
                        for (var i = 0; i < message.coreType.length; ++i)
                            $root.perfetto.protos.AndroidCpuMetric.CoreTypeData.encode(message.coreType[i], writer.uint32(/* id 5, wireType 2 =*/42).fork()).ldelim();
                    if (message.threads != null && message.threads.length)
                        for (var i = 0; i < message.threads.length; ++i)
                            $root.perfetto.protos.AndroidCpuMetric.Thread.encode(message.threads[i], writer.uint32(/* id 6, wireType 2 =*/50).fork()).ldelim();
                    if (message.core != null && message.core.length)
                        for (var i = 0; i < message.core.length; ++i)
                            $root.perfetto.protos.AndroidCpuMetric.CoreData.encode(message.core[i], writer.uint32(/* id 7, wireType 2 =*/58).fork()).ldelim();
                    return writer;
                };

                /**
                 * Encodes the specified Process message, length delimited. Does not implicitly {@link perfetto.protos.AndroidCpuMetric.Process.verify|verify} messages.
                 * @function encodeDelimited
                 * @memberof perfetto.protos.AndroidCpuMetric.Process
                 * @static
                 * @param {perfetto.protos.AndroidCpuMetric.IProcess} message Process message or plain object to encode
                 * @param {$protobuf.Writer} [writer] Writer to encode to
                 * @returns {$protobuf.Writer} Writer
                 */
                Process.encodeDelimited = function encodeDelimited(message, writer) {
                    return this.encode(message, writer).ldelim();
                };

                /**
                 * Decodes a Process message from the specified reader or buffer.
                 * @function decode
                 * @memberof perfetto.protos.AndroidCpuMetric.Process
                 * @static
                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                 * @param {number} [length] Message length if known beforehand
                 * @returns {perfetto.protos.AndroidCpuMetric.Process} Process
                 * @throws {Error} If the payload is not a reader or valid buffer
                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
                 */
                Process.decode = function decode(reader, length) {
                    if (!(reader instanceof $Reader))
                        reader = $Reader.create(reader);
                    var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.AndroidCpuMetric.Process();
                    while (reader.pos < end) {
                        var tag = reader.uint32();
                        switch (tag >>> 3) {
                        case 1:
                            message.name = reader.string();
                            break;
                        case 4:
                            message.metrics = $root.perfetto.protos.AndroidCpuMetric.Metrics.decode(reader, reader.uint32());
                            break;
                        case 6:
                            if (!(message.threads && message.threads.length))
                                message.threads = [];
                            message.threads.push($root.perfetto.protos.AndroidCpuMetric.Thread.decode(reader, reader.uint32()));
                            break;
                        case 7:
                            if (!(message.core && message.core.length))
                                message.core = [];
                            message.core.push($root.perfetto.protos.AndroidCpuMetric.CoreData.decode(reader, reader.uint32()));
                            break;
                        case 5:
                            if (!(message.coreType && message.coreType.length))
                                message.coreType = [];
                            message.coreType.push($root.perfetto.protos.AndroidCpuMetric.CoreTypeData.decode(reader, reader.uint32()));
                            break;
                        default:
                            reader.skipType(tag & 7);
                            break;
                        }
                    }
                    return message;
                };

                /**
                 * Decodes a Process message from the specified reader or buffer, length delimited.
                 * @function decodeDelimited
                 * @memberof perfetto.protos.AndroidCpuMetric.Process
                 * @static
                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                 * @returns {perfetto.protos.AndroidCpuMetric.Process} Process
                 * @throws {Error} If the payload is not a reader or valid buffer
                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
                 */
                Process.decodeDelimited = function decodeDelimited(reader) {
                    if (!(reader instanceof $Reader))
                        reader = new $Reader(reader);
                    return this.decode(reader, reader.uint32());
                };

                /**
                 * Verifies a Process message.
                 * @function verify
                 * @memberof perfetto.protos.AndroidCpuMetric.Process
                 * @static
                 * @param {Object.<string,*>} message Plain object to verify
                 * @returns {string|null} `null` if valid, otherwise the reason why it is not
                 */
                Process.verify = function verify(message) {
                    if (typeof message !== "object" || message === null)
                        return "object expected";
                    if (message.name != null && message.hasOwnProperty("name"))
                        if (!$util.isString(message.name))
                            return "name: string expected";
                    if (message.metrics != null && message.hasOwnProperty("metrics")) {
                        var error = $root.perfetto.protos.AndroidCpuMetric.Metrics.verify(message.metrics);
                        if (error)
                            return "metrics." + error;
                    }
                    if (message.threads != null && message.hasOwnProperty("threads")) {
                        if (!Array.isArray(message.threads))
                            return "threads: array expected";
                        for (var i = 0; i < message.threads.length; ++i) {
                            var error = $root.perfetto.protos.AndroidCpuMetric.Thread.verify(message.threads[i]);
                            if (error)
                                return "threads." + error;
                        }
                    }
                    if (message.core != null && message.hasOwnProperty("core")) {
                        if (!Array.isArray(message.core))
                            return "core: array expected";
                        for (var i = 0; i < message.core.length; ++i) {
                            var error = $root.perfetto.protos.AndroidCpuMetric.CoreData.verify(message.core[i]);
                            if (error)
                                return "core." + error;
                        }
                    }
                    if (message.coreType != null && message.hasOwnProperty("coreType")) {
                        if (!Array.isArray(message.coreType))
                            return "coreType: array expected";
                        for (var i = 0; i < message.coreType.length; ++i) {
                            var error = $root.perfetto.protos.AndroidCpuMetric.CoreTypeData.verify(message.coreType[i]);
                            if (error)
                                return "coreType." + error;
                        }
                    }
                    return null;
                };

                /**
                 * Creates a Process message from a plain object. Also converts values to their respective internal types.
                 * @function fromObject
                 * @memberof perfetto.protos.AndroidCpuMetric.Process
                 * @static
                 * @param {Object.<string,*>} object Plain object
                 * @returns {perfetto.protos.AndroidCpuMetric.Process} Process
                 */
                Process.fromObject = function fromObject(object) {
                    if (object instanceof $root.perfetto.protos.AndroidCpuMetric.Process)
                        return object;
                    var message = new $root.perfetto.protos.AndroidCpuMetric.Process();
                    if (object.name != null)
                        message.name = String(object.name);
                    if (object.metrics != null) {
                        if (typeof object.metrics !== "object")
                            throw TypeError(".perfetto.protos.AndroidCpuMetric.Process.metrics: object expected");
                        message.metrics = $root.perfetto.protos.AndroidCpuMetric.Metrics.fromObject(object.metrics);
                    }
                    if (object.threads) {
                        if (!Array.isArray(object.threads))
                            throw TypeError(".perfetto.protos.AndroidCpuMetric.Process.threads: array expected");
                        message.threads = [];
                        for (var i = 0; i < object.threads.length; ++i) {
                            if (typeof object.threads[i] !== "object")
                                throw TypeError(".perfetto.protos.AndroidCpuMetric.Process.threads: object expected");
                            message.threads[i] = $root.perfetto.protos.AndroidCpuMetric.Thread.fromObject(object.threads[i]);
                        }
                    }
                    if (object.core) {
                        if (!Array.isArray(object.core))
                            throw TypeError(".perfetto.protos.AndroidCpuMetric.Process.core: array expected");
                        message.core = [];
                        for (var i = 0; i < object.core.length; ++i) {
                            if (typeof object.core[i] !== "object")
                                throw TypeError(".perfetto.protos.AndroidCpuMetric.Process.core: object expected");
                            message.core[i] = $root.perfetto.protos.AndroidCpuMetric.CoreData.fromObject(object.core[i]);
                        }
                    }
                    if (object.coreType) {
                        if (!Array.isArray(object.coreType))
                            throw TypeError(".perfetto.protos.AndroidCpuMetric.Process.coreType: array expected");
                        message.coreType = [];
                        for (var i = 0; i < object.coreType.length; ++i) {
                            if (typeof object.coreType[i] !== "object")
                                throw TypeError(".perfetto.protos.AndroidCpuMetric.Process.coreType: object expected");
                            message.coreType[i] = $root.perfetto.protos.AndroidCpuMetric.CoreTypeData.fromObject(object.coreType[i]);
                        }
                    }
                    return message;
                };

                /**
                 * Creates a plain object from a Process message. Also converts values to other types if specified.
                 * @function toObject
                 * @memberof perfetto.protos.AndroidCpuMetric.Process
                 * @static
                 * @param {perfetto.protos.AndroidCpuMetric.Process} message Process
                 * @param {$protobuf.IConversionOptions} [options] Conversion options
                 * @returns {Object.<string,*>} Plain object
                 */
                Process.toObject = function toObject(message, options) {
                    if (!options)
                        options = {};
                    var object = {};
                    if (options.arrays || options.defaults) {
                        object.coreType = [];
                        object.threads = [];
                        object.core = [];
                    }
                    if (options.defaults) {
                        object.name = "";
                        object.metrics = null;
                    }
                    if (message.name != null && message.hasOwnProperty("name"))
                        object.name = message.name;
                    if (message.metrics != null && message.hasOwnProperty("metrics"))
                        object.metrics = $root.perfetto.protos.AndroidCpuMetric.Metrics.toObject(message.metrics, options);
                    if (message.coreType && message.coreType.length) {
                        object.coreType = [];
                        for (var j = 0; j < message.coreType.length; ++j)
                            object.coreType[j] = $root.perfetto.protos.AndroidCpuMetric.CoreTypeData.toObject(message.coreType[j], options);
                    }
                    if (message.threads && message.threads.length) {
                        object.threads = [];
                        for (var j = 0; j < message.threads.length; ++j)
                            object.threads[j] = $root.perfetto.protos.AndroidCpuMetric.Thread.toObject(message.threads[j], options);
                    }
                    if (message.core && message.core.length) {
                        object.core = [];
                        for (var j = 0; j < message.core.length; ++j)
                            object.core[j] = $root.perfetto.protos.AndroidCpuMetric.CoreData.toObject(message.core[j], options);
                    }
                    return object;
                };

                /**
                 * Converts this Process to JSON.
                 * @function toJSON
                 * @memberof perfetto.protos.AndroidCpuMetric.Process
                 * @instance
                 * @returns {Object.<string,*>} JSON object
                 */
                Process.prototype.toJSON = function toJSON() {
                    return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
                };

                return Process;
            })();

            return AndroidCpuMetric;
        })();

        protos.AndroidDisplayMetrics = (function() {

            /**
             * Properties of an AndroidDisplayMetrics.
             * @memberof perfetto.protos
             * @interface IAndroidDisplayMetrics
             * @property {number|null} [totalDuplicateFrames] AndroidDisplayMetrics totalDuplicateFrames
             * @property {number|null} [duplicateFramesLogged] AndroidDisplayMetrics duplicateFramesLogged
             * @property {number|null} [totalDpuUnderrunCount] AndroidDisplayMetrics totalDpuUnderrunCount
             * @property {number|null} [refreshRateSwitches] AndroidDisplayMetrics refreshRateSwitches
             * @property {Array.<perfetto.protos.AndroidDisplayMetrics.IRefreshRateStat>|null} [refreshRateStats] AndroidDisplayMetrics refreshRateStats
             */

            /**
             * Constructs a new AndroidDisplayMetrics.
             * @memberof perfetto.protos
             * @classdesc Represents an AndroidDisplayMetrics.
             * @implements IAndroidDisplayMetrics
             * @constructor
             * @param {perfetto.protos.IAndroidDisplayMetrics=} [properties] Properties to set
             */
            function AndroidDisplayMetrics(properties) {
                this.refreshRateStats = [];
                if (properties)
                    for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                        if (properties[keys[i]] != null)
                            this[keys[i]] = properties[keys[i]];
            }

            /**
             * AndroidDisplayMetrics totalDuplicateFrames.
             * @member {number} totalDuplicateFrames
             * @memberof perfetto.protos.AndroidDisplayMetrics
             * @instance
             */
            AndroidDisplayMetrics.prototype.totalDuplicateFrames = 0;

            /**
             * AndroidDisplayMetrics duplicateFramesLogged.
             * @member {number} duplicateFramesLogged
             * @memberof perfetto.protos.AndroidDisplayMetrics
             * @instance
             */
            AndroidDisplayMetrics.prototype.duplicateFramesLogged = 0;

            /**
             * AndroidDisplayMetrics totalDpuUnderrunCount.
             * @member {number} totalDpuUnderrunCount
             * @memberof perfetto.protos.AndroidDisplayMetrics
             * @instance
             */
            AndroidDisplayMetrics.prototype.totalDpuUnderrunCount = 0;

            /**
             * AndroidDisplayMetrics refreshRateSwitches.
             * @member {number} refreshRateSwitches
             * @memberof perfetto.protos.AndroidDisplayMetrics
             * @instance
             */
            AndroidDisplayMetrics.prototype.refreshRateSwitches = 0;

            /**
             * AndroidDisplayMetrics refreshRateStats.
             * @member {Array.<perfetto.protos.AndroidDisplayMetrics.IRefreshRateStat>} refreshRateStats
             * @memberof perfetto.protos.AndroidDisplayMetrics
             * @instance
             */
            AndroidDisplayMetrics.prototype.refreshRateStats = $util.emptyArray;

            /**
             * Creates a new AndroidDisplayMetrics instance using the specified properties.
             * @function create
             * @memberof perfetto.protos.AndroidDisplayMetrics
             * @static
             * @param {perfetto.protos.IAndroidDisplayMetrics=} [properties] Properties to set
             * @returns {perfetto.protos.AndroidDisplayMetrics} AndroidDisplayMetrics instance
             */
            AndroidDisplayMetrics.create = function create(properties) {
                return new AndroidDisplayMetrics(properties);
            };

            /**
             * Encodes the specified AndroidDisplayMetrics message. Does not implicitly {@link perfetto.protos.AndroidDisplayMetrics.verify|verify} messages.
             * @function encode
             * @memberof perfetto.protos.AndroidDisplayMetrics
             * @static
             * @param {perfetto.protos.IAndroidDisplayMetrics} message AndroidDisplayMetrics message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            AndroidDisplayMetrics.encode = function encode(message, writer) {
                if (!writer)
                    writer = $Writer.create();
                if (message.totalDuplicateFrames != null && Object.hasOwnProperty.call(message, "totalDuplicateFrames"))
                    writer.uint32(/* id 1, wireType 0 =*/8).uint32(message.totalDuplicateFrames);
                if (message.duplicateFramesLogged != null && Object.hasOwnProperty.call(message, "duplicateFramesLogged"))
                    writer.uint32(/* id 2, wireType 0 =*/16).uint32(message.duplicateFramesLogged);
                if (message.totalDpuUnderrunCount != null && Object.hasOwnProperty.call(message, "totalDpuUnderrunCount"))
                    writer.uint32(/* id 3, wireType 0 =*/24).uint32(message.totalDpuUnderrunCount);
                if (message.refreshRateSwitches != null && Object.hasOwnProperty.call(message, "refreshRateSwitches"))
                    writer.uint32(/* id 4, wireType 0 =*/32).uint32(message.refreshRateSwitches);
                if (message.refreshRateStats != null && message.refreshRateStats.length)
                    for (var i = 0; i < message.refreshRateStats.length; ++i)
                        $root.perfetto.protos.AndroidDisplayMetrics.RefreshRateStat.encode(message.refreshRateStats[i], writer.uint32(/* id 5, wireType 2 =*/42).fork()).ldelim();
                return writer;
            };

            /**
             * Encodes the specified AndroidDisplayMetrics message, length delimited. Does not implicitly {@link perfetto.protos.AndroidDisplayMetrics.verify|verify} messages.
             * @function encodeDelimited
             * @memberof perfetto.protos.AndroidDisplayMetrics
             * @static
             * @param {perfetto.protos.IAndroidDisplayMetrics} message AndroidDisplayMetrics message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            AndroidDisplayMetrics.encodeDelimited = function encodeDelimited(message, writer) {
                return this.encode(message, writer).ldelim();
            };

            /**
             * Decodes an AndroidDisplayMetrics message from the specified reader or buffer.
             * @function decode
             * @memberof perfetto.protos.AndroidDisplayMetrics
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @param {number} [length] Message length if known beforehand
             * @returns {perfetto.protos.AndroidDisplayMetrics} AndroidDisplayMetrics
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            AndroidDisplayMetrics.decode = function decode(reader, length) {
                if (!(reader instanceof $Reader))
                    reader = $Reader.create(reader);
                var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.AndroidDisplayMetrics();
                while (reader.pos < end) {
                    var tag = reader.uint32();
                    switch (tag >>> 3) {
                    case 1:
                        message.totalDuplicateFrames = reader.uint32();
                        break;
                    case 2:
                        message.duplicateFramesLogged = reader.uint32();
                        break;
                    case 3:
                        message.totalDpuUnderrunCount = reader.uint32();
                        break;
                    case 4:
                        message.refreshRateSwitches = reader.uint32();
                        break;
                    case 5:
                        if (!(message.refreshRateStats && message.refreshRateStats.length))
                            message.refreshRateStats = [];
                        message.refreshRateStats.push($root.perfetto.protos.AndroidDisplayMetrics.RefreshRateStat.decode(reader, reader.uint32()));
                        break;
                    default:
                        reader.skipType(tag & 7);
                        break;
                    }
                }
                return message;
            };

            /**
             * Decodes an AndroidDisplayMetrics message from the specified reader or buffer, length delimited.
             * @function decodeDelimited
             * @memberof perfetto.protos.AndroidDisplayMetrics
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @returns {perfetto.protos.AndroidDisplayMetrics} AndroidDisplayMetrics
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            AndroidDisplayMetrics.decodeDelimited = function decodeDelimited(reader) {
                if (!(reader instanceof $Reader))
                    reader = new $Reader(reader);
                return this.decode(reader, reader.uint32());
            };

            /**
             * Verifies an AndroidDisplayMetrics message.
             * @function verify
             * @memberof perfetto.protos.AndroidDisplayMetrics
             * @static
             * @param {Object.<string,*>} message Plain object to verify
             * @returns {string|null} `null` if valid, otherwise the reason why it is not
             */
            AndroidDisplayMetrics.verify = function verify(message) {
                if (typeof message !== "object" || message === null)
                    return "object expected";
                if (message.totalDuplicateFrames != null && message.hasOwnProperty("totalDuplicateFrames"))
                    if (!$util.isInteger(message.totalDuplicateFrames))
                        return "totalDuplicateFrames: integer expected";
                if (message.duplicateFramesLogged != null && message.hasOwnProperty("duplicateFramesLogged"))
                    if (!$util.isInteger(message.duplicateFramesLogged))
                        return "duplicateFramesLogged: integer expected";
                if (message.totalDpuUnderrunCount != null && message.hasOwnProperty("totalDpuUnderrunCount"))
                    if (!$util.isInteger(message.totalDpuUnderrunCount))
                        return "totalDpuUnderrunCount: integer expected";
                if (message.refreshRateSwitches != null && message.hasOwnProperty("refreshRateSwitches"))
                    if (!$util.isInteger(message.refreshRateSwitches))
                        return "refreshRateSwitches: integer expected";
                if (message.refreshRateStats != null && message.hasOwnProperty("refreshRateStats")) {
                    if (!Array.isArray(message.refreshRateStats))
                        return "refreshRateStats: array expected";
                    for (var i = 0; i < message.refreshRateStats.length; ++i) {
                        var error = $root.perfetto.protos.AndroidDisplayMetrics.RefreshRateStat.verify(message.refreshRateStats[i]);
                        if (error)
                            return "refreshRateStats." + error;
                    }
                }
                return null;
            };

            /**
             * Creates an AndroidDisplayMetrics message from a plain object. Also converts values to their respective internal types.
             * @function fromObject
             * @memberof perfetto.protos.AndroidDisplayMetrics
             * @static
             * @param {Object.<string,*>} object Plain object
             * @returns {perfetto.protos.AndroidDisplayMetrics} AndroidDisplayMetrics
             */
            AndroidDisplayMetrics.fromObject = function fromObject(object) {
                if (object instanceof $root.perfetto.protos.AndroidDisplayMetrics)
                    return object;
                var message = new $root.perfetto.protos.AndroidDisplayMetrics();
                if (object.totalDuplicateFrames != null)
                    message.totalDuplicateFrames = object.totalDuplicateFrames >>> 0;
                if (object.duplicateFramesLogged != null)
                    message.duplicateFramesLogged = object.duplicateFramesLogged >>> 0;
                if (object.totalDpuUnderrunCount != null)
                    message.totalDpuUnderrunCount = object.totalDpuUnderrunCount >>> 0;
                if (object.refreshRateSwitches != null)
                    message.refreshRateSwitches = object.refreshRateSwitches >>> 0;
                if (object.refreshRateStats) {
                    if (!Array.isArray(object.refreshRateStats))
                        throw TypeError(".perfetto.protos.AndroidDisplayMetrics.refreshRateStats: array expected");
                    message.refreshRateStats = [];
                    for (var i = 0; i < object.refreshRateStats.length; ++i) {
                        if (typeof object.refreshRateStats[i] !== "object")
                            throw TypeError(".perfetto.protos.AndroidDisplayMetrics.refreshRateStats: object expected");
                        message.refreshRateStats[i] = $root.perfetto.protos.AndroidDisplayMetrics.RefreshRateStat.fromObject(object.refreshRateStats[i]);
                    }
                }
                return message;
            };

            /**
             * Creates a plain object from an AndroidDisplayMetrics message. Also converts values to other types if specified.
             * @function toObject
             * @memberof perfetto.protos.AndroidDisplayMetrics
             * @static
             * @param {perfetto.protos.AndroidDisplayMetrics} message AndroidDisplayMetrics
             * @param {$protobuf.IConversionOptions} [options] Conversion options
             * @returns {Object.<string,*>} Plain object
             */
            AndroidDisplayMetrics.toObject = function toObject(message, options) {
                if (!options)
                    options = {};
                var object = {};
                if (options.arrays || options.defaults)
                    object.refreshRateStats = [];
                if (options.defaults) {
                    object.totalDuplicateFrames = 0;
                    object.duplicateFramesLogged = 0;
                    object.totalDpuUnderrunCount = 0;
                    object.refreshRateSwitches = 0;
                }
                if (message.totalDuplicateFrames != null && message.hasOwnProperty("totalDuplicateFrames"))
                    object.totalDuplicateFrames = message.totalDuplicateFrames;
                if (message.duplicateFramesLogged != null && message.hasOwnProperty("duplicateFramesLogged"))
                    object.duplicateFramesLogged = message.duplicateFramesLogged;
                if (message.totalDpuUnderrunCount != null && message.hasOwnProperty("totalDpuUnderrunCount"))
                    object.totalDpuUnderrunCount = message.totalDpuUnderrunCount;
                if (message.refreshRateSwitches != null && message.hasOwnProperty("refreshRateSwitches"))
                    object.refreshRateSwitches = message.refreshRateSwitches;
                if (message.refreshRateStats && message.refreshRateStats.length) {
                    object.refreshRateStats = [];
                    for (var j = 0; j < message.refreshRateStats.length; ++j)
                        object.refreshRateStats[j] = $root.perfetto.protos.AndroidDisplayMetrics.RefreshRateStat.toObject(message.refreshRateStats[j], options);
                }
                return object;
            };

            /**
             * Converts this AndroidDisplayMetrics to JSON.
             * @function toJSON
             * @memberof perfetto.protos.AndroidDisplayMetrics
             * @instance
             * @returns {Object.<string,*>} JSON object
             */
            AndroidDisplayMetrics.prototype.toJSON = function toJSON() {
                return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
            };

            AndroidDisplayMetrics.RefreshRateStat = (function() {

                /**
                 * Properties of a RefreshRateStat.
                 * @memberof perfetto.protos.AndroidDisplayMetrics
                 * @interface IRefreshRateStat
                 * @property {number|null} [refreshRateFps] RefreshRateStat refreshRateFps
                 * @property {number|null} [count] RefreshRateStat count
                 * @property {number|null} [totalDurMs] RefreshRateStat totalDurMs
                 * @property {number|null} [avgDurMs] RefreshRateStat avgDurMs
                 */

                /**
                 * Constructs a new RefreshRateStat.
                 * @memberof perfetto.protos.AndroidDisplayMetrics
                 * @classdesc Represents a RefreshRateStat.
                 * @implements IRefreshRateStat
                 * @constructor
                 * @param {perfetto.protos.AndroidDisplayMetrics.IRefreshRateStat=} [properties] Properties to set
                 */
                function RefreshRateStat(properties) {
                    if (properties)
                        for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                            if (properties[keys[i]] != null)
                                this[keys[i]] = properties[keys[i]];
                }

                /**
                 * RefreshRateStat refreshRateFps.
                 * @member {number} refreshRateFps
                 * @memberof perfetto.protos.AndroidDisplayMetrics.RefreshRateStat
                 * @instance
                 */
                RefreshRateStat.prototype.refreshRateFps = 0;

                /**
                 * RefreshRateStat count.
                 * @member {number} count
                 * @memberof perfetto.protos.AndroidDisplayMetrics.RefreshRateStat
                 * @instance
                 */
                RefreshRateStat.prototype.count = 0;

                /**
                 * RefreshRateStat totalDurMs.
                 * @member {number} totalDurMs
                 * @memberof perfetto.protos.AndroidDisplayMetrics.RefreshRateStat
                 * @instance
                 */
                RefreshRateStat.prototype.totalDurMs = 0;

                /**
                 * RefreshRateStat avgDurMs.
                 * @member {number} avgDurMs
                 * @memberof perfetto.protos.AndroidDisplayMetrics.RefreshRateStat
                 * @instance
                 */
                RefreshRateStat.prototype.avgDurMs = 0;

                /**
                 * Creates a new RefreshRateStat instance using the specified properties.
                 * @function create
                 * @memberof perfetto.protos.AndroidDisplayMetrics.RefreshRateStat
                 * @static
                 * @param {perfetto.protos.AndroidDisplayMetrics.IRefreshRateStat=} [properties] Properties to set
                 * @returns {perfetto.protos.AndroidDisplayMetrics.RefreshRateStat} RefreshRateStat instance
                 */
                RefreshRateStat.create = function create(properties) {
                    return new RefreshRateStat(properties);
                };

                /**
                 * Encodes the specified RefreshRateStat message. Does not implicitly {@link perfetto.protos.AndroidDisplayMetrics.RefreshRateStat.verify|verify} messages.
                 * @function encode
                 * @memberof perfetto.protos.AndroidDisplayMetrics.RefreshRateStat
                 * @static
                 * @param {perfetto.protos.AndroidDisplayMetrics.IRefreshRateStat} message RefreshRateStat message or plain object to encode
                 * @param {$protobuf.Writer} [writer] Writer to encode to
                 * @returns {$protobuf.Writer} Writer
                 */
                RefreshRateStat.encode = function encode(message, writer) {
                    if (!writer)
                        writer = $Writer.create();
                    if (message.refreshRateFps != null && Object.hasOwnProperty.call(message, "refreshRateFps"))
                        writer.uint32(/* id 1, wireType 0 =*/8).uint32(message.refreshRateFps);
                    if (message.count != null && Object.hasOwnProperty.call(message, "count"))
                        writer.uint32(/* id 2, wireType 0 =*/16).uint32(message.count);
                    if (message.totalDurMs != null && Object.hasOwnProperty.call(message, "totalDurMs"))
                        writer.uint32(/* id 3, wireType 1 =*/25).double(message.totalDurMs);
                    if (message.avgDurMs != null && Object.hasOwnProperty.call(message, "avgDurMs"))
                        writer.uint32(/* id 4, wireType 1 =*/33).double(message.avgDurMs);
                    return writer;
                };

                /**
                 * Encodes the specified RefreshRateStat message, length delimited. Does not implicitly {@link perfetto.protos.AndroidDisplayMetrics.RefreshRateStat.verify|verify} messages.
                 * @function encodeDelimited
                 * @memberof perfetto.protos.AndroidDisplayMetrics.RefreshRateStat
                 * @static
                 * @param {perfetto.protos.AndroidDisplayMetrics.IRefreshRateStat} message RefreshRateStat message or plain object to encode
                 * @param {$protobuf.Writer} [writer] Writer to encode to
                 * @returns {$protobuf.Writer} Writer
                 */
                RefreshRateStat.encodeDelimited = function encodeDelimited(message, writer) {
                    return this.encode(message, writer).ldelim();
                };

                /**
                 * Decodes a RefreshRateStat message from the specified reader or buffer.
                 * @function decode
                 * @memberof perfetto.protos.AndroidDisplayMetrics.RefreshRateStat
                 * @static
                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                 * @param {number} [length] Message length if known beforehand
                 * @returns {perfetto.protos.AndroidDisplayMetrics.RefreshRateStat} RefreshRateStat
                 * @throws {Error} If the payload is not a reader or valid buffer
                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
                 */
                RefreshRateStat.decode = function decode(reader, length) {
                    if (!(reader instanceof $Reader))
                        reader = $Reader.create(reader);
                    var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.AndroidDisplayMetrics.RefreshRateStat();
                    while (reader.pos < end) {
                        var tag = reader.uint32();
                        switch (tag >>> 3) {
                        case 1:
                            message.refreshRateFps = reader.uint32();
                            break;
                        case 2:
                            message.count = reader.uint32();
                            break;
                        case 3:
                            message.totalDurMs = reader.double();
                            break;
                        case 4:
                            message.avgDurMs = reader.double();
                            break;
                        default:
                            reader.skipType(tag & 7);
                            break;
                        }
                    }
                    return message;
                };

                /**
                 * Decodes a RefreshRateStat message from the specified reader or buffer, length delimited.
                 * @function decodeDelimited
                 * @memberof perfetto.protos.AndroidDisplayMetrics.RefreshRateStat
                 * @static
                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                 * @returns {perfetto.protos.AndroidDisplayMetrics.RefreshRateStat} RefreshRateStat
                 * @throws {Error} If the payload is not a reader or valid buffer
                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
                 */
                RefreshRateStat.decodeDelimited = function decodeDelimited(reader) {
                    if (!(reader instanceof $Reader))
                        reader = new $Reader(reader);
                    return this.decode(reader, reader.uint32());
                };

                /**
                 * Verifies a RefreshRateStat message.
                 * @function verify
                 * @memberof perfetto.protos.AndroidDisplayMetrics.RefreshRateStat
                 * @static
                 * @param {Object.<string,*>} message Plain object to verify
                 * @returns {string|null} `null` if valid, otherwise the reason why it is not
                 */
                RefreshRateStat.verify = function verify(message) {
                    if (typeof message !== "object" || message === null)
                        return "object expected";
                    if (message.refreshRateFps != null && message.hasOwnProperty("refreshRateFps"))
                        if (!$util.isInteger(message.refreshRateFps))
                            return "refreshRateFps: integer expected";
                    if (message.count != null && message.hasOwnProperty("count"))
                        if (!$util.isInteger(message.count))
                            return "count: integer expected";
                    if (message.totalDurMs != null && message.hasOwnProperty("totalDurMs"))
                        if (typeof message.totalDurMs !== "number")
                            return "totalDurMs: number expected";
                    if (message.avgDurMs != null && message.hasOwnProperty("avgDurMs"))
                        if (typeof message.avgDurMs !== "number")
                            return "avgDurMs: number expected";
                    return null;
                };

                /**
                 * Creates a RefreshRateStat message from a plain object. Also converts values to their respective internal types.
                 * @function fromObject
                 * @memberof perfetto.protos.AndroidDisplayMetrics.RefreshRateStat
                 * @static
                 * @param {Object.<string,*>} object Plain object
                 * @returns {perfetto.protos.AndroidDisplayMetrics.RefreshRateStat} RefreshRateStat
                 */
                RefreshRateStat.fromObject = function fromObject(object) {
                    if (object instanceof $root.perfetto.protos.AndroidDisplayMetrics.RefreshRateStat)
                        return object;
                    var message = new $root.perfetto.protos.AndroidDisplayMetrics.RefreshRateStat();
                    if (object.refreshRateFps != null)
                        message.refreshRateFps = object.refreshRateFps >>> 0;
                    if (object.count != null)
                        message.count = object.count >>> 0;
                    if (object.totalDurMs != null)
                        message.totalDurMs = Number(object.totalDurMs);
                    if (object.avgDurMs != null)
                        message.avgDurMs = Number(object.avgDurMs);
                    return message;
                };

                /**
                 * Creates a plain object from a RefreshRateStat message. Also converts values to other types if specified.
                 * @function toObject
                 * @memberof perfetto.protos.AndroidDisplayMetrics.RefreshRateStat
                 * @static
                 * @param {perfetto.protos.AndroidDisplayMetrics.RefreshRateStat} message RefreshRateStat
                 * @param {$protobuf.IConversionOptions} [options] Conversion options
                 * @returns {Object.<string,*>} Plain object
                 */
                RefreshRateStat.toObject = function toObject(message, options) {
                    if (!options)
                        options = {};
                    var object = {};
                    if (options.defaults) {
                        object.refreshRateFps = 0;
                        object.count = 0;
                        object.totalDurMs = 0;
                        object.avgDurMs = 0;
                    }
                    if (message.refreshRateFps != null && message.hasOwnProperty("refreshRateFps"))
                        object.refreshRateFps = message.refreshRateFps;
                    if (message.count != null && message.hasOwnProperty("count"))
                        object.count = message.count;
                    if (message.totalDurMs != null && message.hasOwnProperty("totalDurMs"))
                        object.totalDurMs = options.json && !isFinite(message.totalDurMs) ? String(message.totalDurMs) : message.totalDurMs;
                    if (message.avgDurMs != null && message.hasOwnProperty("avgDurMs"))
                        object.avgDurMs = options.json && !isFinite(message.avgDurMs) ? String(message.avgDurMs) : message.avgDurMs;
                    return object;
                };

                /**
                 * Converts this RefreshRateStat to JSON.
                 * @function toJSON
                 * @memberof perfetto.protos.AndroidDisplayMetrics.RefreshRateStat
                 * @instance
                 * @returns {Object.<string,*>} JSON object
                 */
                RefreshRateStat.prototype.toJSON = function toJSON() {
                    return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
                };

                return RefreshRateStat;
            })();

            return AndroidDisplayMetrics;
        })();

        protos.AndroidDmaHeapMetric = (function() {

            /**
             * Properties of an AndroidDmaHeapMetric.
             * @memberof perfetto.protos
             * @interface IAndroidDmaHeapMetric
             * @property {number|null} [avgSizeBytes] AndroidDmaHeapMetric avgSizeBytes
             * @property {number|null} [minSizeBytes] AndroidDmaHeapMetric minSizeBytes
             * @property {number|null} [maxSizeBytes] AndroidDmaHeapMetric maxSizeBytes
             * @property {number|null} [totalAllocSizeBytes] AndroidDmaHeapMetric totalAllocSizeBytes
             */

            /**
             * Constructs a new AndroidDmaHeapMetric.
             * @memberof perfetto.protos
             * @classdesc Represents an AndroidDmaHeapMetric.
             * @implements IAndroidDmaHeapMetric
             * @constructor
             * @param {perfetto.protos.IAndroidDmaHeapMetric=} [properties] Properties to set
             */
            function AndroidDmaHeapMetric(properties) {
                if (properties)
                    for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                        if (properties[keys[i]] != null)
                            this[keys[i]] = properties[keys[i]];
            }

            /**
             * AndroidDmaHeapMetric avgSizeBytes.
             * @member {number} avgSizeBytes
             * @memberof perfetto.protos.AndroidDmaHeapMetric
             * @instance
             */
            AndroidDmaHeapMetric.prototype.avgSizeBytes = 0;

            /**
             * AndroidDmaHeapMetric minSizeBytes.
             * @member {number} minSizeBytes
             * @memberof perfetto.protos.AndroidDmaHeapMetric
             * @instance
             */
            AndroidDmaHeapMetric.prototype.minSizeBytes = 0;

            /**
             * AndroidDmaHeapMetric maxSizeBytes.
             * @member {number} maxSizeBytes
             * @memberof perfetto.protos.AndroidDmaHeapMetric
             * @instance
             */
            AndroidDmaHeapMetric.prototype.maxSizeBytes = 0;

            /**
             * AndroidDmaHeapMetric totalAllocSizeBytes.
             * @member {number} totalAllocSizeBytes
             * @memberof perfetto.protos.AndroidDmaHeapMetric
             * @instance
             */
            AndroidDmaHeapMetric.prototype.totalAllocSizeBytes = 0;

            /**
             * Creates a new AndroidDmaHeapMetric instance using the specified properties.
             * @function create
             * @memberof perfetto.protos.AndroidDmaHeapMetric
             * @static
             * @param {perfetto.protos.IAndroidDmaHeapMetric=} [properties] Properties to set
             * @returns {perfetto.protos.AndroidDmaHeapMetric} AndroidDmaHeapMetric instance
             */
            AndroidDmaHeapMetric.create = function create(properties) {
                return new AndroidDmaHeapMetric(properties);
            };

            /**
             * Encodes the specified AndroidDmaHeapMetric message. Does not implicitly {@link perfetto.protos.AndroidDmaHeapMetric.verify|verify} messages.
             * @function encode
             * @memberof perfetto.protos.AndroidDmaHeapMetric
             * @static
             * @param {perfetto.protos.IAndroidDmaHeapMetric} message AndroidDmaHeapMetric message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            AndroidDmaHeapMetric.encode = function encode(message, writer) {
                if (!writer)
                    writer = $Writer.create();
                if (message.avgSizeBytes != null && Object.hasOwnProperty.call(message, "avgSizeBytes"))
                    writer.uint32(/* id 1, wireType 1 =*/9).double(message.avgSizeBytes);
                if (message.minSizeBytes != null && Object.hasOwnProperty.call(message, "minSizeBytes"))
                    writer.uint32(/* id 2, wireType 1 =*/17).double(message.minSizeBytes);
                if (message.maxSizeBytes != null && Object.hasOwnProperty.call(message, "maxSizeBytes"))
                    writer.uint32(/* id 3, wireType 1 =*/25).double(message.maxSizeBytes);
                if (message.totalAllocSizeBytes != null && Object.hasOwnProperty.call(message, "totalAllocSizeBytes"))
                    writer.uint32(/* id 4, wireType 1 =*/33).double(message.totalAllocSizeBytes);
                return writer;
            };

            /**
             * Encodes the specified AndroidDmaHeapMetric message, length delimited. Does not implicitly {@link perfetto.protos.AndroidDmaHeapMetric.verify|verify} messages.
             * @function encodeDelimited
             * @memberof perfetto.protos.AndroidDmaHeapMetric
             * @static
             * @param {perfetto.protos.IAndroidDmaHeapMetric} message AndroidDmaHeapMetric message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            AndroidDmaHeapMetric.encodeDelimited = function encodeDelimited(message, writer) {
                return this.encode(message, writer).ldelim();
            };

            /**
             * Decodes an AndroidDmaHeapMetric message from the specified reader or buffer.
             * @function decode
             * @memberof perfetto.protos.AndroidDmaHeapMetric
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @param {number} [length] Message length if known beforehand
             * @returns {perfetto.protos.AndroidDmaHeapMetric} AndroidDmaHeapMetric
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            AndroidDmaHeapMetric.decode = function decode(reader, length) {
                if (!(reader instanceof $Reader))
                    reader = $Reader.create(reader);
                var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.AndroidDmaHeapMetric();
                while (reader.pos < end) {
                    var tag = reader.uint32();
                    switch (tag >>> 3) {
                    case 1:
                        message.avgSizeBytes = reader.double();
                        break;
                    case 2:
                        message.minSizeBytes = reader.double();
                        break;
                    case 3:
                        message.maxSizeBytes = reader.double();
                        break;
                    case 4:
                        message.totalAllocSizeBytes = reader.double();
                        break;
                    default:
                        reader.skipType(tag & 7);
                        break;
                    }
                }
                return message;
            };

            /**
             * Decodes an AndroidDmaHeapMetric message from the specified reader or buffer, length delimited.
             * @function decodeDelimited
             * @memberof perfetto.protos.AndroidDmaHeapMetric
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @returns {perfetto.protos.AndroidDmaHeapMetric} AndroidDmaHeapMetric
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            AndroidDmaHeapMetric.decodeDelimited = function decodeDelimited(reader) {
                if (!(reader instanceof $Reader))
                    reader = new $Reader(reader);
                return this.decode(reader, reader.uint32());
            };

            /**
             * Verifies an AndroidDmaHeapMetric message.
             * @function verify
             * @memberof perfetto.protos.AndroidDmaHeapMetric
             * @static
             * @param {Object.<string,*>} message Plain object to verify
             * @returns {string|null} `null` if valid, otherwise the reason why it is not
             */
            AndroidDmaHeapMetric.verify = function verify(message) {
                if (typeof message !== "object" || message === null)
                    return "object expected";
                if (message.avgSizeBytes != null && message.hasOwnProperty("avgSizeBytes"))
                    if (typeof message.avgSizeBytes !== "number")
                        return "avgSizeBytes: number expected";
                if (message.minSizeBytes != null && message.hasOwnProperty("minSizeBytes"))
                    if (typeof message.minSizeBytes !== "number")
                        return "minSizeBytes: number expected";
                if (message.maxSizeBytes != null && message.hasOwnProperty("maxSizeBytes"))
                    if (typeof message.maxSizeBytes !== "number")
                        return "maxSizeBytes: number expected";
                if (message.totalAllocSizeBytes != null && message.hasOwnProperty("totalAllocSizeBytes"))
                    if (typeof message.totalAllocSizeBytes !== "number")
                        return "totalAllocSizeBytes: number expected";
                return null;
            };

            /**
             * Creates an AndroidDmaHeapMetric message from a plain object. Also converts values to their respective internal types.
             * @function fromObject
             * @memberof perfetto.protos.AndroidDmaHeapMetric
             * @static
             * @param {Object.<string,*>} object Plain object
             * @returns {perfetto.protos.AndroidDmaHeapMetric} AndroidDmaHeapMetric
             */
            AndroidDmaHeapMetric.fromObject = function fromObject(object) {
                if (object instanceof $root.perfetto.protos.AndroidDmaHeapMetric)
                    return object;
                var message = new $root.perfetto.protos.AndroidDmaHeapMetric();
                if (object.avgSizeBytes != null)
                    message.avgSizeBytes = Number(object.avgSizeBytes);
                if (object.minSizeBytes != null)
                    message.minSizeBytes = Number(object.minSizeBytes);
                if (object.maxSizeBytes != null)
                    message.maxSizeBytes = Number(object.maxSizeBytes);
                if (object.totalAllocSizeBytes != null)
                    message.totalAllocSizeBytes = Number(object.totalAllocSizeBytes);
                return message;
            };

            /**
             * Creates a plain object from an AndroidDmaHeapMetric message. Also converts values to other types if specified.
             * @function toObject
             * @memberof perfetto.protos.AndroidDmaHeapMetric
             * @static
             * @param {perfetto.protos.AndroidDmaHeapMetric} message AndroidDmaHeapMetric
             * @param {$protobuf.IConversionOptions} [options] Conversion options
             * @returns {Object.<string,*>} Plain object
             */
            AndroidDmaHeapMetric.toObject = function toObject(message, options) {
                if (!options)
                    options = {};
                var object = {};
                if (options.defaults) {
                    object.avgSizeBytes = 0;
                    object.minSizeBytes = 0;
                    object.maxSizeBytes = 0;
                    object.totalAllocSizeBytes = 0;
                }
                if (message.avgSizeBytes != null && message.hasOwnProperty("avgSizeBytes"))
                    object.avgSizeBytes = options.json && !isFinite(message.avgSizeBytes) ? String(message.avgSizeBytes) : message.avgSizeBytes;
                if (message.minSizeBytes != null && message.hasOwnProperty("minSizeBytes"))
                    object.minSizeBytes = options.json && !isFinite(message.minSizeBytes) ? String(message.minSizeBytes) : message.minSizeBytes;
                if (message.maxSizeBytes != null && message.hasOwnProperty("maxSizeBytes"))
                    object.maxSizeBytes = options.json && !isFinite(message.maxSizeBytes) ? String(message.maxSizeBytes) : message.maxSizeBytes;
                if (message.totalAllocSizeBytes != null && message.hasOwnProperty("totalAllocSizeBytes"))
                    object.totalAllocSizeBytes = options.json && !isFinite(message.totalAllocSizeBytes) ? String(message.totalAllocSizeBytes) : message.totalAllocSizeBytes;
                return object;
            };

            /**
             * Converts this AndroidDmaHeapMetric to JSON.
             * @function toJSON
             * @memberof perfetto.protos.AndroidDmaHeapMetric
             * @instance
             * @returns {Object.<string,*>} JSON object
             */
            AndroidDmaHeapMetric.prototype.toJSON = function toJSON() {
                return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
            };

            return AndroidDmaHeapMetric;
        })();

        protos.AndroidFastrpcMetric = (function() {

            /**
             * Properties of an AndroidFastrpcMetric.
             * @memberof perfetto.protos
             * @interface IAndroidFastrpcMetric
             * @property {Array.<perfetto.protos.AndroidFastrpcMetric.ISubsystem>|null} [subsystem] AndroidFastrpcMetric subsystem
             */

            /**
             * Constructs a new AndroidFastrpcMetric.
             * @memberof perfetto.protos
             * @classdesc Represents an AndroidFastrpcMetric.
             * @implements IAndroidFastrpcMetric
             * @constructor
             * @param {perfetto.protos.IAndroidFastrpcMetric=} [properties] Properties to set
             */
            function AndroidFastrpcMetric(properties) {
                this.subsystem = [];
                if (properties)
                    for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                        if (properties[keys[i]] != null)
                            this[keys[i]] = properties[keys[i]];
            }

            /**
             * AndroidFastrpcMetric subsystem.
             * @member {Array.<perfetto.protos.AndroidFastrpcMetric.ISubsystem>} subsystem
             * @memberof perfetto.protos.AndroidFastrpcMetric
             * @instance
             */
            AndroidFastrpcMetric.prototype.subsystem = $util.emptyArray;

            /**
             * Creates a new AndroidFastrpcMetric instance using the specified properties.
             * @function create
             * @memberof perfetto.protos.AndroidFastrpcMetric
             * @static
             * @param {perfetto.protos.IAndroidFastrpcMetric=} [properties] Properties to set
             * @returns {perfetto.protos.AndroidFastrpcMetric} AndroidFastrpcMetric instance
             */
            AndroidFastrpcMetric.create = function create(properties) {
                return new AndroidFastrpcMetric(properties);
            };

            /**
             * Encodes the specified AndroidFastrpcMetric message. Does not implicitly {@link perfetto.protos.AndroidFastrpcMetric.verify|verify} messages.
             * @function encode
             * @memberof perfetto.protos.AndroidFastrpcMetric
             * @static
             * @param {perfetto.protos.IAndroidFastrpcMetric} message AndroidFastrpcMetric message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            AndroidFastrpcMetric.encode = function encode(message, writer) {
                if (!writer)
                    writer = $Writer.create();
                if (message.subsystem != null && message.subsystem.length)
                    for (var i = 0; i < message.subsystem.length; ++i)
                        $root.perfetto.protos.AndroidFastrpcMetric.Subsystem.encode(message.subsystem[i], writer.uint32(/* id 1, wireType 2 =*/10).fork()).ldelim();
                return writer;
            };

            /**
             * Encodes the specified AndroidFastrpcMetric message, length delimited. Does not implicitly {@link perfetto.protos.AndroidFastrpcMetric.verify|verify} messages.
             * @function encodeDelimited
             * @memberof perfetto.protos.AndroidFastrpcMetric
             * @static
             * @param {perfetto.protos.IAndroidFastrpcMetric} message AndroidFastrpcMetric message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            AndroidFastrpcMetric.encodeDelimited = function encodeDelimited(message, writer) {
                return this.encode(message, writer).ldelim();
            };

            /**
             * Decodes an AndroidFastrpcMetric message from the specified reader or buffer.
             * @function decode
             * @memberof perfetto.protos.AndroidFastrpcMetric
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @param {number} [length] Message length if known beforehand
             * @returns {perfetto.protos.AndroidFastrpcMetric} AndroidFastrpcMetric
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            AndroidFastrpcMetric.decode = function decode(reader, length) {
                if (!(reader instanceof $Reader))
                    reader = $Reader.create(reader);
                var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.AndroidFastrpcMetric();
                while (reader.pos < end) {
                    var tag = reader.uint32();
                    switch (tag >>> 3) {
                    case 1:
                        if (!(message.subsystem && message.subsystem.length))
                            message.subsystem = [];
                        message.subsystem.push($root.perfetto.protos.AndroidFastrpcMetric.Subsystem.decode(reader, reader.uint32()));
                        break;
                    default:
                        reader.skipType(tag & 7);
                        break;
                    }
                }
                return message;
            };

            /**
             * Decodes an AndroidFastrpcMetric message from the specified reader or buffer, length delimited.
             * @function decodeDelimited
             * @memberof perfetto.protos.AndroidFastrpcMetric
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @returns {perfetto.protos.AndroidFastrpcMetric} AndroidFastrpcMetric
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            AndroidFastrpcMetric.decodeDelimited = function decodeDelimited(reader) {
                if (!(reader instanceof $Reader))
                    reader = new $Reader(reader);
                return this.decode(reader, reader.uint32());
            };

            /**
             * Verifies an AndroidFastrpcMetric message.
             * @function verify
             * @memberof perfetto.protos.AndroidFastrpcMetric
             * @static
             * @param {Object.<string,*>} message Plain object to verify
             * @returns {string|null} `null` if valid, otherwise the reason why it is not
             */
            AndroidFastrpcMetric.verify = function verify(message) {
                if (typeof message !== "object" || message === null)
                    return "object expected";
                if (message.subsystem != null && message.hasOwnProperty("subsystem")) {
                    if (!Array.isArray(message.subsystem))
                        return "subsystem: array expected";
                    for (var i = 0; i < message.subsystem.length; ++i) {
                        var error = $root.perfetto.protos.AndroidFastrpcMetric.Subsystem.verify(message.subsystem[i]);
                        if (error)
                            return "subsystem." + error;
                    }
                }
                return null;
            };

            /**
             * Creates an AndroidFastrpcMetric message from a plain object. Also converts values to their respective internal types.
             * @function fromObject
             * @memberof perfetto.protos.AndroidFastrpcMetric
             * @static
             * @param {Object.<string,*>} object Plain object
             * @returns {perfetto.protos.AndroidFastrpcMetric} AndroidFastrpcMetric
             */
            AndroidFastrpcMetric.fromObject = function fromObject(object) {
                if (object instanceof $root.perfetto.protos.AndroidFastrpcMetric)
                    return object;
                var message = new $root.perfetto.protos.AndroidFastrpcMetric();
                if (object.subsystem) {
                    if (!Array.isArray(object.subsystem))
                        throw TypeError(".perfetto.protos.AndroidFastrpcMetric.subsystem: array expected");
                    message.subsystem = [];
                    for (var i = 0; i < object.subsystem.length; ++i) {
                        if (typeof object.subsystem[i] !== "object")
                            throw TypeError(".perfetto.protos.AndroidFastrpcMetric.subsystem: object expected");
                        message.subsystem[i] = $root.perfetto.protos.AndroidFastrpcMetric.Subsystem.fromObject(object.subsystem[i]);
                    }
                }
                return message;
            };

            /**
             * Creates a plain object from an AndroidFastrpcMetric message. Also converts values to other types if specified.
             * @function toObject
             * @memberof perfetto.protos.AndroidFastrpcMetric
             * @static
             * @param {perfetto.protos.AndroidFastrpcMetric} message AndroidFastrpcMetric
             * @param {$protobuf.IConversionOptions} [options] Conversion options
             * @returns {Object.<string,*>} Plain object
             */
            AndroidFastrpcMetric.toObject = function toObject(message, options) {
                if (!options)
                    options = {};
                var object = {};
                if (options.arrays || options.defaults)
                    object.subsystem = [];
                if (message.subsystem && message.subsystem.length) {
                    object.subsystem = [];
                    for (var j = 0; j < message.subsystem.length; ++j)
                        object.subsystem[j] = $root.perfetto.protos.AndroidFastrpcMetric.Subsystem.toObject(message.subsystem[j], options);
                }
                return object;
            };

            /**
             * Converts this AndroidFastrpcMetric to JSON.
             * @function toJSON
             * @memberof perfetto.protos.AndroidFastrpcMetric
             * @instance
             * @returns {Object.<string,*>} JSON object
             */
            AndroidFastrpcMetric.prototype.toJSON = function toJSON() {
                return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
            };

            AndroidFastrpcMetric.Subsystem = (function() {

                /**
                 * Properties of a Subsystem.
                 * @memberof perfetto.protos.AndroidFastrpcMetric
                 * @interface ISubsystem
                 * @property {string|null} [name] Subsystem name
                 * @property {number|null} [avgSizeBytes] Subsystem avgSizeBytes
                 * @property {number|null} [minSizeBytes] Subsystem minSizeBytes
                 * @property {number|null} [maxSizeBytes] Subsystem maxSizeBytes
                 * @property {number|null} [totalAllocSizeBytes] Subsystem totalAllocSizeBytes
                 */

                /**
                 * Constructs a new Subsystem.
                 * @memberof perfetto.protos.AndroidFastrpcMetric
                 * @classdesc Represents a Subsystem.
                 * @implements ISubsystem
                 * @constructor
                 * @param {perfetto.protos.AndroidFastrpcMetric.ISubsystem=} [properties] Properties to set
                 */
                function Subsystem(properties) {
                    if (properties)
                        for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                            if (properties[keys[i]] != null)
                                this[keys[i]] = properties[keys[i]];
                }

                /**
                 * Subsystem name.
                 * @member {string} name
                 * @memberof perfetto.protos.AndroidFastrpcMetric.Subsystem
                 * @instance
                 */
                Subsystem.prototype.name = "";

                /**
                 * Subsystem avgSizeBytes.
                 * @member {number} avgSizeBytes
                 * @memberof perfetto.protos.AndroidFastrpcMetric.Subsystem
                 * @instance
                 */
                Subsystem.prototype.avgSizeBytes = 0;

                /**
                 * Subsystem minSizeBytes.
                 * @member {number} minSizeBytes
                 * @memberof perfetto.protos.AndroidFastrpcMetric.Subsystem
                 * @instance
                 */
                Subsystem.prototype.minSizeBytes = 0;

                /**
                 * Subsystem maxSizeBytes.
                 * @member {number} maxSizeBytes
                 * @memberof perfetto.protos.AndroidFastrpcMetric.Subsystem
                 * @instance
                 */
                Subsystem.prototype.maxSizeBytes = 0;

                /**
                 * Subsystem totalAllocSizeBytes.
                 * @member {number} totalAllocSizeBytes
                 * @memberof perfetto.protos.AndroidFastrpcMetric.Subsystem
                 * @instance
                 */
                Subsystem.prototype.totalAllocSizeBytes = 0;

                /**
                 * Creates a new Subsystem instance using the specified properties.
                 * @function create
                 * @memberof perfetto.protos.AndroidFastrpcMetric.Subsystem
                 * @static
                 * @param {perfetto.protos.AndroidFastrpcMetric.ISubsystem=} [properties] Properties to set
                 * @returns {perfetto.protos.AndroidFastrpcMetric.Subsystem} Subsystem instance
                 */
                Subsystem.create = function create(properties) {
                    return new Subsystem(properties);
                };

                /**
                 * Encodes the specified Subsystem message. Does not implicitly {@link perfetto.protos.AndroidFastrpcMetric.Subsystem.verify|verify} messages.
                 * @function encode
                 * @memberof perfetto.protos.AndroidFastrpcMetric.Subsystem
                 * @static
                 * @param {perfetto.protos.AndroidFastrpcMetric.ISubsystem} message Subsystem message or plain object to encode
                 * @param {$protobuf.Writer} [writer] Writer to encode to
                 * @returns {$protobuf.Writer} Writer
                 */
                Subsystem.encode = function encode(message, writer) {
                    if (!writer)
                        writer = $Writer.create();
                    if (message.name != null && Object.hasOwnProperty.call(message, "name"))
                        writer.uint32(/* id 1, wireType 2 =*/10).string(message.name);
                    if (message.avgSizeBytes != null && Object.hasOwnProperty.call(message, "avgSizeBytes"))
                        writer.uint32(/* id 2, wireType 1 =*/17).double(message.avgSizeBytes);
                    if (message.minSizeBytes != null && Object.hasOwnProperty.call(message, "minSizeBytes"))
                        writer.uint32(/* id 3, wireType 1 =*/25).double(message.minSizeBytes);
                    if (message.maxSizeBytes != null && Object.hasOwnProperty.call(message, "maxSizeBytes"))
                        writer.uint32(/* id 4, wireType 1 =*/33).double(message.maxSizeBytes);
                    if (message.totalAllocSizeBytes != null && Object.hasOwnProperty.call(message, "totalAllocSizeBytes"))
                        writer.uint32(/* id 5, wireType 1 =*/41).double(message.totalAllocSizeBytes);
                    return writer;
                };

                /**
                 * Encodes the specified Subsystem message, length delimited. Does not implicitly {@link perfetto.protos.AndroidFastrpcMetric.Subsystem.verify|verify} messages.
                 * @function encodeDelimited
                 * @memberof perfetto.protos.AndroidFastrpcMetric.Subsystem
                 * @static
                 * @param {perfetto.protos.AndroidFastrpcMetric.ISubsystem} message Subsystem message or plain object to encode
                 * @param {$protobuf.Writer} [writer] Writer to encode to
                 * @returns {$protobuf.Writer} Writer
                 */
                Subsystem.encodeDelimited = function encodeDelimited(message, writer) {
                    return this.encode(message, writer).ldelim();
                };

                /**
                 * Decodes a Subsystem message from the specified reader or buffer.
                 * @function decode
                 * @memberof perfetto.protos.AndroidFastrpcMetric.Subsystem
                 * @static
                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                 * @param {number} [length] Message length if known beforehand
                 * @returns {perfetto.protos.AndroidFastrpcMetric.Subsystem} Subsystem
                 * @throws {Error} If the payload is not a reader or valid buffer
                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
                 */
                Subsystem.decode = function decode(reader, length) {
                    if (!(reader instanceof $Reader))
                        reader = $Reader.create(reader);
                    var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.AndroidFastrpcMetric.Subsystem();
                    while (reader.pos < end) {
                        var tag = reader.uint32();
                        switch (tag >>> 3) {
                        case 1:
                            message.name = reader.string();
                            break;
                        case 2:
                            message.avgSizeBytes = reader.double();
                            break;
                        case 3:
                            message.minSizeBytes = reader.double();
                            break;
                        case 4:
                            message.maxSizeBytes = reader.double();
                            break;
                        case 5:
                            message.totalAllocSizeBytes = reader.double();
                            break;
                        default:
                            reader.skipType(tag & 7);
                            break;
                        }
                    }
                    return message;
                };

                /**
                 * Decodes a Subsystem message from the specified reader or buffer, length delimited.
                 * @function decodeDelimited
                 * @memberof perfetto.protos.AndroidFastrpcMetric.Subsystem
                 * @static
                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                 * @returns {perfetto.protos.AndroidFastrpcMetric.Subsystem} Subsystem
                 * @throws {Error} If the payload is not a reader or valid buffer
                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
                 */
                Subsystem.decodeDelimited = function decodeDelimited(reader) {
                    if (!(reader instanceof $Reader))
                        reader = new $Reader(reader);
                    return this.decode(reader, reader.uint32());
                };

                /**
                 * Verifies a Subsystem message.
                 * @function verify
                 * @memberof perfetto.protos.AndroidFastrpcMetric.Subsystem
                 * @static
                 * @param {Object.<string,*>} message Plain object to verify
                 * @returns {string|null} `null` if valid, otherwise the reason why it is not
                 */
                Subsystem.verify = function verify(message) {
                    if (typeof message !== "object" || message === null)
                        return "object expected";
                    if (message.name != null && message.hasOwnProperty("name"))
                        if (!$util.isString(message.name))
                            return "name: string expected";
                    if (message.avgSizeBytes != null && message.hasOwnProperty("avgSizeBytes"))
                        if (typeof message.avgSizeBytes !== "number")
                            return "avgSizeBytes: number expected";
                    if (message.minSizeBytes != null && message.hasOwnProperty("minSizeBytes"))
                        if (typeof message.minSizeBytes !== "number")
                            return "minSizeBytes: number expected";
                    if (message.maxSizeBytes != null && message.hasOwnProperty("maxSizeBytes"))
                        if (typeof message.maxSizeBytes !== "number")
                            return "maxSizeBytes: number expected";
                    if (message.totalAllocSizeBytes != null && message.hasOwnProperty("totalAllocSizeBytes"))
                        if (typeof message.totalAllocSizeBytes !== "number")
                            return "totalAllocSizeBytes: number expected";
                    return null;
                };

                /**
                 * Creates a Subsystem message from a plain object. Also converts values to their respective internal types.
                 * @function fromObject
                 * @memberof perfetto.protos.AndroidFastrpcMetric.Subsystem
                 * @static
                 * @param {Object.<string,*>} object Plain object
                 * @returns {perfetto.protos.AndroidFastrpcMetric.Subsystem} Subsystem
                 */
                Subsystem.fromObject = function fromObject(object) {
                    if (object instanceof $root.perfetto.protos.AndroidFastrpcMetric.Subsystem)
                        return object;
                    var message = new $root.perfetto.protos.AndroidFastrpcMetric.Subsystem();
                    if (object.name != null)
                        message.name = String(object.name);
                    if (object.avgSizeBytes != null)
                        message.avgSizeBytes = Number(object.avgSizeBytes);
                    if (object.minSizeBytes != null)
                        message.minSizeBytes = Number(object.minSizeBytes);
                    if (object.maxSizeBytes != null)
                        message.maxSizeBytes = Number(object.maxSizeBytes);
                    if (object.totalAllocSizeBytes != null)
                        message.totalAllocSizeBytes = Number(object.totalAllocSizeBytes);
                    return message;
                };

                /**
                 * Creates a plain object from a Subsystem message. Also converts values to other types if specified.
                 * @function toObject
                 * @memberof perfetto.protos.AndroidFastrpcMetric.Subsystem
                 * @static
                 * @param {perfetto.protos.AndroidFastrpcMetric.Subsystem} message Subsystem
                 * @param {$protobuf.IConversionOptions} [options] Conversion options
                 * @returns {Object.<string,*>} Plain object
                 */
                Subsystem.toObject = function toObject(message, options) {
                    if (!options)
                        options = {};
                    var object = {};
                    if (options.defaults) {
                        object.name = "";
                        object.avgSizeBytes = 0;
                        object.minSizeBytes = 0;
                        object.maxSizeBytes = 0;
                        object.totalAllocSizeBytes = 0;
                    }
                    if (message.name != null && message.hasOwnProperty("name"))
                        object.name = message.name;
                    if (message.avgSizeBytes != null && message.hasOwnProperty("avgSizeBytes"))
                        object.avgSizeBytes = options.json && !isFinite(message.avgSizeBytes) ? String(message.avgSizeBytes) : message.avgSizeBytes;
                    if (message.minSizeBytes != null && message.hasOwnProperty("minSizeBytes"))
                        object.minSizeBytes = options.json && !isFinite(message.minSizeBytes) ? String(message.minSizeBytes) : message.minSizeBytes;
                    if (message.maxSizeBytes != null && message.hasOwnProperty("maxSizeBytes"))
                        object.maxSizeBytes = options.json && !isFinite(message.maxSizeBytes) ? String(message.maxSizeBytes) : message.maxSizeBytes;
                    if (message.totalAllocSizeBytes != null && message.hasOwnProperty("totalAllocSizeBytes"))
                        object.totalAllocSizeBytes = options.json && !isFinite(message.totalAllocSizeBytes) ? String(message.totalAllocSizeBytes) : message.totalAllocSizeBytes;
                    return object;
                };

                /**
                 * Converts this Subsystem to JSON.
                 * @function toJSON
                 * @memberof perfetto.protos.AndroidFastrpcMetric.Subsystem
                 * @instance
                 * @returns {Object.<string,*>} JSON object
                 */
                Subsystem.prototype.toJSON = function toJSON() {
                    return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
                };

                return Subsystem;
            })();

            return AndroidFastrpcMetric;
        })();

        protos.G2dMetrics = (function() {

            /**
             * Properties of a G2dMetrics.
             * @memberof perfetto.protos
             * @interface IG2dMetrics
             * @property {perfetto.protos.G2dMetrics.IG2dMetric|null} [g2dHw] G2dMetrics g2dHw
             * @property {perfetto.protos.G2dMetrics.IG2dMetric|null} [g2dSw] G2dMetrics g2dSw
             */

            /**
             * Constructs a new G2dMetrics.
             * @memberof perfetto.protos
             * @classdesc Represents a G2dMetrics.
             * @implements IG2dMetrics
             * @constructor
             * @param {perfetto.protos.IG2dMetrics=} [properties] Properties to set
             */
            function G2dMetrics(properties) {
                if (properties)
                    for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                        if (properties[keys[i]] != null)
                            this[keys[i]] = properties[keys[i]];
            }

            /**
             * G2dMetrics g2dHw.
             * @member {perfetto.protos.G2dMetrics.IG2dMetric|null|undefined} g2dHw
             * @memberof perfetto.protos.G2dMetrics
             * @instance
             */
            G2dMetrics.prototype.g2dHw = null;

            /**
             * G2dMetrics g2dSw.
             * @member {perfetto.protos.G2dMetrics.IG2dMetric|null|undefined} g2dSw
             * @memberof perfetto.protos.G2dMetrics
             * @instance
             */
            G2dMetrics.prototype.g2dSw = null;

            /**
             * Creates a new G2dMetrics instance using the specified properties.
             * @function create
             * @memberof perfetto.protos.G2dMetrics
             * @static
             * @param {perfetto.protos.IG2dMetrics=} [properties] Properties to set
             * @returns {perfetto.protos.G2dMetrics} G2dMetrics instance
             */
            G2dMetrics.create = function create(properties) {
                return new G2dMetrics(properties);
            };

            /**
             * Encodes the specified G2dMetrics message. Does not implicitly {@link perfetto.protos.G2dMetrics.verify|verify} messages.
             * @function encode
             * @memberof perfetto.protos.G2dMetrics
             * @static
             * @param {perfetto.protos.IG2dMetrics} message G2dMetrics message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            G2dMetrics.encode = function encode(message, writer) {
                if (!writer)
                    writer = $Writer.create();
                if (message.g2dHw != null && Object.hasOwnProperty.call(message, "g2dHw"))
                    $root.perfetto.protos.G2dMetrics.G2dMetric.encode(message.g2dHw, writer.uint32(/* id 1, wireType 2 =*/10).fork()).ldelim();
                if (message.g2dSw != null && Object.hasOwnProperty.call(message, "g2dSw"))
                    $root.perfetto.protos.G2dMetrics.G2dMetric.encode(message.g2dSw, writer.uint32(/* id 2, wireType 2 =*/18).fork()).ldelim();
                return writer;
            };

            /**
             * Encodes the specified G2dMetrics message, length delimited. Does not implicitly {@link perfetto.protos.G2dMetrics.verify|verify} messages.
             * @function encodeDelimited
             * @memberof perfetto.protos.G2dMetrics
             * @static
             * @param {perfetto.protos.IG2dMetrics} message G2dMetrics message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            G2dMetrics.encodeDelimited = function encodeDelimited(message, writer) {
                return this.encode(message, writer).ldelim();
            };

            /**
             * Decodes a G2dMetrics message from the specified reader or buffer.
             * @function decode
             * @memberof perfetto.protos.G2dMetrics
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @param {number} [length] Message length if known beforehand
             * @returns {perfetto.protos.G2dMetrics} G2dMetrics
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            G2dMetrics.decode = function decode(reader, length) {
                if (!(reader instanceof $Reader))
                    reader = $Reader.create(reader);
                var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.G2dMetrics();
                while (reader.pos < end) {
                    var tag = reader.uint32();
                    switch (tag >>> 3) {
                    case 1:
                        message.g2dHw = $root.perfetto.protos.G2dMetrics.G2dMetric.decode(reader, reader.uint32());
                        break;
                    case 2:
                        message.g2dSw = $root.perfetto.protos.G2dMetrics.G2dMetric.decode(reader, reader.uint32());
                        break;
                    default:
                        reader.skipType(tag & 7);
                        break;
                    }
                }
                return message;
            };

            /**
             * Decodes a G2dMetrics message from the specified reader or buffer, length delimited.
             * @function decodeDelimited
             * @memberof perfetto.protos.G2dMetrics
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @returns {perfetto.protos.G2dMetrics} G2dMetrics
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            G2dMetrics.decodeDelimited = function decodeDelimited(reader) {
                if (!(reader instanceof $Reader))
                    reader = new $Reader(reader);
                return this.decode(reader, reader.uint32());
            };

            /**
             * Verifies a G2dMetrics message.
             * @function verify
             * @memberof perfetto.protos.G2dMetrics
             * @static
             * @param {Object.<string,*>} message Plain object to verify
             * @returns {string|null} `null` if valid, otherwise the reason why it is not
             */
            G2dMetrics.verify = function verify(message) {
                if (typeof message !== "object" || message === null)
                    return "object expected";
                if (message.g2dHw != null && message.hasOwnProperty("g2dHw")) {
                    var error = $root.perfetto.protos.G2dMetrics.G2dMetric.verify(message.g2dHw);
                    if (error)
                        return "g2dHw." + error;
                }
                if (message.g2dSw != null && message.hasOwnProperty("g2dSw")) {
                    var error = $root.perfetto.protos.G2dMetrics.G2dMetric.verify(message.g2dSw);
                    if (error)
                        return "g2dSw." + error;
                }
                return null;
            };

            /**
             * Creates a G2dMetrics message from a plain object. Also converts values to their respective internal types.
             * @function fromObject
             * @memberof perfetto.protos.G2dMetrics
             * @static
             * @param {Object.<string,*>} object Plain object
             * @returns {perfetto.protos.G2dMetrics} G2dMetrics
             */
            G2dMetrics.fromObject = function fromObject(object) {
                if (object instanceof $root.perfetto.protos.G2dMetrics)
                    return object;
                var message = new $root.perfetto.protos.G2dMetrics();
                if (object.g2dHw != null) {
                    if (typeof object.g2dHw !== "object")
                        throw TypeError(".perfetto.protos.G2dMetrics.g2dHw: object expected");
                    message.g2dHw = $root.perfetto.protos.G2dMetrics.G2dMetric.fromObject(object.g2dHw);
                }
                if (object.g2dSw != null) {
                    if (typeof object.g2dSw !== "object")
                        throw TypeError(".perfetto.protos.G2dMetrics.g2dSw: object expected");
                    message.g2dSw = $root.perfetto.protos.G2dMetrics.G2dMetric.fromObject(object.g2dSw);
                }
                return message;
            };

            /**
             * Creates a plain object from a G2dMetrics message. Also converts values to other types if specified.
             * @function toObject
             * @memberof perfetto.protos.G2dMetrics
             * @static
             * @param {perfetto.protos.G2dMetrics} message G2dMetrics
             * @param {$protobuf.IConversionOptions} [options] Conversion options
             * @returns {Object.<string,*>} Plain object
             */
            G2dMetrics.toObject = function toObject(message, options) {
                if (!options)
                    options = {};
                var object = {};
                if (options.defaults) {
                    object.g2dHw = null;
                    object.g2dSw = null;
                }
                if (message.g2dHw != null && message.hasOwnProperty("g2dHw"))
                    object.g2dHw = $root.perfetto.protos.G2dMetrics.G2dMetric.toObject(message.g2dHw, options);
                if (message.g2dSw != null && message.hasOwnProperty("g2dSw"))
                    object.g2dSw = $root.perfetto.protos.G2dMetrics.G2dMetric.toObject(message.g2dSw, options);
                return object;
            };

            /**
             * Converts this G2dMetrics to JSON.
             * @function toJSON
             * @memberof perfetto.protos.G2dMetrics
             * @instance
             * @returns {Object.<string,*>} JSON object
             */
            G2dMetrics.prototype.toJSON = function toJSON() {
                return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
            };

            G2dMetrics.G2dInstance = (function() {

                /**
                 * Properties of a G2dInstance.
                 * @memberof perfetto.protos.G2dMetrics
                 * @interface IG2dInstance
                 * @property {string|null} [name] G2dInstance name
                 * @property {number|null} [maxDurNs] G2dInstance maxDurNs
                 * @property {number|null} [minDurNs] G2dInstance minDurNs
                 * @property {number|null} [avgDurNs] G2dInstance avgDurNs
                 * @property {number|null} [frameCount] G2dInstance frameCount
                 * @property {number|null} [errorCount] G2dInstance errorCount
                 */

                /**
                 * Constructs a new G2dInstance.
                 * @memberof perfetto.protos.G2dMetrics
                 * @classdesc Represents a G2dInstance.
                 * @implements IG2dInstance
                 * @constructor
                 * @param {perfetto.protos.G2dMetrics.IG2dInstance=} [properties] Properties to set
                 */
                function G2dInstance(properties) {
                    if (properties)
                        for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                            if (properties[keys[i]] != null)
                                this[keys[i]] = properties[keys[i]];
                }

                /**
                 * G2dInstance name.
                 * @member {string} name
                 * @memberof perfetto.protos.G2dMetrics.G2dInstance
                 * @instance
                 */
                G2dInstance.prototype.name = "";

                /**
                 * G2dInstance maxDurNs.
                 * @member {number} maxDurNs
                 * @memberof perfetto.protos.G2dMetrics.G2dInstance
                 * @instance
                 */
                G2dInstance.prototype.maxDurNs = $util.Long ? $util.Long.fromBits(0,0,false) : 0;

                /**
                 * G2dInstance minDurNs.
                 * @member {number} minDurNs
                 * @memberof perfetto.protos.G2dMetrics.G2dInstance
                 * @instance
                 */
                G2dInstance.prototype.minDurNs = $util.Long ? $util.Long.fromBits(0,0,false) : 0;

                /**
                 * G2dInstance avgDurNs.
                 * @member {number} avgDurNs
                 * @memberof perfetto.protos.G2dMetrics.G2dInstance
                 * @instance
                 */
                G2dInstance.prototype.avgDurNs = $util.Long ? $util.Long.fromBits(0,0,false) : 0;

                /**
                 * G2dInstance frameCount.
                 * @member {number} frameCount
                 * @memberof perfetto.protos.G2dMetrics.G2dInstance
                 * @instance
                 */
                G2dInstance.prototype.frameCount = 0;

                /**
                 * G2dInstance errorCount.
                 * @member {number} errorCount
                 * @memberof perfetto.protos.G2dMetrics.G2dInstance
                 * @instance
                 */
                G2dInstance.prototype.errorCount = 0;

                /**
                 * Creates a new G2dInstance instance using the specified properties.
                 * @function create
                 * @memberof perfetto.protos.G2dMetrics.G2dInstance
                 * @static
                 * @param {perfetto.protos.G2dMetrics.IG2dInstance=} [properties] Properties to set
                 * @returns {perfetto.protos.G2dMetrics.G2dInstance} G2dInstance instance
                 */
                G2dInstance.create = function create(properties) {
                    return new G2dInstance(properties);
                };

                /**
                 * Encodes the specified G2dInstance message. Does not implicitly {@link perfetto.protos.G2dMetrics.G2dInstance.verify|verify} messages.
                 * @function encode
                 * @memberof perfetto.protos.G2dMetrics.G2dInstance
                 * @static
                 * @param {perfetto.protos.G2dMetrics.IG2dInstance} message G2dInstance message or plain object to encode
                 * @param {$protobuf.Writer} [writer] Writer to encode to
                 * @returns {$protobuf.Writer} Writer
                 */
                G2dInstance.encode = function encode(message, writer) {
                    if (!writer)
                        writer = $Writer.create();
                    if (message.name != null && Object.hasOwnProperty.call(message, "name"))
                        writer.uint32(/* id 1, wireType 2 =*/10).string(message.name);
                    if (message.maxDurNs != null && Object.hasOwnProperty.call(message, "maxDurNs"))
                        writer.uint32(/* id 2, wireType 0 =*/16).int64(message.maxDurNs);
                    if (message.minDurNs != null && Object.hasOwnProperty.call(message, "minDurNs"))
                        writer.uint32(/* id 3, wireType 0 =*/24).int64(message.minDurNs);
                    if (message.avgDurNs != null && Object.hasOwnProperty.call(message, "avgDurNs"))
                        writer.uint32(/* id 4, wireType 0 =*/32).int64(message.avgDurNs);
                    if (message.frameCount != null && Object.hasOwnProperty.call(message, "frameCount"))
                        writer.uint32(/* id 5, wireType 0 =*/40).uint32(message.frameCount);
                    if (message.errorCount != null && Object.hasOwnProperty.call(message, "errorCount"))
                        writer.uint32(/* id 6, wireType 0 =*/48).uint32(message.errorCount);
                    return writer;
                };

                /**
                 * Encodes the specified G2dInstance message, length delimited. Does not implicitly {@link perfetto.protos.G2dMetrics.G2dInstance.verify|verify} messages.
                 * @function encodeDelimited
                 * @memberof perfetto.protos.G2dMetrics.G2dInstance
                 * @static
                 * @param {perfetto.protos.G2dMetrics.IG2dInstance} message G2dInstance message or plain object to encode
                 * @param {$protobuf.Writer} [writer] Writer to encode to
                 * @returns {$protobuf.Writer} Writer
                 */
                G2dInstance.encodeDelimited = function encodeDelimited(message, writer) {
                    return this.encode(message, writer).ldelim();
                };

                /**
                 * Decodes a G2dInstance message from the specified reader or buffer.
                 * @function decode
                 * @memberof perfetto.protos.G2dMetrics.G2dInstance
                 * @static
                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                 * @param {number} [length] Message length if known beforehand
                 * @returns {perfetto.protos.G2dMetrics.G2dInstance} G2dInstance
                 * @throws {Error} If the payload is not a reader or valid buffer
                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
                 */
                G2dInstance.decode = function decode(reader, length) {
                    if (!(reader instanceof $Reader))
                        reader = $Reader.create(reader);
                    var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.G2dMetrics.G2dInstance();
                    while (reader.pos < end) {
                        var tag = reader.uint32();
                        switch (tag >>> 3) {
                        case 1:
                            message.name = reader.string();
                            break;
                        case 2:
                            message.maxDurNs = reader.int64();
                            break;
                        case 3:
                            message.minDurNs = reader.int64();
                            break;
                        case 4:
                            message.avgDurNs = reader.int64();
                            break;
                        case 5:
                            message.frameCount = reader.uint32();
                            break;
                        case 6:
                            message.errorCount = reader.uint32();
                            break;
                        default:
                            reader.skipType(tag & 7);
                            break;
                        }
                    }
                    return message;
                };

                /**
                 * Decodes a G2dInstance message from the specified reader or buffer, length delimited.
                 * @function decodeDelimited
                 * @memberof perfetto.protos.G2dMetrics.G2dInstance
                 * @static
                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                 * @returns {perfetto.protos.G2dMetrics.G2dInstance} G2dInstance
                 * @throws {Error} If the payload is not a reader or valid buffer
                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
                 */
                G2dInstance.decodeDelimited = function decodeDelimited(reader) {
                    if (!(reader instanceof $Reader))
                        reader = new $Reader(reader);
                    return this.decode(reader, reader.uint32());
                };

                /**
                 * Verifies a G2dInstance message.
                 * @function verify
                 * @memberof perfetto.protos.G2dMetrics.G2dInstance
                 * @static
                 * @param {Object.<string,*>} message Plain object to verify
                 * @returns {string|null} `null` if valid, otherwise the reason why it is not
                 */
                G2dInstance.verify = function verify(message) {
                    if (typeof message !== "object" || message === null)
                        return "object expected";
                    if (message.name != null && message.hasOwnProperty("name"))
                        if (!$util.isString(message.name))
                            return "name: string expected";
                    if (message.maxDurNs != null && message.hasOwnProperty("maxDurNs"))
                        if (!$util.isInteger(message.maxDurNs) && !(message.maxDurNs && $util.isInteger(message.maxDurNs.low) && $util.isInteger(message.maxDurNs.high)))
                            return "maxDurNs: integer|Long expected";
                    if (message.minDurNs != null && message.hasOwnProperty("minDurNs"))
                        if (!$util.isInteger(message.minDurNs) && !(message.minDurNs && $util.isInteger(message.minDurNs.low) && $util.isInteger(message.minDurNs.high)))
                            return "minDurNs: integer|Long expected";
                    if (message.avgDurNs != null && message.hasOwnProperty("avgDurNs"))
                        if (!$util.isInteger(message.avgDurNs) && !(message.avgDurNs && $util.isInteger(message.avgDurNs.low) && $util.isInteger(message.avgDurNs.high)))
                            return "avgDurNs: integer|Long expected";
                    if (message.frameCount != null && message.hasOwnProperty("frameCount"))
                        if (!$util.isInteger(message.frameCount))
                            return "frameCount: integer expected";
                    if (message.errorCount != null && message.hasOwnProperty("errorCount"))
                        if (!$util.isInteger(message.errorCount))
                            return "errorCount: integer expected";
                    return null;
                };

                /**
                 * Creates a G2dInstance message from a plain object. Also converts values to their respective internal types.
                 * @function fromObject
                 * @memberof perfetto.protos.G2dMetrics.G2dInstance
                 * @static
                 * @param {Object.<string,*>} object Plain object
                 * @returns {perfetto.protos.G2dMetrics.G2dInstance} G2dInstance
                 */
                G2dInstance.fromObject = function fromObject(object) {
                    if (object instanceof $root.perfetto.protos.G2dMetrics.G2dInstance)
                        return object;
                    var message = new $root.perfetto.protos.G2dMetrics.G2dInstance();
                    if (object.name != null)
                        message.name = String(object.name);
                    if (object.maxDurNs != null)
                        if ($util.Long)
                            (message.maxDurNs = $util.Long.fromValue(object.maxDurNs)).unsigned = false;
                        else if (typeof object.maxDurNs === "string")
                            message.maxDurNs = parseInt(object.maxDurNs, 10);
                        else if (typeof object.maxDurNs === "number")
                            message.maxDurNs = object.maxDurNs;
                        else if (typeof object.maxDurNs === "object")
                            message.maxDurNs = new $util.LongBits(object.maxDurNs.low >>> 0, object.maxDurNs.high >>> 0).toNumber();
                    if (object.minDurNs != null)
                        if ($util.Long)
                            (message.minDurNs = $util.Long.fromValue(object.minDurNs)).unsigned = false;
                        else if (typeof object.minDurNs === "string")
                            message.minDurNs = parseInt(object.minDurNs, 10);
                        else if (typeof object.minDurNs === "number")
                            message.minDurNs = object.minDurNs;
                        else if (typeof object.minDurNs === "object")
                            message.minDurNs = new $util.LongBits(object.minDurNs.low >>> 0, object.minDurNs.high >>> 0).toNumber();
                    if (object.avgDurNs != null)
                        if ($util.Long)
                            (message.avgDurNs = $util.Long.fromValue(object.avgDurNs)).unsigned = false;
                        else if (typeof object.avgDurNs === "string")
                            message.avgDurNs = parseInt(object.avgDurNs, 10);
                        else if (typeof object.avgDurNs === "number")
                            message.avgDurNs = object.avgDurNs;
                        else if (typeof object.avgDurNs === "object")
                            message.avgDurNs = new $util.LongBits(object.avgDurNs.low >>> 0, object.avgDurNs.high >>> 0).toNumber();
                    if (object.frameCount != null)
                        message.frameCount = object.frameCount >>> 0;
                    if (object.errorCount != null)
                        message.errorCount = object.errorCount >>> 0;
                    return message;
                };

                /**
                 * Creates a plain object from a G2dInstance message. Also converts values to other types if specified.
                 * @function toObject
                 * @memberof perfetto.protos.G2dMetrics.G2dInstance
                 * @static
                 * @param {perfetto.protos.G2dMetrics.G2dInstance} message G2dInstance
                 * @param {$protobuf.IConversionOptions} [options] Conversion options
                 * @returns {Object.<string,*>} Plain object
                 */
                G2dInstance.toObject = function toObject(message, options) {
                    if (!options)
                        options = {};
                    var object = {};
                    if (options.defaults) {
                        object.name = "";
                        if ($util.Long) {
                            var long = new $util.Long(0, 0, false);
                            object.maxDurNs = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
                        } else
                            object.maxDurNs = options.longs === String ? "0" : 0;
                        if ($util.Long) {
                            var long = new $util.Long(0, 0, false);
                            object.minDurNs = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
                        } else
                            object.minDurNs = options.longs === String ? "0" : 0;
                        if ($util.Long) {
                            var long = new $util.Long(0, 0, false);
                            object.avgDurNs = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
                        } else
                            object.avgDurNs = options.longs === String ? "0" : 0;
                        object.frameCount = 0;
                        object.errorCount = 0;
                    }
                    if (message.name != null && message.hasOwnProperty("name"))
                        object.name = message.name;
                    if (message.maxDurNs != null && message.hasOwnProperty("maxDurNs"))
                        if (typeof message.maxDurNs === "number")
                            object.maxDurNs = options.longs === String ? String(message.maxDurNs) : message.maxDurNs;
                        else
                            object.maxDurNs = options.longs === String ? $util.Long.prototype.toString.call(message.maxDurNs) : options.longs === Number ? new $util.LongBits(message.maxDurNs.low >>> 0, message.maxDurNs.high >>> 0).toNumber() : message.maxDurNs;
                    if (message.minDurNs != null && message.hasOwnProperty("minDurNs"))
                        if (typeof message.minDurNs === "number")
                            object.minDurNs = options.longs === String ? String(message.minDurNs) : message.minDurNs;
                        else
                            object.minDurNs = options.longs === String ? $util.Long.prototype.toString.call(message.minDurNs) : options.longs === Number ? new $util.LongBits(message.minDurNs.low >>> 0, message.minDurNs.high >>> 0).toNumber() : message.minDurNs;
                    if (message.avgDurNs != null && message.hasOwnProperty("avgDurNs"))
                        if (typeof message.avgDurNs === "number")
                            object.avgDurNs = options.longs === String ? String(message.avgDurNs) : message.avgDurNs;
                        else
                            object.avgDurNs = options.longs === String ? $util.Long.prototype.toString.call(message.avgDurNs) : options.longs === Number ? new $util.LongBits(message.avgDurNs.low >>> 0, message.avgDurNs.high >>> 0).toNumber() : message.avgDurNs;
                    if (message.frameCount != null && message.hasOwnProperty("frameCount"))
                        object.frameCount = message.frameCount;
                    if (message.errorCount != null && message.hasOwnProperty("errorCount"))
                        object.errorCount = message.errorCount;
                    return object;
                };

                /**
                 * Converts this G2dInstance to JSON.
                 * @function toJSON
                 * @memberof perfetto.protos.G2dMetrics.G2dInstance
                 * @instance
                 * @returns {Object.<string,*>} JSON object
                 */
                G2dInstance.prototype.toJSON = function toJSON() {
                    return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
                };

                return G2dInstance;
            })();

            G2dMetrics.G2dMetric = (function() {

                /**
                 * Properties of a G2dMetric.
                 * @memberof perfetto.protos.G2dMetrics
                 * @interface IG2dMetric
                 * @property {Array.<perfetto.protos.G2dMetrics.IG2dInstance>|null} [instances] G2dMetric instances
                 * @property {number|null} [maxDurNs] G2dMetric maxDurNs
                 * @property {number|null} [minDurNs] G2dMetric minDurNs
                 * @property {number|null} [avgDurNs] G2dMetric avgDurNs
                 * @property {number|null} [frameCount] G2dMetric frameCount
                 * @property {number|null} [errorCount] G2dMetric errorCount
                 */

                /**
                 * Constructs a new G2dMetric.
                 * @memberof perfetto.protos.G2dMetrics
                 * @classdesc Represents a G2dMetric.
                 * @implements IG2dMetric
                 * @constructor
                 * @param {perfetto.protos.G2dMetrics.IG2dMetric=} [properties] Properties to set
                 */
                function G2dMetric(properties) {
                    this.instances = [];
                    if (properties)
                        for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                            if (properties[keys[i]] != null)
                                this[keys[i]] = properties[keys[i]];
                }

                /**
                 * G2dMetric instances.
                 * @member {Array.<perfetto.protos.G2dMetrics.IG2dInstance>} instances
                 * @memberof perfetto.protos.G2dMetrics.G2dMetric
                 * @instance
                 */
                G2dMetric.prototype.instances = $util.emptyArray;

                /**
                 * G2dMetric maxDurNs.
                 * @member {number} maxDurNs
                 * @memberof perfetto.protos.G2dMetrics.G2dMetric
                 * @instance
                 */
                G2dMetric.prototype.maxDurNs = $util.Long ? $util.Long.fromBits(0,0,false) : 0;

                /**
                 * G2dMetric minDurNs.
                 * @member {number} minDurNs
                 * @memberof perfetto.protos.G2dMetrics.G2dMetric
                 * @instance
                 */
                G2dMetric.prototype.minDurNs = $util.Long ? $util.Long.fromBits(0,0,false) : 0;

                /**
                 * G2dMetric avgDurNs.
                 * @member {number} avgDurNs
                 * @memberof perfetto.protos.G2dMetrics.G2dMetric
                 * @instance
                 */
                G2dMetric.prototype.avgDurNs = $util.Long ? $util.Long.fromBits(0,0,false) : 0;

                /**
                 * G2dMetric frameCount.
                 * @member {number} frameCount
                 * @memberof perfetto.protos.G2dMetrics.G2dMetric
                 * @instance
                 */
                G2dMetric.prototype.frameCount = 0;

                /**
                 * G2dMetric errorCount.
                 * @member {number} errorCount
                 * @memberof perfetto.protos.G2dMetrics.G2dMetric
                 * @instance
                 */
                G2dMetric.prototype.errorCount = 0;

                /**
                 * Creates a new G2dMetric instance using the specified properties.
                 * @function create
                 * @memberof perfetto.protos.G2dMetrics.G2dMetric
                 * @static
                 * @param {perfetto.protos.G2dMetrics.IG2dMetric=} [properties] Properties to set
                 * @returns {perfetto.protos.G2dMetrics.G2dMetric} G2dMetric instance
                 */
                G2dMetric.create = function create(properties) {
                    return new G2dMetric(properties);
                };

                /**
                 * Encodes the specified G2dMetric message. Does not implicitly {@link perfetto.protos.G2dMetrics.G2dMetric.verify|verify} messages.
                 * @function encode
                 * @memberof perfetto.protos.G2dMetrics.G2dMetric
                 * @static
                 * @param {perfetto.protos.G2dMetrics.IG2dMetric} message G2dMetric message or plain object to encode
                 * @param {$protobuf.Writer} [writer] Writer to encode to
                 * @returns {$protobuf.Writer} Writer
                 */
                G2dMetric.encode = function encode(message, writer) {
                    if (!writer)
                        writer = $Writer.create();
                    if (message.instances != null && message.instances.length)
                        for (var i = 0; i < message.instances.length; ++i)
                            $root.perfetto.protos.G2dMetrics.G2dInstance.encode(message.instances[i], writer.uint32(/* id 1, wireType 2 =*/10).fork()).ldelim();
                    if (message.maxDurNs != null && Object.hasOwnProperty.call(message, "maxDurNs"))
                        writer.uint32(/* id 2, wireType 0 =*/16).int64(message.maxDurNs);
                    if (message.minDurNs != null && Object.hasOwnProperty.call(message, "minDurNs"))
                        writer.uint32(/* id 3, wireType 0 =*/24).int64(message.minDurNs);
                    if (message.avgDurNs != null && Object.hasOwnProperty.call(message, "avgDurNs"))
                        writer.uint32(/* id 4, wireType 0 =*/32).int64(message.avgDurNs);
                    if (message.frameCount != null && Object.hasOwnProperty.call(message, "frameCount"))
                        writer.uint32(/* id 5, wireType 0 =*/40).uint32(message.frameCount);
                    if (message.errorCount != null && Object.hasOwnProperty.call(message, "errorCount"))
                        writer.uint32(/* id 6, wireType 0 =*/48).uint32(message.errorCount);
                    return writer;
                };

                /**
                 * Encodes the specified G2dMetric message, length delimited. Does not implicitly {@link perfetto.protos.G2dMetrics.G2dMetric.verify|verify} messages.
                 * @function encodeDelimited
                 * @memberof perfetto.protos.G2dMetrics.G2dMetric
                 * @static
                 * @param {perfetto.protos.G2dMetrics.IG2dMetric} message G2dMetric message or plain object to encode
                 * @param {$protobuf.Writer} [writer] Writer to encode to
                 * @returns {$protobuf.Writer} Writer
                 */
                G2dMetric.encodeDelimited = function encodeDelimited(message, writer) {
                    return this.encode(message, writer).ldelim();
                };

                /**
                 * Decodes a G2dMetric message from the specified reader or buffer.
                 * @function decode
                 * @memberof perfetto.protos.G2dMetrics.G2dMetric
                 * @static
                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                 * @param {number} [length] Message length if known beforehand
                 * @returns {perfetto.protos.G2dMetrics.G2dMetric} G2dMetric
                 * @throws {Error} If the payload is not a reader or valid buffer
                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
                 */
                G2dMetric.decode = function decode(reader, length) {
                    if (!(reader instanceof $Reader))
                        reader = $Reader.create(reader);
                    var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.G2dMetrics.G2dMetric();
                    while (reader.pos < end) {
                        var tag = reader.uint32();
                        switch (tag >>> 3) {
                        case 1:
                            if (!(message.instances && message.instances.length))
                                message.instances = [];
                            message.instances.push($root.perfetto.protos.G2dMetrics.G2dInstance.decode(reader, reader.uint32()));
                            break;
                        case 2:
                            message.maxDurNs = reader.int64();
                            break;
                        case 3:
                            message.minDurNs = reader.int64();
                            break;
                        case 4:
                            message.avgDurNs = reader.int64();
                            break;
                        case 5:
                            message.frameCount = reader.uint32();
                            break;
                        case 6:
                            message.errorCount = reader.uint32();
                            break;
                        default:
                            reader.skipType(tag & 7);
                            break;
                        }
                    }
                    return message;
                };

                /**
                 * Decodes a G2dMetric message from the specified reader or buffer, length delimited.
                 * @function decodeDelimited
                 * @memberof perfetto.protos.G2dMetrics.G2dMetric
                 * @static
                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                 * @returns {perfetto.protos.G2dMetrics.G2dMetric} G2dMetric
                 * @throws {Error} If the payload is not a reader or valid buffer
                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
                 */
                G2dMetric.decodeDelimited = function decodeDelimited(reader) {
                    if (!(reader instanceof $Reader))
                        reader = new $Reader(reader);
                    return this.decode(reader, reader.uint32());
                };

                /**
                 * Verifies a G2dMetric message.
                 * @function verify
                 * @memberof perfetto.protos.G2dMetrics.G2dMetric
                 * @static
                 * @param {Object.<string,*>} message Plain object to verify
                 * @returns {string|null} `null` if valid, otherwise the reason why it is not
                 */
                G2dMetric.verify = function verify(message) {
                    if (typeof message !== "object" || message === null)
                        return "object expected";
                    if (message.instances != null && message.hasOwnProperty("instances")) {
                        if (!Array.isArray(message.instances))
                            return "instances: array expected";
                        for (var i = 0; i < message.instances.length; ++i) {
                            var error = $root.perfetto.protos.G2dMetrics.G2dInstance.verify(message.instances[i]);
                            if (error)
                                return "instances." + error;
                        }
                    }
                    if (message.maxDurNs != null && message.hasOwnProperty("maxDurNs"))
                        if (!$util.isInteger(message.maxDurNs) && !(message.maxDurNs && $util.isInteger(message.maxDurNs.low) && $util.isInteger(message.maxDurNs.high)))
                            return "maxDurNs: integer|Long expected";
                    if (message.minDurNs != null && message.hasOwnProperty("minDurNs"))
                        if (!$util.isInteger(message.minDurNs) && !(message.minDurNs && $util.isInteger(message.minDurNs.low) && $util.isInteger(message.minDurNs.high)))
                            return "minDurNs: integer|Long expected";
                    if (message.avgDurNs != null && message.hasOwnProperty("avgDurNs"))
                        if (!$util.isInteger(message.avgDurNs) && !(message.avgDurNs && $util.isInteger(message.avgDurNs.low) && $util.isInteger(message.avgDurNs.high)))
                            return "avgDurNs: integer|Long expected";
                    if (message.frameCount != null && message.hasOwnProperty("frameCount"))
                        if (!$util.isInteger(message.frameCount))
                            return "frameCount: integer expected";
                    if (message.errorCount != null && message.hasOwnProperty("errorCount"))
                        if (!$util.isInteger(message.errorCount))
                            return "errorCount: integer expected";
                    return null;
                };

                /**
                 * Creates a G2dMetric message from a plain object. Also converts values to their respective internal types.
                 * @function fromObject
                 * @memberof perfetto.protos.G2dMetrics.G2dMetric
                 * @static
                 * @param {Object.<string,*>} object Plain object
                 * @returns {perfetto.protos.G2dMetrics.G2dMetric} G2dMetric
                 */
                G2dMetric.fromObject = function fromObject(object) {
                    if (object instanceof $root.perfetto.protos.G2dMetrics.G2dMetric)
                        return object;
                    var message = new $root.perfetto.protos.G2dMetrics.G2dMetric();
                    if (object.instances) {
                        if (!Array.isArray(object.instances))
                            throw TypeError(".perfetto.protos.G2dMetrics.G2dMetric.instances: array expected");
                        message.instances = [];
                        for (var i = 0; i < object.instances.length; ++i) {
                            if (typeof object.instances[i] !== "object")
                                throw TypeError(".perfetto.protos.G2dMetrics.G2dMetric.instances: object expected");
                            message.instances[i] = $root.perfetto.protos.G2dMetrics.G2dInstance.fromObject(object.instances[i]);
                        }
                    }
                    if (object.maxDurNs != null)
                        if ($util.Long)
                            (message.maxDurNs = $util.Long.fromValue(object.maxDurNs)).unsigned = false;
                        else if (typeof object.maxDurNs === "string")
                            message.maxDurNs = parseInt(object.maxDurNs, 10);
                        else if (typeof object.maxDurNs === "number")
                            message.maxDurNs = object.maxDurNs;
                        else if (typeof object.maxDurNs === "object")
                            message.maxDurNs = new $util.LongBits(object.maxDurNs.low >>> 0, object.maxDurNs.high >>> 0).toNumber();
                    if (object.minDurNs != null)
                        if ($util.Long)
                            (message.minDurNs = $util.Long.fromValue(object.minDurNs)).unsigned = false;
                        else if (typeof object.minDurNs === "string")
                            message.minDurNs = parseInt(object.minDurNs, 10);
                        else if (typeof object.minDurNs === "number")
                            message.minDurNs = object.minDurNs;
                        else if (typeof object.minDurNs === "object")
                            message.minDurNs = new $util.LongBits(object.minDurNs.low >>> 0, object.minDurNs.high >>> 0).toNumber();
                    if (object.avgDurNs != null)
                        if ($util.Long)
                            (message.avgDurNs = $util.Long.fromValue(object.avgDurNs)).unsigned = false;
                        else if (typeof object.avgDurNs === "string")
                            message.avgDurNs = parseInt(object.avgDurNs, 10);
                        else if (typeof object.avgDurNs === "number")
                            message.avgDurNs = object.avgDurNs;
                        else if (typeof object.avgDurNs === "object")
                            message.avgDurNs = new $util.LongBits(object.avgDurNs.low >>> 0, object.avgDurNs.high >>> 0).toNumber();
                    if (object.frameCount != null)
                        message.frameCount = object.frameCount >>> 0;
                    if (object.errorCount != null)
                        message.errorCount = object.errorCount >>> 0;
                    return message;
                };

                /**
                 * Creates a plain object from a G2dMetric message. Also converts values to other types if specified.
                 * @function toObject
                 * @memberof perfetto.protos.G2dMetrics.G2dMetric
                 * @static
                 * @param {perfetto.protos.G2dMetrics.G2dMetric} message G2dMetric
                 * @param {$protobuf.IConversionOptions} [options] Conversion options
                 * @returns {Object.<string,*>} Plain object
                 */
                G2dMetric.toObject = function toObject(message, options) {
                    if (!options)
                        options = {};
                    var object = {};
                    if (options.arrays || options.defaults)
                        object.instances = [];
                    if (options.defaults) {
                        if ($util.Long) {
                            var long = new $util.Long(0, 0, false);
                            object.maxDurNs = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
                        } else
                            object.maxDurNs = options.longs === String ? "0" : 0;
                        if ($util.Long) {
                            var long = new $util.Long(0, 0, false);
                            object.minDurNs = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
                        } else
                            object.minDurNs = options.longs === String ? "0" : 0;
                        if ($util.Long) {
                            var long = new $util.Long(0, 0, false);
                            object.avgDurNs = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
                        } else
                            object.avgDurNs = options.longs === String ? "0" : 0;
                        object.frameCount = 0;
                        object.errorCount = 0;
                    }
                    if (message.instances && message.instances.length) {
                        object.instances = [];
                        for (var j = 0; j < message.instances.length; ++j)
                            object.instances[j] = $root.perfetto.protos.G2dMetrics.G2dInstance.toObject(message.instances[j], options);
                    }
                    if (message.maxDurNs != null && message.hasOwnProperty("maxDurNs"))
                        if (typeof message.maxDurNs === "number")
                            object.maxDurNs = options.longs === String ? String(message.maxDurNs) : message.maxDurNs;
                        else
                            object.maxDurNs = options.longs === String ? $util.Long.prototype.toString.call(message.maxDurNs) : options.longs === Number ? new $util.LongBits(message.maxDurNs.low >>> 0, message.maxDurNs.high >>> 0).toNumber() : message.maxDurNs;
                    if (message.minDurNs != null && message.hasOwnProperty("minDurNs"))
                        if (typeof message.minDurNs === "number")
                            object.minDurNs = options.longs === String ? String(message.minDurNs) : message.minDurNs;
                        else
                            object.minDurNs = options.longs === String ? $util.Long.prototype.toString.call(message.minDurNs) : options.longs === Number ? new $util.LongBits(message.minDurNs.low >>> 0, message.minDurNs.high >>> 0).toNumber() : message.minDurNs;
                    if (message.avgDurNs != null && message.hasOwnProperty("avgDurNs"))
                        if (typeof message.avgDurNs === "number")
                            object.avgDurNs = options.longs === String ? String(message.avgDurNs) : message.avgDurNs;
                        else
                            object.avgDurNs = options.longs === String ? $util.Long.prototype.toString.call(message.avgDurNs) : options.longs === Number ? new $util.LongBits(message.avgDurNs.low >>> 0, message.avgDurNs.high >>> 0).toNumber() : message.avgDurNs;
                    if (message.frameCount != null && message.hasOwnProperty("frameCount"))
                        object.frameCount = message.frameCount;
                    if (message.errorCount != null && message.hasOwnProperty("errorCount"))
                        object.errorCount = message.errorCount;
                    return object;
                };

                /**
                 * Converts this G2dMetric to JSON.
                 * @function toJSON
                 * @memberof perfetto.protos.G2dMetrics.G2dMetric
                 * @instance
                 * @returns {Object.<string,*>} JSON object
                 */
                G2dMetric.prototype.toJSON = function toJSON() {
                    return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
                };

                return G2dMetric;
            })();

            return G2dMetrics;
        })();

        protos.AndroidGpuMetric = (function() {

            /**
             * Properties of an AndroidGpuMetric.
             * @memberof perfetto.protos
             * @interface IAndroidGpuMetric
             * @property {Array.<perfetto.protos.AndroidGpuMetric.IProcess>|null} [processes] AndroidGpuMetric processes
             * @property {number|null} [memMax] AndroidGpuMetric memMax
             * @property {number|null} [memMin] AndroidGpuMetric memMin
             * @property {number|null} [memAvg] AndroidGpuMetric memAvg
             */

            /**
             * Constructs a new AndroidGpuMetric.
             * @memberof perfetto.protos
             * @classdesc Represents an AndroidGpuMetric.
             * @implements IAndroidGpuMetric
             * @constructor
             * @param {perfetto.protos.IAndroidGpuMetric=} [properties] Properties to set
             */
            function AndroidGpuMetric(properties) {
                this.processes = [];
                if (properties)
                    for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                        if (properties[keys[i]] != null)
                            this[keys[i]] = properties[keys[i]];
            }

            /**
             * AndroidGpuMetric processes.
             * @member {Array.<perfetto.protos.AndroidGpuMetric.IProcess>} processes
             * @memberof perfetto.protos.AndroidGpuMetric
             * @instance
             */
            AndroidGpuMetric.prototype.processes = $util.emptyArray;

            /**
             * AndroidGpuMetric memMax.
             * @member {number} memMax
             * @memberof perfetto.protos.AndroidGpuMetric
             * @instance
             */
            AndroidGpuMetric.prototype.memMax = $util.Long ? $util.Long.fromBits(0,0,false) : 0;

            /**
             * AndroidGpuMetric memMin.
             * @member {number} memMin
             * @memberof perfetto.protos.AndroidGpuMetric
             * @instance
             */
            AndroidGpuMetric.prototype.memMin = $util.Long ? $util.Long.fromBits(0,0,false) : 0;

            /**
             * AndroidGpuMetric memAvg.
             * @member {number} memAvg
             * @memberof perfetto.protos.AndroidGpuMetric
             * @instance
             */
            AndroidGpuMetric.prototype.memAvg = $util.Long ? $util.Long.fromBits(0,0,false) : 0;

            /**
             * Creates a new AndroidGpuMetric instance using the specified properties.
             * @function create
             * @memberof perfetto.protos.AndroidGpuMetric
             * @static
             * @param {perfetto.protos.IAndroidGpuMetric=} [properties] Properties to set
             * @returns {perfetto.protos.AndroidGpuMetric} AndroidGpuMetric instance
             */
            AndroidGpuMetric.create = function create(properties) {
                return new AndroidGpuMetric(properties);
            };

            /**
             * Encodes the specified AndroidGpuMetric message. Does not implicitly {@link perfetto.protos.AndroidGpuMetric.verify|verify} messages.
             * @function encode
             * @memberof perfetto.protos.AndroidGpuMetric
             * @static
             * @param {perfetto.protos.IAndroidGpuMetric} message AndroidGpuMetric message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            AndroidGpuMetric.encode = function encode(message, writer) {
                if (!writer)
                    writer = $Writer.create();
                if (message.processes != null && message.processes.length)
                    for (var i = 0; i < message.processes.length; ++i)
                        $root.perfetto.protos.AndroidGpuMetric.Process.encode(message.processes[i], writer.uint32(/* id 1, wireType 2 =*/10).fork()).ldelim();
                if (message.memMax != null && Object.hasOwnProperty.call(message, "memMax"))
                    writer.uint32(/* id 2, wireType 0 =*/16).int64(message.memMax);
                if (message.memMin != null && Object.hasOwnProperty.call(message, "memMin"))
                    writer.uint32(/* id 3, wireType 0 =*/24).int64(message.memMin);
                if (message.memAvg != null && Object.hasOwnProperty.call(message, "memAvg"))
                    writer.uint32(/* id 4, wireType 0 =*/32).int64(message.memAvg);
                return writer;
            };

            /**
             * Encodes the specified AndroidGpuMetric message, length delimited. Does not implicitly {@link perfetto.protos.AndroidGpuMetric.verify|verify} messages.
             * @function encodeDelimited
             * @memberof perfetto.protos.AndroidGpuMetric
             * @static
             * @param {perfetto.protos.IAndroidGpuMetric} message AndroidGpuMetric message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            AndroidGpuMetric.encodeDelimited = function encodeDelimited(message, writer) {
                return this.encode(message, writer).ldelim();
            };

            /**
             * Decodes an AndroidGpuMetric message from the specified reader or buffer.
             * @function decode
             * @memberof perfetto.protos.AndroidGpuMetric
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @param {number} [length] Message length if known beforehand
             * @returns {perfetto.protos.AndroidGpuMetric} AndroidGpuMetric
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            AndroidGpuMetric.decode = function decode(reader, length) {
                if (!(reader instanceof $Reader))
                    reader = $Reader.create(reader);
                var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.AndroidGpuMetric();
                while (reader.pos < end) {
                    var tag = reader.uint32();
                    switch (tag >>> 3) {
                    case 1:
                        if (!(message.processes && message.processes.length))
                            message.processes = [];
                        message.processes.push($root.perfetto.protos.AndroidGpuMetric.Process.decode(reader, reader.uint32()));
                        break;
                    case 2:
                        message.memMax = reader.int64();
                        break;
                    case 3:
                        message.memMin = reader.int64();
                        break;
                    case 4:
                        message.memAvg = reader.int64();
                        break;
                    default:
                        reader.skipType(tag & 7);
                        break;
                    }
                }
                return message;
            };

            /**
             * Decodes an AndroidGpuMetric message from the specified reader or buffer, length delimited.
             * @function decodeDelimited
             * @memberof perfetto.protos.AndroidGpuMetric
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @returns {perfetto.protos.AndroidGpuMetric} AndroidGpuMetric
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            AndroidGpuMetric.decodeDelimited = function decodeDelimited(reader) {
                if (!(reader instanceof $Reader))
                    reader = new $Reader(reader);
                return this.decode(reader, reader.uint32());
            };

            /**
             * Verifies an AndroidGpuMetric message.
             * @function verify
             * @memberof perfetto.protos.AndroidGpuMetric
             * @static
             * @param {Object.<string,*>} message Plain object to verify
             * @returns {string|null} `null` if valid, otherwise the reason why it is not
             */
            AndroidGpuMetric.verify = function verify(message) {
                if (typeof message !== "object" || message === null)
                    return "object expected";
                if (message.processes != null && message.hasOwnProperty("processes")) {
                    if (!Array.isArray(message.processes))
                        return "processes: array expected";
                    for (var i = 0; i < message.processes.length; ++i) {
                        var error = $root.perfetto.protos.AndroidGpuMetric.Process.verify(message.processes[i]);
                        if (error)
                            return "processes." + error;
                    }
                }
                if (message.memMax != null && message.hasOwnProperty("memMax"))
                    if (!$util.isInteger(message.memMax) && !(message.memMax && $util.isInteger(message.memMax.low) && $util.isInteger(message.memMax.high)))
                        return "memMax: integer|Long expected";
                if (message.memMin != null && message.hasOwnProperty("memMin"))
                    if (!$util.isInteger(message.memMin) && !(message.memMin && $util.isInteger(message.memMin.low) && $util.isInteger(message.memMin.high)))
                        return "memMin: integer|Long expected";
                if (message.memAvg != null && message.hasOwnProperty("memAvg"))
                    if (!$util.isInteger(message.memAvg) && !(message.memAvg && $util.isInteger(message.memAvg.low) && $util.isInteger(message.memAvg.high)))
                        return "memAvg: integer|Long expected";
                return null;
            };

            /**
             * Creates an AndroidGpuMetric message from a plain object. Also converts values to their respective internal types.
             * @function fromObject
             * @memberof perfetto.protos.AndroidGpuMetric
             * @static
             * @param {Object.<string,*>} object Plain object
             * @returns {perfetto.protos.AndroidGpuMetric} AndroidGpuMetric
             */
            AndroidGpuMetric.fromObject = function fromObject(object) {
                if (object instanceof $root.perfetto.protos.AndroidGpuMetric)
                    return object;
                var message = new $root.perfetto.protos.AndroidGpuMetric();
                if (object.processes) {
                    if (!Array.isArray(object.processes))
                        throw TypeError(".perfetto.protos.AndroidGpuMetric.processes: array expected");
                    message.processes = [];
                    for (var i = 0; i < object.processes.length; ++i) {
                        if (typeof object.processes[i] !== "object")
                            throw TypeError(".perfetto.protos.AndroidGpuMetric.processes: object expected");
                        message.processes[i] = $root.perfetto.protos.AndroidGpuMetric.Process.fromObject(object.processes[i]);
                    }
                }
                if (object.memMax != null)
                    if ($util.Long)
                        (message.memMax = $util.Long.fromValue(object.memMax)).unsigned = false;
                    else if (typeof object.memMax === "string")
                        message.memMax = parseInt(object.memMax, 10);
                    else if (typeof object.memMax === "number")
                        message.memMax = object.memMax;
                    else if (typeof object.memMax === "object")
                        message.memMax = new $util.LongBits(object.memMax.low >>> 0, object.memMax.high >>> 0).toNumber();
                if (object.memMin != null)
                    if ($util.Long)
                        (message.memMin = $util.Long.fromValue(object.memMin)).unsigned = false;
                    else if (typeof object.memMin === "string")
                        message.memMin = parseInt(object.memMin, 10);
                    else if (typeof object.memMin === "number")
                        message.memMin = object.memMin;
                    else if (typeof object.memMin === "object")
                        message.memMin = new $util.LongBits(object.memMin.low >>> 0, object.memMin.high >>> 0).toNumber();
                if (object.memAvg != null)
                    if ($util.Long)
                        (message.memAvg = $util.Long.fromValue(object.memAvg)).unsigned = false;
                    else if (typeof object.memAvg === "string")
                        message.memAvg = parseInt(object.memAvg, 10);
                    else if (typeof object.memAvg === "number")
                        message.memAvg = object.memAvg;
                    else if (typeof object.memAvg === "object")
                        message.memAvg = new $util.LongBits(object.memAvg.low >>> 0, object.memAvg.high >>> 0).toNumber();
                return message;
            };

            /**
             * Creates a plain object from an AndroidGpuMetric message. Also converts values to other types if specified.
             * @function toObject
             * @memberof perfetto.protos.AndroidGpuMetric
             * @static
             * @param {perfetto.protos.AndroidGpuMetric} message AndroidGpuMetric
             * @param {$protobuf.IConversionOptions} [options] Conversion options
             * @returns {Object.<string,*>} Plain object
             */
            AndroidGpuMetric.toObject = function toObject(message, options) {
                if (!options)
                    options = {};
                var object = {};
                if (options.arrays || options.defaults)
                    object.processes = [];
                if (options.defaults) {
                    if ($util.Long) {
                        var long = new $util.Long(0, 0, false);
                        object.memMax = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
                    } else
                        object.memMax = options.longs === String ? "0" : 0;
                    if ($util.Long) {
                        var long = new $util.Long(0, 0, false);
                        object.memMin = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
                    } else
                        object.memMin = options.longs === String ? "0" : 0;
                    if ($util.Long) {
                        var long = new $util.Long(0, 0, false);
                        object.memAvg = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
                    } else
                        object.memAvg = options.longs === String ? "0" : 0;
                }
                if (message.processes && message.processes.length) {
                    object.processes = [];
                    for (var j = 0; j < message.processes.length; ++j)
                        object.processes[j] = $root.perfetto.protos.AndroidGpuMetric.Process.toObject(message.processes[j], options);
                }
                if (message.memMax != null && message.hasOwnProperty("memMax"))
                    if (typeof message.memMax === "number")
                        object.memMax = options.longs === String ? String(message.memMax) : message.memMax;
                    else
                        object.memMax = options.longs === String ? $util.Long.prototype.toString.call(message.memMax) : options.longs === Number ? new $util.LongBits(message.memMax.low >>> 0, message.memMax.high >>> 0).toNumber() : message.memMax;
                if (message.memMin != null && message.hasOwnProperty("memMin"))
                    if (typeof message.memMin === "number")
                        object.memMin = options.longs === String ? String(message.memMin) : message.memMin;
                    else
                        object.memMin = options.longs === String ? $util.Long.prototype.toString.call(message.memMin) : options.longs === Number ? new $util.LongBits(message.memMin.low >>> 0, message.memMin.high >>> 0).toNumber() : message.memMin;
                if (message.memAvg != null && message.hasOwnProperty("memAvg"))
                    if (typeof message.memAvg === "number")
                        object.memAvg = options.longs === String ? String(message.memAvg) : message.memAvg;
                    else
                        object.memAvg = options.longs === String ? $util.Long.prototype.toString.call(message.memAvg) : options.longs === Number ? new $util.LongBits(message.memAvg.low >>> 0, message.memAvg.high >>> 0).toNumber() : message.memAvg;
                return object;
            };

            /**
             * Converts this AndroidGpuMetric to JSON.
             * @function toJSON
             * @memberof perfetto.protos.AndroidGpuMetric
             * @instance
             * @returns {Object.<string,*>} JSON object
             */
            AndroidGpuMetric.prototype.toJSON = function toJSON() {
                return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
            };

            AndroidGpuMetric.Process = (function() {

                /**
                 * Properties of a Process.
                 * @memberof perfetto.protos.AndroidGpuMetric
                 * @interface IProcess
                 * @property {string|null} [name] Process name
                 * @property {number|null} [memMax] Process memMax
                 * @property {number|null} [memMin] Process memMin
                 * @property {number|null} [memAvg] Process memAvg
                 */

                /**
                 * Constructs a new Process.
                 * @memberof perfetto.protos.AndroidGpuMetric
                 * @classdesc Represents a Process.
                 * @implements IProcess
                 * @constructor
                 * @param {perfetto.protos.AndroidGpuMetric.IProcess=} [properties] Properties to set
                 */
                function Process(properties) {
                    if (properties)
                        for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                            if (properties[keys[i]] != null)
                                this[keys[i]] = properties[keys[i]];
                }

                /**
                 * Process name.
                 * @member {string} name
                 * @memberof perfetto.protos.AndroidGpuMetric.Process
                 * @instance
                 */
                Process.prototype.name = "";

                /**
                 * Process memMax.
                 * @member {number} memMax
                 * @memberof perfetto.protos.AndroidGpuMetric.Process
                 * @instance
                 */
                Process.prototype.memMax = $util.Long ? $util.Long.fromBits(0,0,false) : 0;

                /**
                 * Process memMin.
                 * @member {number} memMin
                 * @memberof perfetto.protos.AndroidGpuMetric.Process
                 * @instance
                 */
                Process.prototype.memMin = $util.Long ? $util.Long.fromBits(0,0,false) : 0;

                /**
                 * Process memAvg.
                 * @member {number} memAvg
                 * @memberof perfetto.protos.AndroidGpuMetric.Process
                 * @instance
                 */
                Process.prototype.memAvg = $util.Long ? $util.Long.fromBits(0,0,false) : 0;

                /**
                 * Creates a new Process instance using the specified properties.
                 * @function create
                 * @memberof perfetto.protos.AndroidGpuMetric.Process
                 * @static
                 * @param {perfetto.protos.AndroidGpuMetric.IProcess=} [properties] Properties to set
                 * @returns {perfetto.protos.AndroidGpuMetric.Process} Process instance
                 */
                Process.create = function create(properties) {
                    return new Process(properties);
                };

                /**
                 * Encodes the specified Process message. Does not implicitly {@link perfetto.protos.AndroidGpuMetric.Process.verify|verify} messages.
                 * @function encode
                 * @memberof perfetto.protos.AndroidGpuMetric.Process
                 * @static
                 * @param {perfetto.protos.AndroidGpuMetric.IProcess} message Process message or plain object to encode
                 * @param {$protobuf.Writer} [writer] Writer to encode to
                 * @returns {$protobuf.Writer} Writer
                 */
                Process.encode = function encode(message, writer) {
                    if (!writer)
                        writer = $Writer.create();
                    if (message.name != null && Object.hasOwnProperty.call(message, "name"))
                        writer.uint32(/* id 1, wireType 2 =*/10).string(message.name);
                    if (message.memMax != null && Object.hasOwnProperty.call(message, "memMax"))
                        writer.uint32(/* id 2, wireType 0 =*/16).int64(message.memMax);
                    if (message.memMin != null && Object.hasOwnProperty.call(message, "memMin"))
                        writer.uint32(/* id 3, wireType 0 =*/24).int64(message.memMin);
                    if (message.memAvg != null && Object.hasOwnProperty.call(message, "memAvg"))
                        writer.uint32(/* id 4, wireType 0 =*/32).int64(message.memAvg);
                    return writer;
                };

                /**
                 * Encodes the specified Process message, length delimited. Does not implicitly {@link perfetto.protos.AndroidGpuMetric.Process.verify|verify} messages.
                 * @function encodeDelimited
                 * @memberof perfetto.protos.AndroidGpuMetric.Process
                 * @static
                 * @param {perfetto.protos.AndroidGpuMetric.IProcess} message Process message or plain object to encode
                 * @param {$protobuf.Writer} [writer] Writer to encode to
                 * @returns {$protobuf.Writer} Writer
                 */
                Process.encodeDelimited = function encodeDelimited(message, writer) {
                    return this.encode(message, writer).ldelim();
                };

                /**
                 * Decodes a Process message from the specified reader or buffer.
                 * @function decode
                 * @memberof perfetto.protos.AndroidGpuMetric.Process
                 * @static
                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                 * @param {number} [length] Message length if known beforehand
                 * @returns {perfetto.protos.AndroidGpuMetric.Process} Process
                 * @throws {Error} If the payload is not a reader or valid buffer
                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
                 */
                Process.decode = function decode(reader, length) {
                    if (!(reader instanceof $Reader))
                        reader = $Reader.create(reader);
                    var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.AndroidGpuMetric.Process();
                    while (reader.pos < end) {
                        var tag = reader.uint32();
                        switch (tag >>> 3) {
                        case 1:
                            message.name = reader.string();
                            break;
                        case 2:
                            message.memMax = reader.int64();
                            break;
                        case 3:
                            message.memMin = reader.int64();
                            break;
                        case 4:
                            message.memAvg = reader.int64();
                            break;
                        default:
                            reader.skipType(tag & 7);
                            break;
                        }
                    }
                    return message;
                };

                /**
                 * Decodes a Process message from the specified reader or buffer, length delimited.
                 * @function decodeDelimited
                 * @memberof perfetto.protos.AndroidGpuMetric.Process
                 * @static
                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                 * @returns {perfetto.protos.AndroidGpuMetric.Process} Process
                 * @throws {Error} If the payload is not a reader or valid buffer
                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
                 */
                Process.decodeDelimited = function decodeDelimited(reader) {
                    if (!(reader instanceof $Reader))
                        reader = new $Reader(reader);
                    return this.decode(reader, reader.uint32());
                };

                /**
                 * Verifies a Process message.
                 * @function verify
                 * @memberof perfetto.protos.AndroidGpuMetric.Process
                 * @static
                 * @param {Object.<string,*>} message Plain object to verify
                 * @returns {string|null} `null` if valid, otherwise the reason why it is not
                 */
                Process.verify = function verify(message) {
                    if (typeof message !== "object" || message === null)
                        return "object expected";
                    if (message.name != null && message.hasOwnProperty("name"))
                        if (!$util.isString(message.name))
                            return "name: string expected";
                    if (message.memMax != null && message.hasOwnProperty("memMax"))
                        if (!$util.isInteger(message.memMax) && !(message.memMax && $util.isInteger(message.memMax.low) && $util.isInteger(message.memMax.high)))
                            return "memMax: integer|Long expected";
                    if (message.memMin != null && message.hasOwnProperty("memMin"))
                        if (!$util.isInteger(message.memMin) && !(message.memMin && $util.isInteger(message.memMin.low) && $util.isInteger(message.memMin.high)))
                            return "memMin: integer|Long expected";
                    if (message.memAvg != null && message.hasOwnProperty("memAvg"))
                        if (!$util.isInteger(message.memAvg) && !(message.memAvg && $util.isInteger(message.memAvg.low) && $util.isInteger(message.memAvg.high)))
                            return "memAvg: integer|Long expected";
                    return null;
                };

                /**
                 * Creates a Process message from a plain object. Also converts values to their respective internal types.
                 * @function fromObject
                 * @memberof perfetto.protos.AndroidGpuMetric.Process
                 * @static
                 * @param {Object.<string,*>} object Plain object
                 * @returns {perfetto.protos.AndroidGpuMetric.Process} Process
                 */
                Process.fromObject = function fromObject(object) {
                    if (object instanceof $root.perfetto.protos.AndroidGpuMetric.Process)
                        return object;
                    var message = new $root.perfetto.protos.AndroidGpuMetric.Process();
                    if (object.name != null)
                        message.name = String(object.name);
                    if (object.memMax != null)
                        if ($util.Long)
                            (message.memMax = $util.Long.fromValue(object.memMax)).unsigned = false;
                        else if (typeof object.memMax === "string")
                            message.memMax = parseInt(object.memMax, 10);
                        else if (typeof object.memMax === "number")
                            message.memMax = object.memMax;
                        else if (typeof object.memMax === "object")
                            message.memMax = new $util.LongBits(object.memMax.low >>> 0, object.memMax.high >>> 0).toNumber();
                    if (object.memMin != null)
                        if ($util.Long)
                            (message.memMin = $util.Long.fromValue(object.memMin)).unsigned = false;
                        else if (typeof object.memMin === "string")
                            message.memMin = parseInt(object.memMin, 10);
                        else if (typeof object.memMin === "number")
                            message.memMin = object.memMin;
                        else if (typeof object.memMin === "object")
                            message.memMin = new $util.LongBits(object.memMin.low >>> 0, object.memMin.high >>> 0).toNumber();
                    if (object.memAvg != null)
                        if ($util.Long)
                            (message.memAvg = $util.Long.fromValue(object.memAvg)).unsigned = false;
                        else if (typeof object.memAvg === "string")
                            message.memAvg = parseInt(object.memAvg, 10);
                        else if (typeof object.memAvg === "number")
                            message.memAvg = object.memAvg;
                        else if (typeof object.memAvg === "object")
                            message.memAvg = new $util.LongBits(object.memAvg.low >>> 0, object.memAvg.high >>> 0).toNumber();
                    return message;
                };

                /**
                 * Creates a plain object from a Process message. Also converts values to other types if specified.
                 * @function toObject
                 * @memberof perfetto.protos.AndroidGpuMetric.Process
                 * @static
                 * @param {perfetto.protos.AndroidGpuMetric.Process} message Process
                 * @param {$protobuf.IConversionOptions} [options] Conversion options
                 * @returns {Object.<string,*>} Plain object
                 */
                Process.toObject = function toObject(message, options) {
                    if (!options)
                        options = {};
                    var object = {};
                    if (options.defaults) {
                        object.name = "";
                        if ($util.Long) {
                            var long = new $util.Long(0, 0, false);
                            object.memMax = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
                        } else
                            object.memMax = options.longs === String ? "0" : 0;
                        if ($util.Long) {
                            var long = new $util.Long(0, 0, false);
                            object.memMin = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
                        } else
                            object.memMin = options.longs === String ? "0" : 0;
                        if ($util.Long) {
                            var long = new $util.Long(0, 0, false);
                            object.memAvg = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
                        } else
                            object.memAvg = options.longs === String ? "0" : 0;
                    }
                    if (message.name != null && message.hasOwnProperty("name"))
                        object.name = message.name;
                    if (message.memMax != null && message.hasOwnProperty("memMax"))
                        if (typeof message.memMax === "number")
                            object.memMax = options.longs === String ? String(message.memMax) : message.memMax;
                        else
                            object.memMax = options.longs === String ? $util.Long.prototype.toString.call(message.memMax) : options.longs === Number ? new $util.LongBits(message.memMax.low >>> 0, message.memMax.high >>> 0).toNumber() : message.memMax;
                    if (message.memMin != null && message.hasOwnProperty("memMin"))
                        if (typeof message.memMin === "number")
                            object.memMin = options.longs === String ? String(message.memMin) : message.memMin;
                        else
                            object.memMin = options.longs === String ? $util.Long.prototype.toString.call(message.memMin) : options.longs === Number ? new $util.LongBits(message.memMin.low >>> 0, message.memMin.high >>> 0).toNumber() : message.memMin;
                    if (message.memAvg != null && message.hasOwnProperty("memAvg"))
                        if (typeof message.memAvg === "number")
                            object.memAvg = options.longs === String ? String(message.memAvg) : message.memAvg;
                        else
                            object.memAvg = options.longs === String ? $util.Long.prototype.toString.call(message.memAvg) : options.longs === Number ? new $util.LongBits(message.memAvg.low >>> 0, message.memAvg.high >>> 0).toNumber() : message.memAvg;
                    return object;
                };

                /**
                 * Converts this Process to JSON.
                 * @function toJSON
                 * @memberof perfetto.protos.AndroidGpuMetric.Process
                 * @instance
                 * @returns {Object.<string,*>} JSON object
                 */
                Process.prototype.toJSON = function toJSON() {
                    return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
                };

                return Process;
            })();

            return AndroidGpuMetric;
        })();

        protos.AndroidHwcomposerMetrics = (function() {

            /**
             * Properties of an AndroidHwcomposerMetrics.
             * @memberof perfetto.protos
             * @interface IAndroidHwcomposerMetrics
             * @property {number|null} [compositionTotalLayers] AndroidHwcomposerMetrics compositionTotalLayers
             * @property {number|null} [compositionDpuLayers] AndroidHwcomposerMetrics compositionDpuLayers
             * @property {number|null} [compositionGpuLayers] AndroidHwcomposerMetrics compositionGpuLayers
             * @property {number|null} [compositionDpuCachedLayers] AndroidHwcomposerMetrics compositionDpuCachedLayers
             * @property {number|null} [compositionSfCachedLayers] AndroidHwcomposerMetrics compositionSfCachedLayers
             * @property {number|null} [skippedValidationCount] AndroidHwcomposerMetrics skippedValidationCount
             * @property {number|null} [unskippedValidationCount] AndroidHwcomposerMetrics unskippedValidationCount
             * @property {number|null} [separatedValidationCount] AndroidHwcomposerMetrics separatedValidationCount
             * @property {number|null} [unknownValidationCount] AndroidHwcomposerMetrics unknownValidationCount
             * @property {number|null} [avgAllExecutionTimeMs] AndroidHwcomposerMetrics avgAllExecutionTimeMs
             * @property {number|null} [avgSkippedExecutionTimeMs] AndroidHwcomposerMetrics avgSkippedExecutionTimeMs
             * @property {number|null} [avgUnskippedExecutionTimeMs] AndroidHwcomposerMetrics avgUnskippedExecutionTimeMs
             * @property {number|null} [avgSeparatedExecutionTimeMs] AndroidHwcomposerMetrics avgSeparatedExecutionTimeMs
             */

            /**
             * Constructs a new AndroidHwcomposerMetrics.
             * @memberof perfetto.protos
             * @classdesc Represents an AndroidHwcomposerMetrics.
             * @implements IAndroidHwcomposerMetrics
             * @constructor
             * @param {perfetto.protos.IAndroidHwcomposerMetrics=} [properties] Properties to set
             */
            function AndroidHwcomposerMetrics(properties) {
                if (properties)
                    for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                        if (properties[keys[i]] != null)
                            this[keys[i]] = properties[keys[i]];
            }

            /**
             * AndroidHwcomposerMetrics compositionTotalLayers.
             * @member {number} compositionTotalLayers
             * @memberof perfetto.protos.AndroidHwcomposerMetrics
             * @instance
             */
            AndroidHwcomposerMetrics.prototype.compositionTotalLayers = 0;

            /**
             * AndroidHwcomposerMetrics compositionDpuLayers.
             * @member {number} compositionDpuLayers
             * @memberof perfetto.protos.AndroidHwcomposerMetrics
             * @instance
             */
            AndroidHwcomposerMetrics.prototype.compositionDpuLayers = 0;

            /**
             * AndroidHwcomposerMetrics compositionGpuLayers.
             * @member {number} compositionGpuLayers
             * @memberof perfetto.protos.AndroidHwcomposerMetrics
             * @instance
             */
            AndroidHwcomposerMetrics.prototype.compositionGpuLayers = 0;

            /**
             * AndroidHwcomposerMetrics compositionDpuCachedLayers.
             * @member {number} compositionDpuCachedLayers
             * @memberof perfetto.protos.AndroidHwcomposerMetrics
             * @instance
             */
            AndroidHwcomposerMetrics.prototype.compositionDpuCachedLayers = 0;

            /**
             * AndroidHwcomposerMetrics compositionSfCachedLayers.
             * @member {number} compositionSfCachedLayers
             * @memberof perfetto.protos.AndroidHwcomposerMetrics
             * @instance
             */
            AndroidHwcomposerMetrics.prototype.compositionSfCachedLayers = 0;

            /**
             * AndroidHwcomposerMetrics skippedValidationCount.
             * @member {number} skippedValidationCount
             * @memberof perfetto.protos.AndroidHwcomposerMetrics
             * @instance
             */
            AndroidHwcomposerMetrics.prototype.skippedValidationCount = 0;

            /**
             * AndroidHwcomposerMetrics unskippedValidationCount.
             * @member {number} unskippedValidationCount
             * @memberof perfetto.protos.AndroidHwcomposerMetrics
             * @instance
             */
            AndroidHwcomposerMetrics.prototype.unskippedValidationCount = 0;

            /**
             * AndroidHwcomposerMetrics separatedValidationCount.
             * @member {number} separatedValidationCount
             * @memberof perfetto.protos.AndroidHwcomposerMetrics
             * @instance
             */
            AndroidHwcomposerMetrics.prototype.separatedValidationCount = 0;

            /**
             * AndroidHwcomposerMetrics unknownValidationCount.
             * @member {number} unknownValidationCount
             * @memberof perfetto.protos.AndroidHwcomposerMetrics
             * @instance
             */
            AndroidHwcomposerMetrics.prototype.unknownValidationCount = 0;

            /**
             * AndroidHwcomposerMetrics avgAllExecutionTimeMs.
             * @member {number} avgAllExecutionTimeMs
             * @memberof perfetto.protos.AndroidHwcomposerMetrics
             * @instance
             */
            AndroidHwcomposerMetrics.prototype.avgAllExecutionTimeMs = 0;

            /**
             * AndroidHwcomposerMetrics avgSkippedExecutionTimeMs.
             * @member {number} avgSkippedExecutionTimeMs
             * @memberof perfetto.protos.AndroidHwcomposerMetrics
             * @instance
             */
            AndroidHwcomposerMetrics.prototype.avgSkippedExecutionTimeMs = 0;

            /**
             * AndroidHwcomposerMetrics avgUnskippedExecutionTimeMs.
             * @member {number} avgUnskippedExecutionTimeMs
             * @memberof perfetto.protos.AndroidHwcomposerMetrics
             * @instance
             */
            AndroidHwcomposerMetrics.prototype.avgUnskippedExecutionTimeMs = 0;

            /**
             * AndroidHwcomposerMetrics avgSeparatedExecutionTimeMs.
             * @member {number} avgSeparatedExecutionTimeMs
             * @memberof perfetto.protos.AndroidHwcomposerMetrics
             * @instance
             */
            AndroidHwcomposerMetrics.prototype.avgSeparatedExecutionTimeMs = 0;

            /**
             * Creates a new AndroidHwcomposerMetrics instance using the specified properties.
             * @function create
             * @memberof perfetto.protos.AndroidHwcomposerMetrics
             * @static
             * @param {perfetto.protos.IAndroidHwcomposerMetrics=} [properties] Properties to set
             * @returns {perfetto.protos.AndroidHwcomposerMetrics} AndroidHwcomposerMetrics instance
             */
            AndroidHwcomposerMetrics.create = function create(properties) {
                return new AndroidHwcomposerMetrics(properties);
            };

            /**
             * Encodes the specified AndroidHwcomposerMetrics message. Does not implicitly {@link perfetto.protos.AndroidHwcomposerMetrics.verify|verify} messages.
             * @function encode
             * @memberof perfetto.protos.AndroidHwcomposerMetrics
             * @static
             * @param {perfetto.protos.IAndroidHwcomposerMetrics} message AndroidHwcomposerMetrics message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            AndroidHwcomposerMetrics.encode = function encode(message, writer) {
                if (!writer)
                    writer = $Writer.create();
                if (message.compositionTotalLayers != null && Object.hasOwnProperty.call(message, "compositionTotalLayers"))
                    writer.uint32(/* id 1, wireType 1 =*/9).double(message.compositionTotalLayers);
                if (message.compositionDpuLayers != null && Object.hasOwnProperty.call(message, "compositionDpuLayers"))
                    writer.uint32(/* id 2, wireType 1 =*/17).double(message.compositionDpuLayers);
                if (message.compositionGpuLayers != null && Object.hasOwnProperty.call(message, "compositionGpuLayers"))
                    writer.uint32(/* id 3, wireType 1 =*/25).double(message.compositionGpuLayers);
                if (message.compositionDpuCachedLayers != null && Object.hasOwnProperty.call(message, "compositionDpuCachedLayers"))
                    writer.uint32(/* id 4, wireType 1 =*/33).double(message.compositionDpuCachedLayers);
                if (message.compositionSfCachedLayers != null && Object.hasOwnProperty.call(message, "compositionSfCachedLayers"))
                    writer.uint32(/* id 5, wireType 1 =*/41).double(message.compositionSfCachedLayers);
                if (message.skippedValidationCount != null && Object.hasOwnProperty.call(message, "skippedValidationCount"))
                    writer.uint32(/* id 6, wireType 0 =*/48).int32(message.skippedValidationCount);
                if (message.unskippedValidationCount != null && Object.hasOwnProperty.call(message, "unskippedValidationCount"))
                    writer.uint32(/* id 7, wireType 0 =*/56).int32(message.unskippedValidationCount);
                if (message.separatedValidationCount != null && Object.hasOwnProperty.call(message, "separatedValidationCount"))
                    writer.uint32(/* id 8, wireType 0 =*/64).int32(message.separatedValidationCount);
                if (message.unknownValidationCount != null && Object.hasOwnProperty.call(message, "unknownValidationCount"))
                    writer.uint32(/* id 9, wireType 0 =*/72).int32(message.unknownValidationCount);
                if (message.avgAllExecutionTimeMs != null && Object.hasOwnProperty.call(message, "avgAllExecutionTimeMs"))
                    writer.uint32(/* id 10, wireType 1 =*/81).double(message.avgAllExecutionTimeMs);
                if (message.avgSkippedExecutionTimeMs != null && Object.hasOwnProperty.call(message, "avgSkippedExecutionTimeMs"))
                    writer.uint32(/* id 11, wireType 1 =*/89).double(message.avgSkippedExecutionTimeMs);
                if (message.avgUnskippedExecutionTimeMs != null && Object.hasOwnProperty.call(message, "avgUnskippedExecutionTimeMs"))
                    writer.uint32(/* id 12, wireType 1 =*/97).double(message.avgUnskippedExecutionTimeMs);
                if (message.avgSeparatedExecutionTimeMs != null && Object.hasOwnProperty.call(message, "avgSeparatedExecutionTimeMs"))
                    writer.uint32(/* id 13, wireType 1 =*/105).double(message.avgSeparatedExecutionTimeMs);
                return writer;
            };

            /**
             * Encodes the specified AndroidHwcomposerMetrics message, length delimited. Does not implicitly {@link perfetto.protos.AndroidHwcomposerMetrics.verify|verify} messages.
             * @function encodeDelimited
             * @memberof perfetto.protos.AndroidHwcomposerMetrics
             * @static
             * @param {perfetto.protos.IAndroidHwcomposerMetrics} message AndroidHwcomposerMetrics message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            AndroidHwcomposerMetrics.encodeDelimited = function encodeDelimited(message, writer) {
                return this.encode(message, writer).ldelim();
            };

            /**
             * Decodes an AndroidHwcomposerMetrics message from the specified reader or buffer.
             * @function decode
             * @memberof perfetto.protos.AndroidHwcomposerMetrics
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @param {number} [length] Message length if known beforehand
             * @returns {perfetto.protos.AndroidHwcomposerMetrics} AndroidHwcomposerMetrics
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            AndroidHwcomposerMetrics.decode = function decode(reader, length) {
                if (!(reader instanceof $Reader))
                    reader = $Reader.create(reader);
                var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.AndroidHwcomposerMetrics();
                while (reader.pos < end) {
                    var tag = reader.uint32();
                    switch (tag >>> 3) {
                    case 1:
                        message.compositionTotalLayers = reader.double();
                        break;
                    case 2:
                        message.compositionDpuLayers = reader.double();
                        break;
                    case 3:
                        message.compositionGpuLayers = reader.double();
                        break;
                    case 4:
                        message.compositionDpuCachedLayers = reader.double();
                        break;
                    case 5:
                        message.compositionSfCachedLayers = reader.double();
                        break;
                    case 6:
                        message.skippedValidationCount = reader.int32();
                        break;
                    case 7:
                        message.unskippedValidationCount = reader.int32();
                        break;
                    case 8:
                        message.separatedValidationCount = reader.int32();
                        break;
                    case 9:
                        message.unknownValidationCount = reader.int32();
                        break;
                    case 10:
                        message.avgAllExecutionTimeMs = reader.double();
                        break;
                    case 11:
                        message.avgSkippedExecutionTimeMs = reader.double();
                        break;
                    case 12:
                        message.avgUnskippedExecutionTimeMs = reader.double();
                        break;
                    case 13:
                        message.avgSeparatedExecutionTimeMs = reader.double();
                        break;
                    default:
                        reader.skipType(tag & 7);
                        break;
                    }
                }
                return message;
            };

            /**
             * Decodes an AndroidHwcomposerMetrics message from the specified reader or buffer, length delimited.
             * @function decodeDelimited
             * @memberof perfetto.protos.AndroidHwcomposerMetrics
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @returns {perfetto.protos.AndroidHwcomposerMetrics} AndroidHwcomposerMetrics
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            AndroidHwcomposerMetrics.decodeDelimited = function decodeDelimited(reader) {
                if (!(reader instanceof $Reader))
                    reader = new $Reader(reader);
                return this.decode(reader, reader.uint32());
            };

            /**
             * Verifies an AndroidHwcomposerMetrics message.
             * @function verify
             * @memberof perfetto.protos.AndroidHwcomposerMetrics
             * @static
             * @param {Object.<string,*>} message Plain object to verify
             * @returns {string|null} `null` if valid, otherwise the reason why it is not
             */
            AndroidHwcomposerMetrics.verify = function verify(message) {
                if (typeof message !== "object" || message === null)
                    return "object expected";
                if (message.compositionTotalLayers != null && message.hasOwnProperty("compositionTotalLayers"))
                    if (typeof message.compositionTotalLayers !== "number")
                        return "compositionTotalLayers: number expected";
                if (message.compositionDpuLayers != null && message.hasOwnProperty("compositionDpuLayers"))
                    if (typeof message.compositionDpuLayers !== "number")
                        return "compositionDpuLayers: number expected";
                if (message.compositionGpuLayers != null && message.hasOwnProperty("compositionGpuLayers"))
                    if (typeof message.compositionGpuLayers !== "number")
                        return "compositionGpuLayers: number expected";
                if (message.compositionDpuCachedLayers != null && message.hasOwnProperty("compositionDpuCachedLayers"))
                    if (typeof message.compositionDpuCachedLayers !== "number")
                        return "compositionDpuCachedLayers: number expected";
                if (message.compositionSfCachedLayers != null && message.hasOwnProperty("compositionSfCachedLayers"))
                    if (typeof message.compositionSfCachedLayers !== "number")
                        return "compositionSfCachedLayers: number expected";
                if (message.skippedValidationCount != null && message.hasOwnProperty("skippedValidationCount"))
                    if (!$util.isInteger(message.skippedValidationCount))
                        return "skippedValidationCount: integer expected";
                if (message.unskippedValidationCount != null && message.hasOwnProperty("unskippedValidationCount"))
                    if (!$util.isInteger(message.unskippedValidationCount))
                        return "unskippedValidationCount: integer expected";
                if (message.separatedValidationCount != null && message.hasOwnProperty("separatedValidationCount"))
                    if (!$util.isInteger(message.separatedValidationCount))
                        return "separatedValidationCount: integer expected";
                if (message.unknownValidationCount != null && message.hasOwnProperty("unknownValidationCount"))
                    if (!$util.isInteger(message.unknownValidationCount))
                        return "unknownValidationCount: integer expected";
                if (message.avgAllExecutionTimeMs != null && message.hasOwnProperty("avgAllExecutionTimeMs"))
                    if (typeof message.avgAllExecutionTimeMs !== "number")
                        return "avgAllExecutionTimeMs: number expected";
                if (message.avgSkippedExecutionTimeMs != null && message.hasOwnProperty("avgSkippedExecutionTimeMs"))
                    if (typeof message.avgSkippedExecutionTimeMs !== "number")
                        return "avgSkippedExecutionTimeMs: number expected";
                if (message.avgUnskippedExecutionTimeMs != null && message.hasOwnProperty("avgUnskippedExecutionTimeMs"))
                    if (typeof message.avgUnskippedExecutionTimeMs !== "number")
                        return "avgUnskippedExecutionTimeMs: number expected";
                if (message.avgSeparatedExecutionTimeMs != null && message.hasOwnProperty("avgSeparatedExecutionTimeMs"))
                    if (typeof message.avgSeparatedExecutionTimeMs !== "number")
                        return "avgSeparatedExecutionTimeMs: number expected";
                return null;
            };

            /**
             * Creates an AndroidHwcomposerMetrics message from a plain object. Also converts values to their respective internal types.
             * @function fromObject
             * @memberof perfetto.protos.AndroidHwcomposerMetrics
             * @static
             * @param {Object.<string,*>} object Plain object
             * @returns {perfetto.protos.AndroidHwcomposerMetrics} AndroidHwcomposerMetrics
             */
            AndroidHwcomposerMetrics.fromObject = function fromObject(object) {
                if (object instanceof $root.perfetto.protos.AndroidHwcomposerMetrics)
                    return object;
                var message = new $root.perfetto.protos.AndroidHwcomposerMetrics();
                if (object.compositionTotalLayers != null)
                    message.compositionTotalLayers = Number(object.compositionTotalLayers);
                if (object.compositionDpuLayers != null)
                    message.compositionDpuLayers = Number(object.compositionDpuLayers);
                if (object.compositionGpuLayers != null)
                    message.compositionGpuLayers = Number(object.compositionGpuLayers);
                if (object.compositionDpuCachedLayers != null)
                    message.compositionDpuCachedLayers = Number(object.compositionDpuCachedLayers);
                if (object.compositionSfCachedLayers != null)
                    message.compositionSfCachedLayers = Number(object.compositionSfCachedLayers);
                if (object.skippedValidationCount != null)
                    message.skippedValidationCount = object.skippedValidationCount | 0;
                if (object.unskippedValidationCount != null)
                    message.unskippedValidationCount = object.unskippedValidationCount | 0;
                if (object.separatedValidationCount != null)
                    message.separatedValidationCount = object.separatedValidationCount | 0;
                if (object.unknownValidationCount != null)
                    message.unknownValidationCount = object.unknownValidationCount | 0;
                if (object.avgAllExecutionTimeMs != null)
                    message.avgAllExecutionTimeMs = Number(object.avgAllExecutionTimeMs);
                if (object.avgSkippedExecutionTimeMs != null)
                    message.avgSkippedExecutionTimeMs = Number(object.avgSkippedExecutionTimeMs);
                if (object.avgUnskippedExecutionTimeMs != null)
                    message.avgUnskippedExecutionTimeMs = Number(object.avgUnskippedExecutionTimeMs);
                if (object.avgSeparatedExecutionTimeMs != null)
                    message.avgSeparatedExecutionTimeMs = Number(object.avgSeparatedExecutionTimeMs);
                return message;
            };

            /**
             * Creates a plain object from an AndroidHwcomposerMetrics message. Also converts values to other types if specified.
             * @function toObject
             * @memberof perfetto.protos.AndroidHwcomposerMetrics
             * @static
             * @param {perfetto.protos.AndroidHwcomposerMetrics} message AndroidHwcomposerMetrics
             * @param {$protobuf.IConversionOptions} [options] Conversion options
             * @returns {Object.<string,*>} Plain object
             */
            AndroidHwcomposerMetrics.toObject = function toObject(message, options) {
                if (!options)
                    options = {};
                var object = {};
                if (options.defaults) {
                    object.compositionTotalLayers = 0;
                    object.compositionDpuLayers = 0;
                    object.compositionGpuLayers = 0;
                    object.compositionDpuCachedLayers = 0;
                    object.compositionSfCachedLayers = 0;
                    object.skippedValidationCount = 0;
                    object.unskippedValidationCount = 0;
                    object.separatedValidationCount = 0;
                    object.unknownValidationCount = 0;
                    object.avgAllExecutionTimeMs = 0;
                    object.avgSkippedExecutionTimeMs = 0;
                    object.avgUnskippedExecutionTimeMs = 0;
                    object.avgSeparatedExecutionTimeMs = 0;
                }
                if (message.compositionTotalLayers != null && message.hasOwnProperty("compositionTotalLayers"))
                    object.compositionTotalLayers = options.json && !isFinite(message.compositionTotalLayers) ? String(message.compositionTotalLayers) : message.compositionTotalLayers;
                if (message.compositionDpuLayers != null && message.hasOwnProperty("compositionDpuLayers"))
                    object.compositionDpuLayers = options.json && !isFinite(message.compositionDpuLayers) ? String(message.compositionDpuLayers) : message.compositionDpuLayers;
                if (message.compositionGpuLayers != null && message.hasOwnProperty("compositionGpuLayers"))
                    object.compositionGpuLayers = options.json && !isFinite(message.compositionGpuLayers) ? String(message.compositionGpuLayers) : message.compositionGpuLayers;
                if (message.compositionDpuCachedLayers != null && message.hasOwnProperty("compositionDpuCachedLayers"))
                    object.compositionDpuCachedLayers = options.json && !isFinite(message.compositionDpuCachedLayers) ? String(message.compositionDpuCachedLayers) : message.compositionDpuCachedLayers;
                if (message.compositionSfCachedLayers != null && message.hasOwnProperty("compositionSfCachedLayers"))
                    object.compositionSfCachedLayers = options.json && !isFinite(message.compositionSfCachedLayers) ? String(message.compositionSfCachedLayers) : message.compositionSfCachedLayers;
                if (message.skippedValidationCount != null && message.hasOwnProperty("skippedValidationCount"))
                    object.skippedValidationCount = message.skippedValidationCount;
                if (message.unskippedValidationCount != null && message.hasOwnProperty("unskippedValidationCount"))
                    object.unskippedValidationCount = message.unskippedValidationCount;
                if (message.separatedValidationCount != null && message.hasOwnProperty("separatedValidationCount"))
                    object.separatedValidationCount = message.separatedValidationCount;
                if (message.unknownValidationCount != null && message.hasOwnProperty("unknownValidationCount"))
                    object.unknownValidationCount = message.unknownValidationCount;
                if (message.avgAllExecutionTimeMs != null && message.hasOwnProperty("avgAllExecutionTimeMs"))
                    object.avgAllExecutionTimeMs = options.json && !isFinite(message.avgAllExecutionTimeMs) ? String(message.avgAllExecutionTimeMs) : message.avgAllExecutionTimeMs;
                if (message.avgSkippedExecutionTimeMs != null && message.hasOwnProperty("avgSkippedExecutionTimeMs"))
                    object.avgSkippedExecutionTimeMs = options.json && !isFinite(message.avgSkippedExecutionTimeMs) ? String(message.avgSkippedExecutionTimeMs) : message.avgSkippedExecutionTimeMs;
                if (message.avgUnskippedExecutionTimeMs != null && message.hasOwnProperty("avgUnskippedExecutionTimeMs"))
                    object.avgUnskippedExecutionTimeMs = options.json && !isFinite(message.avgUnskippedExecutionTimeMs) ? String(message.avgUnskippedExecutionTimeMs) : message.avgUnskippedExecutionTimeMs;
                if (message.avgSeparatedExecutionTimeMs != null && message.hasOwnProperty("avgSeparatedExecutionTimeMs"))
                    object.avgSeparatedExecutionTimeMs = options.json && !isFinite(message.avgSeparatedExecutionTimeMs) ? String(message.avgSeparatedExecutionTimeMs) : message.avgSeparatedExecutionTimeMs;
                return object;
            };

            /**
             * Converts this AndroidHwcomposerMetrics to JSON.
             * @function toJSON
             * @memberof perfetto.protos.AndroidHwcomposerMetrics
             * @instance
             * @returns {Object.<string,*>} JSON object
             */
            AndroidHwcomposerMetrics.prototype.toJSON = function toJSON() {
                return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
            };

            return AndroidHwcomposerMetrics;
        })();

        protos.ProcessRenderInfo = (function() {

            /**
             * Properties of a ProcessRenderInfo.
             * @memberof perfetto.protos
             * @interface IProcessRenderInfo
             * @property {string|null} [processName] ProcessRenderInfo processName
             * @property {number|null} [rtCpuTimeMs] ProcessRenderInfo rtCpuTimeMs
             * @property {number|null} [drawFrameCount] ProcessRenderInfo drawFrameCount
             * @property {number|null} [drawFrameMax] ProcessRenderInfo drawFrameMax
             * @property {number|null} [drawFrameMin] ProcessRenderInfo drawFrameMin
             * @property {number|null} [drawFrameAvg] ProcessRenderInfo drawFrameAvg
             * @property {number|null} [flushCount] ProcessRenderInfo flushCount
             * @property {number|null} [flushMax] ProcessRenderInfo flushMax
             * @property {number|null} [flushMin] ProcessRenderInfo flushMin
             * @property {number|null} [flushAvg] ProcessRenderInfo flushAvg
             * @property {number|null} [prepareTreeCount] ProcessRenderInfo prepareTreeCount
             * @property {number|null} [prepareTreeMax] ProcessRenderInfo prepareTreeMax
             * @property {number|null} [prepareTreeMin] ProcessRenderInfo prepareTreeMin
             * @property {number|null} [prepareTreeAvg] ProcessRenderInfo prepareTreeAvg
             * @property {number|null} [gpuCompletionCount] ProcessRenderInfo gpuCompletionCount
             * @property {number|null} [gpuCompletionMax] ProcessRenderInfo gpuCompletionMax
             * @property {number|null} [gpuCompletionMin] ProcessRenderInfo gpuCompletionMin
             * @property {number|null} [gpuCompletionAvg] ProcessRenderInfo gpuCompletionAvg
             * @property {number|null} [uiRecordCount] ProcessRenderInfo uiRecordCount
             * @property {number|null} [uiRecordMax] ProcessRenderInfo uiRecordMax
             * @property {number|null} [uiRecordMin] ProcessRenderInfo uiRecordMin
             * @property {number|null} [uiRecordAvg] ProcessRenderInfo uiRecordAvg
             * @property {number|null} [shaderCompileCount] ProcessRenderInfo shaderCompileCount
             * @property {number|null} [shaderCompileTime] ProcessRenderInfo shaderCompileTime
             * @property {number|null} [shaderCompileAvg] ProcessRenderInfo shaderCompileAvg
             * @property {number|null} [cacheHitCount] ProcessRenderInfo cacheHitCount
             * @property {number|null} [cacheHitTime] ProcessRenderInfo cacheHitTime
             * @property {number|null} [cacheHitAvg] ProcessRenderInfo cacheHitAvg
             * @property {number|null} [cacheMissCount] ProcessRenderInfo cacheMissCount
             * @property {number|null} [cacheMissTime] ProcessRenderInfo cacheMissTime
             * @property {number|null} [cacheMissAvg] ProcessRenderInfo cacheMissAvg
             * @property {number|null} [graphicsCpuMemMax] ProcessRenderInfo graphicsCpuMemMax
             * @property {number|null} [graphicsCpuMemMin] ProcessRenderInfo graphicsCpuMemMin
             * @property {number|null} [graphicsCpuMemAvg] ProcessRenderInfo graphicsCpuMemAvg
             * @property {number|null} [graphicsGpuMemMax] ProcessRenderInfo graphicsGpuMemMax
             * @property {number|null} [graphicsGpuMemMin] ProcessRenderInfo graphicsGpuMemMin
             * @property {number|null} [graphicsGpuMemAvg] ProcessRenderInfo graphicsGpuMemAvg
             * @property {number|null} [textureMemMax] ProcessRenderInfo textureMemMax
             * @property {number|null} [textureMemMin] ProcessRenderInfo textureMemMin
             * @property {number|null} [textureMemAvg] ProcessRenderInfo textureMemAvg
             * @property {number|null} [allMemMax] ProcessRenderInfo allMemMax
             * @property {number|null} [allMemMin] ProcessRenderInfo allMemMin
             * @property {number|null} [allMemAvg] ProcessRenderInfo allMemAvg
             */

            /**
             * Constructs a new ProcessRenderInfo.
             * @memberof perfetto.protos
             * @classdesc Represents a ProcessRenderInfo.
             * @implements IProcessRenderInfo
             * @constructor
             * @param {perfetto.protos.IProcessRenderInfo=} [properties] Properties to set
             */
            function ProcessRenderInfo(properties) {
                if (properties)
                    for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                        if (properties[keys[i]] != null)
                            this[keys[i]] = properties[keys[i]];
            }

            /**
             * ProcessRenderInfo processName.
             * @member {string} processName
             * @memberof perfetto.protos.ProcessRenderInfo
             * @instance
             */
            ProcessRenderInfo.prototype.processName = "";

            /**
             * ProcessRenderInfo rtCpuTimeMs.
             * @member {number} rtCpuTimeMs
             * @memberof perfetto.protos.ProcessRenderInfo
             * @instance
             */
            ProcessRenderInfo.prototype.rtCpuTimeMs = $util.Long ? $util.Long.fromBits(0,0,false) : 0;

            /**
             * ProcessRenderInfo drawFrameCount.
             * @member {number} drawFrameCount
             * @memberof perfetto.protos.ProcessRenderInfo
             * @instance
             */
            ProcessRenderInfo.prototype.drawFrameCount = 0;

            /**
             * ProcessRenderInfo drawFrameMax.
             * @member {number} drawFrameMax
             * @memberof perfetto.protos.ProcessRenderInfo
             * @instance
             */
            ProcessRenderInfo.prototype.drawFrameMax = $util.Long ? $util.Long.fromBits(0,0,false) : 0;

            /**
             * ProcessRenderInfo drawFrameMin.
             * @member {number} drawFrameMin
             * @memberof perfetto.protos.ProcessRenderInfo
             * @instance
             */
            ProcessRenderInfo.prototype.drawFrameMin = $util.Long ? $util.Long.fromBits(0,0,false) : 0;

            /**
             * ProcessRenderInfo drawFrameAvg.
             * @member {number} drawFrameAvg
             * @memberof perfetto.protos.ProcessRenderInfo
             * @instance
             */
            ProcessRenderInfo.prototype.drawFrameAvg = 0;

            /**
             * ProcessRenderInfo flushCount.
             * @member {number} flushCount
             * @memberof perfetto.protos.ProcessRenderInfo
             * @instance
             */
            ProcessRenderInfo.prototype.flushCount = 0;

            /**
             * ProcessRenderInfo flushMax.
             * @member {number} flushMax
             * @memberof perfetto.protos.ProcessRenderInfo
             * @instance
             */
            ProcessRenderInfo.prototype.flushMax = $util.Long ? $util.Long.fromBits(0,0,false) : 0;

            /**
             * ProcessRenderInfo flushMin.
             * @member {number} flushMin
             * @memberof perfetto.protos.ProcessRenderInfo
             * @instance
             */
            ProcessRenderInfo.prototype.flushMin = $util.Long ? $util.Long.fromBits(0,0,false) : 0;

            /**
             * ProcessRenderInfo flushAvg.
             * @member {number} flushAvg
             * @memberof perfetto.protos.ProcessRenderInfo
             * @instance
             */
            ProcessRenderInfo.prototype.flushAvg = 0;

            /**
             * ProcessRenderInfo prepareTreeCount.
             * @member {number} prepareTreeCount
             * @memberof perfetto.protos.ProcessRenderInfo
             * @instance
             */
            ProcessRenderInfo.prototype.prepareTreeCount = 0;

            /**
             * ProcessRenderInfo prepareTreeMax.
             * @member {number} prepareTreeMax
             * @memberof perfetto.protos.ProcessRenderInfo
             * @instance
             */
            ProcessRenderInfo.prototype.prepareTreeMax = $util.Long ? $util.Long.fromBits(0,0,false) : 0;

            /**
             * ProcessRenderInfo prepareTreeMin.
             * @member {number} prepareTreeMin
             * @memberof perfetto.protos.ProcessRenderInfo
             * @instance
             */
            ProcessRenderInfo.prototype.prepareTreeMin = $util.Long ? $util.Long.fromBits(0,0,false) : 0;

            /**
             * ProcessRenderInfo prepareTreeAvg.
             * @member {number} prepareTreeAvg
             * @memberof perfetto.protos.ProcessRenderInfo
             * @instance
             */
            ProcessRenderInfo.prototype.prepareTreeAvg = 0;

            /**
             * ProcessRenderInfo gpuCompletionCount.
             * @member {number} gpuCompletionCount
             * @memberof perfetto.protos.ProcessRenderInfo
             * @instance
             */
            ProcessRenderInfo.prototype.gpuCompletionCount = 0;

            /**
             * ProcessRenderInfo gpuCompletionMax.
             * @member {number} gpuCompletionMax
             * @memberof perfetto.protos.ProcessRenderInfo
             * @instance
             */
            ProcessRenderInfo.prototype.gpuCompletionMax = $util.Long ? $util.Long.fromBits(0,0,false) : 0;

            /**
             * ProcessRenderInfo gpuCompletionMin.
             * @member {number} gpuCompletionMin
             * @memberof perfetto.protos.ProcessRenderInfo
             * @instance
             */
            ProcessRenderInfo.prototype.gpuCompletionMin = $util.Long ? $util.Long.fromBits(0,0,false) : 0;

            /**
             * ProcessRenderInfo gpuCompletionAvg.
             * @member {number} gpuCompletionAvg
             * @memberof perfetto.protos.ProcessRenderInfo
             * @instance
             */
            ProcessRenderInfo.prototype.gpuCompletionAvg = 0;

            /**
             * ProcessRenderInfo uiRecordCount.
             * @member {number} uiRecordCount
             * @memberof perfetto.protos.ProcessRenderInfo
             * @instance
             */
            ProcessRenderInfo.prototype.uiRecordCount = 0;

            /**
             * ProcessRenderInfo uiRecordMax.
             * @member {number} uiRecordMax
             * @memberof perfetto.protos.ProcessRenderInfo
             * @instance
             */
            ProcessRenderInfo.prototype.uiRecordMax = $util.Long ? $util.Long.fromBits(0,0,false) : 0;

            /**
             * ProcessRenderInfo uiRecordMin.
             * @member {number} uiRecordMin
             * @memberof perfetto.protos.ProcessRenderInfo
             * @instance
             */
            ProcessRenderInfo.prototype.uiRecordMin = $util.Long ? $util.Long.fromBits(0,0,false) : 0;

            /**
             * ProcessRenderInfo uiRecordAvg.
             * @member {number} uiRecordAvg
             * @memberof perfetto.protos.ProcessRenderInfo
             * @instance
             */
            ProcessRenderInfo.prototype.uiRecordAvg = 0;

            /**
             * ProcessRenderInfo shaderCompileCount.
             * @member {number} shaderCompileCount
             * @memberof perfetto.protos.ProcessRenderInfo
             * @instance
             */
            ProcessRenderInfo.prototype.shaderCompileCount = 0;

            /**
             * ProcessRenderInfo shaderCompileTime.
             * @member {number} shaderCompileTime
             * @memberof perfetto.protos.ProcessRenderInfo
             * @instance
             */
            ProcessRenderInfo.prototype.shaderCompileTime = $util.Long ? $util.Long.fromBits(0,0,false) : 0;

            /**
             * ProcessRenderInfo shaderCompileAvg.
             * @member {number} shaderCompileAvg
             * @memberof perfetto.protos.ProcessRenderInfo
             * @instance
             */
            ProcessRenderInfo.prototype.shaderCompileAvg = 0;

            /**
             * ProcessRenderInfo cacheHitCount.
             * @member {number} cacheHitCount
             * @memberof perfetto.protos.ProcessRenderInfo
             * @instance
             */
            ProcessRenderInfo.prototype.cacheHitCount = 0;

            /**
             * ProcessRenderInfo cacheHitTime.
             * @member {number} cacheHitTime
             * @memberof perfetto.protos.ProcessRenderInfo
             * @instance
             */
            ProcessRenderInfo.prototype.cacheHitTime = $util.Long ? $util.Long.fromBits(0,0,false) : 0;

            /**
             * ProcessRenderInfo cacheHitAvg.
             * @member {number} cacheHitAvg
             * @memberof perfetto.protos.ProcessRenderInfo
             * @instance
             */
            ProcessRenderInfo.prototype.cacheHitAvg = 0;

            /**
             * ProcessRenderInfo cacheMissCount.
             * @member {number} cacheMissCount
             * @memberof perfetto.protos.ProcessRenderInfo
             * @instance
             */
            ProcessRenderInfo.prototype.cacheMissCount = 0;

            /**
             * ProcessRenderInfo cacheMissTime.
             * @member {number} cacheMissTime
             * @memberof perfetto.protos.ProcessRenderInfo
             * @instance
             */
            ProcessRenderInfo.prototype.cacheMissTime = $util.Long ? $util.Long.fromBits(0,0,false) : 0;

            /**
             * ProcessRenderInfo cacheMissAvg.
             * @member {number} cacheMissAvg
             * @memberof perfetto.protos.ProcessRenderInfo
             * @instance
             */
            ProcessRenderInfo.prototype.cacheMissAvg = 0;

            /**
             * ProcessRenderInfo graphicsCpuMemMax.
             * @member {number} graphicsCpuMemMax
             * @memberof perfetto.protos.ProcessRenderInfo
             * @instance
             */
            ProcessRenderInfo.prototype.graphicsCpuMemMax = $util.Long ? $util.Long.fromBits(0,0,false) : 0;

            /**
             * ProcessRenderInfo graphicsCpuMemMin.
             * @member {number} graphicsCpuMemMin
             * @memberof perfetto.protos.ProcessRenderInfo
             * @instance
             */
            ProcessRenderInfo.prototype.graphicsCpuMemMin = $util.Long ? $util.Long.fromBits(0,0,false) : 0;

            /**
             * ProcessRenderInfo graphicsCpuMemAvg.
             * @member {number} graphicsCpuMemAvg
             * @memberof perfetto.protos.ProcessRenderInfo
             * @instance
             */
            ProcessRenderInfo.prototype.graphicsCpuMemAvg = 0;

            /**
             * ProcessRenderInfo graphicsGpuMemMax.
             * @member {number} graphicsGpuMemMax
             * @memberof perfetto.protos.ProcessRenderInfo
             * @instance
             */
            ProcessRenderInfo.prototype.graphicsGpuMemMax = $util.Long ? $util.Long.fromBits(0,0,false) : 0;

            /**
             * ProcessRenderInfo graphicsGpuMemMin.
             * @member {number} graphicsGpuMemMin
             * @memberof perfetto.protos.ProcessRenderInfo
             * @instance
             */
            ProcessRenderInfo.prototype.graphicsGpuMemMin = $util.Long ? $util.Long.fromBits(0,0,false) : 0;

            /**
             * ProcessRenderInfo graphicsGpuMemAvg.
             * @member {number} graphicsGpuMemAvg
             * @memberof perfetto.protos.ProcessRenderInfo
             * @instance
             */
            ProcessRenderInfo.prototype.graphicsGpuMemAvg = 0;

            /**
             * ProcessRenderInfo textureMemMax.
             * @member {number} textureMemMax
             * @memberof perfetto.protos.ProcessRenderInfo
             * @instance
             */
            ProcessRenderInfo.prototype.textureMemMax = $util.Long ? $util.Long.fromBits(0,0,false) : 0;

            /**
             * ProcessRenderInfo textureMemMin.
             * @member {number} textureMemMin
             * @memberof perfetto.protos.ProcessRenderInfo
             * @instance
             */
            ProcessRenderInfo.prototype.textureMemMin = $util.Long ? $util.Long.fromBits(0,0,false) : 0;

            /**
             * ProcessRenderInfo textureMemAvg.
             * @member {number} textureMemAvg
             * @memberof perfetto.protos.ProcessRenderInfo
             * @instance
             */
            ProcessRenderInfo.prototype.textureMemAvg = 0;

            /**
             * ProcessRenderInfo allMemMax.
             * @member {number} allMemMax
             * @memberof perfetto.protos.ProcessRenderInfo
             * @instance
             */
            ProcessRenderInfo.prototype.allMemMax = $util.Long ? $util.Long.fromBits(0,0,false) : 0;

            /**
             * ProcessRenderInfo allMemMin.
             * @member {number} allMemMin
             * @memberof perfetto.protos.ProcessRenderInfo
             * @instance
             */
            ProcessRenderInfo.prototype.allMemMin = $util.Long ? $util.Long.fromBits(0,0,false) : 0;

            /**
             * ProcessRenderInfo allMemAvg.
             * @member {number} allMemAvg
             * @memberof perfetto.protos.ProcessRenderInfo
             * @instance
             */
            ProcessRenderInfo.prototype.allMemAvg = 0;

            /**
             * Creates a new ProcessRenderInfo instance using the specified properties.
             * @function create
             * @memberof perfetto.protos.ProcessRenderInfo
             * @static
             * @param {perfetto.protos.IProcessRenderInfo=} [properties] Properties to set
             * @returns {perfetto.protos.ProcessRenderInfo} ProcessRenderInfo instance
             */
            ProcessRenderInfo.create = function create(properties) {
                return new ProcessRenderInfo(properties);
            };

            /**
             * Encodes the specified ProcessRenderInfo message. Does not implicitly {@link perfetto.protos.ProcessRenderInfo.verify|verify} messages.
             * @function encode
             * @memberof perfetto.protos.ProcessRenderInfo
             * @static
             * @param {perfetto.protos.IProcessRenderInfo} message ProcessRenderInfo message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            ProcessRenderInfo.encode = function encode(message, writer) {
                if (!writer)
                    writer = $Writer.create();
                if (message.processName != null && Object.hasOwnProperty.call(message, "processName"))
                    writer.uint32(/* id 1, wireType 2 =*/10).string(message.processName);
                if (message.rtCpuTimeMs != null && Object.hasOwnProperty.call(message, "rtCpuTimeMs"))
                    writer.uint32(/* id 2, wireType 0 =*/16).int64(message.rtCpuTimeMs);
                if (message.drawFrameCount != null && Object.hasOwnProperty.call(message, "drawFrameCount"))
                    writer.uint32(/* id 3, wireType 0 =*/24).uint32(message.drawFrameCount);
                if (message.drawFrameMax != null && Object.hasOwnProperty.call(message, "drawFrameMax"))
                    writer.uint32(/* id 4, wireType 0 =*/32).int64(message.drawFrameMax);
                if (message.drawFrameMin != null && Object.hasOwnProperty.call(message, "drawFrameMin"))
                    writer.uint32(/* id 5, wireType 0 =*/40).int64(message.drawFrameMin);
                if (message.drawFrameAvg != null && Object.hasOwnProperty.call(message, "drawFrameAvg"))
                    writer.uint32(/* id 6, wireType 1 =*/49).double(message.drawFrameAvg);
                if (message.flushCount != null && Object.hasOwnProperty.call(message, "flushCount"))
                    writer.uint32(/* id 7, wireType 0 =*/56).uint32(message.flushCount);
                if (message.flushMax != null && Object.hasOwnProperty.call(message, "flushMax"))
                    writer.uint32(/* id 8, wireType 0 =*/64).int64(message.flushMax);
                if (message.flushMin != null && Object.hasOwnProperty.call(message, "flushMin"))
                    writer.uint32(/* id 9, wireType 0 =*/72).int64(message.flushMin);
                if (message.flushAvg != null && Object.hasOwnProperty.call(message, "flushAvg"))
                    writer.uint32(/* id 10, wireType 1 =*/81).double(message.flushAvg);
                if (message.prepareTreeCount != null && Object.hasOwnProperty.call(message, "prepareTreeCount"))
                    writer.uint32(/* id 11, wireType 0 =*/88).uint32(message.prepareTreeCount);
                if (message.prepareTreeMax != null && Object.hasOwnProperty.call(message, "prepareTreeMax"))
                    writer.uint32(/* id 12, wireType 0 =*/96).int64(message.prepareTreeMax);
                if (message.prepareTreeMin != null && Object.hasOwnProperty.call(message, "prepareTreeMin"))
                    writer.uint32(/* id 13, wireType 0 =*/104).int64(message.prepareTreeMin);
                if (message.prepareTreeAvg != null && Object.hasOwnProperty.call(message, "prepareTreeAvg"))
                    writer.uint32(/* id 14, wireType 1 =*/113).double(message.prepareTreeAvg);
                if (message.gpuCompletionCount != null && Object.hasOwnProperty.call(message, "gpuCompletionCount"))
                    writer.uint32(/* id 15, wireType 0 =*/120).uint32(message.gpuCompletionCount);
                if (message.gpuCompletionMax != null && Object.hasOwnProperty.call(message, "gpuCompletionMax"))
                    writer.uint32(/* id 16, wireType 0 =*/128).int64(message.gpuCompletionMax);
                if (message.gpuCompletionMin != null && Object.hasOwnProperty.call(message, "gpuCompletionMin"))
                    writer.uint32(/* id 17, wireType 0 =*/136).int64(message.gpuCompletionMin);
                if (message.gpuCompletionAvg != null && Object.hasOwnProperty.call(message, "gpuCompletionAvg"))
                    writer.uint32(/* id 18, wireType 1 =*/145).double(message.gpuCompletionAvg);
                if (message.uiRecordCount != null && Object.hasOwnProperty.call(message, "uiRecordCount"))
                    writer.uint32(/* id 19, wireType 0 =*/152).uint32(message.uiRecordCount);
                if (message.uiRecordMax != null && Object.hasOwnProperty.call(message, "uiRecordMax"))
                    writer.uint32(/* id 20, wireType 0 =*/160).int64(message.uiRecordMax);
                if (message.uiRecordMin != null && Object.hasOwnProperty.call(message, "uiRecordMin"))
                    writer.uint32(/* id 21, wireType 0 =*/168).int64(message.uiRecordMin);
                if (message.uiRecordAvg != null && Object.hasOwnProperty.call(message, "uiRecordAvg"))
                    writer.uint32(/* id 22, wireType 1 =*/177).double(message.uiRecordAvg);
                if (message.shaderCompileCount != null && Object.hasOwnProperty.call(message, "shaderCompileCount"))
                    writer.uint32(/* id 23, wireType 0 =*/184).uint32(message.shaderCompileCount);
                if (message.shaderCompileTime != null && Object.hasOwnProperty.call(message, "shaderCompileTime"))
                    writer.uint32(/* id 24, wireType 0 =*/192).int64(message.shaderCompileTime);
                if (message.shaderCompileAvg != null && Object.hasOwnProperty.call(message, "shaderCompileAvg"))
                    writer.uint32(/* id 25, wireType 1 =*/201).double(message.shaderCompileAvg);
                if (message.cacheHitCount != null && Object.hasOwnProperty.call(message, "cacheHitCount"))
                    writer.uint32(/* id 26, wireType 0 =*/208).uint32(message.cacheHitCount);
                if (message.cacheHitTime != null && Object.hasOwnProperty.call(message, "cacheHitTime"))
                    writer.uint32(/* id 27, wireType 0 =*/216).int64(message.cacheHitTime);
                if (message.cacheHitAvg != null && Object.hasOwnProperty.call(message, "cacheHitAvg"))
                    writer.uint32(/* id 28, wireType 1 =*/225).double(message.cacheHitAvg);
                if (message.cacheMissCount != null && Object.hasOwnProperty.call(message, "cacheMissCount"))
                    writer.uint32(/* id 29, wireType 0 =*/232).uint32(message.cacheMissCount);
                if (message.cacheMissTime != null && Object.hasOwnProperty.call(message, "cacheMissTime"))
                    writer.uint32(/* id 30, wireType 0 =*/240).int64(message.cacheMissTime);
                if (message.cacheMissAvg != null && Object.hasOwnProperty.call(message, "cacheMissAvg"))
                    writer.uint32(/* id 31, wireType 1 =*/249).double(message.cacheMissAvg);
                if (message.graphicsCpuMemMax != null && Object.hasOwnProperty.call(message, "graphicsCpuMemMax"))
                    writer.uint32(/* id 32, wireType 0 =*/256).int64(message.graphicsCpuMemMax);
                if (message.graphicsCpuMemMin != null && Object.hasOwnProperty.call(message, "graphicsCpuMemMin"))
                    writer.uint32(/* id 33, wireType 0 =*/264).int64(message.graphicsCpuMemMin);
                if (message.graphicsCpuMemAvg != null && Object.hasOwnProperty.call(message, "graphicsCpuMemAvg"))
                    writer.uint32(/* id 34, wireType 1 =*/273).double(message.graphicsCpuMemAvg);
                if (message.graphicsGpuMemMax != null && Object.hasOwnProperty.call(message, "graphicsGpuMemMax"))
                    writer.uint32(/* id 35, wireType 0 =*/280).int64(message.graphicsGpuMemMax);
                if (message.graphicsGpuMemMin != null && Object.hasOwnProperty.call(message, "graphicsGpuMemMin"))
                    writer.uint32(/* id 36, wireType 0 =*/288).int64(message.graphicsGpuMemMin);
                if (message.graphicsGpuMemAvg != null && Object.hasOwnProperty.call(message, "graphicsGpuMemAvg"))
                    writer.uint32(/* id 37, wireType 1 =*/297).double(message.graphicsGpuMemAvg);
                if (message.textureMemMax != null && Object.hasOwnProperty.call(message, "textureMemMax"))
                    writer.uint32(/* id 38, wireType 0 =*/304).int64(message.textureMemMax);
                if (message.textureMemMin != null && Object.hasOwnProperty.call(message, "textureMemMin"))
                    writer.uint32(/* id 39, wireType 0 =*/312).int64(message.textureMemMin);
                if (message.textureMemAvg != null && Object.hasOwnProperty.call(message, "textureMemAvg"))
                    writer.uint32(/* id 40, wireType 1 =*/321).double(message.textureMemAvg);
                if (message.allMemMax != null && Object.hasOwnProperty.call(message, "allMemMax"))
                    writer.uint32(/* id 41, wireType 0 =*/328).int64(message.allMemMax);
                if (message.allMemMin != null && Object.hasOwnProperty.call(message, "allMemMin"))
                    writer.uint32(/* id 42, wireType 0 =*/336).int64(message.allMemMin);
                if (message.allMemAvg != null && Object.hasOwnProperty.call(message, "allMemAvg"))
                    writer.uint32(/* id 43, wireType 1 =*/345).double(message.allMemAvg);
                return writer;
            };

            /**
             * Encodes the specified ProcessRenderInfo message, length delimited. Does not implicitly {@link perfetto.protos.ProcessRenderInfo.verify|verify} messages.
             * @function encodeDelimited
             * @memberof perfetto.protos.ProcessRenderInfo
             * @static
             * @param {perfetto.protos.IProcessRenderInfo} message ProcessRenderInfo message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            ProcessRenderInfo.encodeDelimited = function encodeDelimited(message, writer) {
                return this.encode(message, writer).ldelim();
            };

            /**
             * Decodes a ProcessRenderInfo message from the specified reader or buffer.
             * @function decode
             * @memberof perfetto.protos.ProcessRenderInfo
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @param {number} [length] Message length if known beforehand
             * @returns {perfetto.protos.ProcessRenderInfo} ProcessRenderInfo
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            ProcessRenderInfo.decode = function decode(reader, length) {
                if (!(reader instanceof $Reader))
                    reader = $Reader.create(reader);
                var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.ProcessRenderInfo();
                while (reader.pos < end) {
                    var tag = reader.uint32();
                    switch (tag >>> 3) {
                    case 1:
                        message.processName = reader.string();
                        break;
                    case 2:
                        message.rtCpuTimeMs = reader.int64();
                        break;
                    case 3:
                        message.drawFrameCount = reader.uint32();
                        break;
                    case 4:
                        message.drawFrameMax = reader.int64();
                        break;
                    case 5:
                        message.drawFrameMin = reader.int64();
                        break;
                    case 6:
                        message.drawFrameAvg = reader.double();
                        break;
                    case 7:
                        message.flushCount = reader.uint32();
                        break;
                    case 8:
                        message.flushMax = reader.int64();
                        break;
                    case 9:
                        message.flushMin = reader.int64();
                        break;
                    case 10:
                        message.flushAvg = reader.double();
                        break;
                    case 11:
                        message.prepareTreeCount = reader.uint32();
                        break;
                    case 12:
                        message.prepareTreeMax = reader.int64();
                        break;
                    case 13:
                        message.prepareTreeMin = reader.int64();
                        break;
                    case 14:
                        message.prepareTreeAvg = reader.double();
                        break;
                    case 15:
                        message.gpuCompletionCount = reader.uint32();
                        break;
                    case 16:
                        message.gpuCompletionMax = reader.int64();
                        break;
                    case 17:
                        message.gpuCompletionMin = reader.int64();
                        break;
                    case 18:
                        message.gpuCompletionAvg = reader.double();
                        break;
                    case 19:
                        message.uiRecordCount = reader.uint32();
                        break;
                    case 20:
                        message.uiRecordMax = reader.int64();
                        break;
                    case 21:
                        message.uiRecordMin = reader.int64();
                        break;
                    case 22:
                        message.uiRecordAvg = reader.double();
                        break;
                    case 23:
                        message.shaderCompileCount = reader.uint32();
                        break;
                    case 24:
                        message.shaderCompileTime = reader.int64();
                        break;
                    case 25:
                        message.shaderCompileAvg = reader.double();
                        break;
                    case 26:
                        message.cacheHitCount = reader.uint32();
                        break;
                    case 27:
                        message.cacheHitTime = reader.int64();
                        break;
                    case 28:
                        message.cacheHitAvg = reader.double();
                        break;
                    case 29:
                        message.cacheMissCount = reader.uint32();
                        break;
                    case 30:
                        message.cacheMissTime = reader.int64();
                        break;
                    case 31:
                        message.cacheMissAvg = reader.double();
                        break;
                    case 32:
                        message.graphicsCpuMemMax = reader.int64();
                        break;
                    case 33:
                        message.graphicsCpuMemMin = reader.int64();
                        break;
                    case 34:
                        message.graphicsCpuMemAvg = reader.double();
                        break;
                    case 35:
                        message.graphicsGpuMemMax = reader.int64();
                        break;
                    case 36:
                        message.graphicsGpuMemMin = reader.int64();
                        break;
                    case 37:
                        message.graphicsGpuMemAvg = reader.double();
                        break;
                    case 38:
                        message.textureMemMax = reader.int64();
                        break;
                    case 39:
                        message.textureMemMin = reader.int64();
                        break;
                    case 40:
                        message.textureMemAvg = reader.double();
                        break;
                    case 41:
                        message.allMemMax = reader.int64();
                        break;
                    case 42:
                        message.allMemMin = reader.int64();
                        break;
                    case 43:
                        message.allMemAvg = reader.double();
                        break;
                    default:
                        reader.skipType(tag & 7);
                        break;
                    }
                }
                return message;
            };

            /**
             * Decodes a ProcessRenderInfo message from the specified reader or buffer, length delimited.
             * @function decodeDelimited
             * @memberof perfetto.protos.ProcessRenderInfo
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @returns {perfetto.protos.ProcessRenderInfo} ProcessRenderInfo
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            ProcessRenderInfo.decodeDelimited = function decodeDelimited(reader) {
                if (!(reader instanceof $Reader))
                    reader = new $Reader(reader);
                return this.decode(reader, reader.uint32());
            };

            /**
             * Verifies a ProcessRenderInfo message.
             * @function verify
             * @memberof perfetto.protos.ProcessRenderInfo
             * @static
             * @param {Object.<string,*>} message Plain object to verify
             * @returns {string|null} `null` if valid, otherwise the reason why it is not
             */
            ProcessRenderInfo.verify = function verify(message) {
                if (typeof message !== "object" || message === null)
                    return "object expected";
                if (message.processName != null && message.hasOwnProperty("processName"))
                    if (!$util.isString(message.processName))
                        return "processName: string expected";
                if (message.rtCpuTimeMs != null && message.hasOwnProperty("rtCpuTimeMs"))
                    if (!$util.isInteger(message.rtCpuTimeMs) && !(message.rtCpuTimeMs && $util.isInteger(message.rtCpuTimeMs.low) && $util.isInteger(message.rtCpuTimeMs.high)))
                        return "rtCpuTimeMs: integer|Long expected";
                if (message.drawFrameCount != null && message.hasOwnProperty("drawFrameCount"))
                    if (!$util.isInteger(message.drawFrameCount))
                        return "drawFrameCount: integer expected";
                if (message.drawFrameMax != null && message.hasOwnProperty("drawFrameMax"))
                    if (!$util.isInteger(message.drawFrameMax) && !(message.drawFrameMax && $util.isInteger(message.drawFrameMax.low) && $util.isInteger(message.drawFrameMax.high)))
                        return "drawFrameMax: integer|Long expected";
                if (message.drawFrameMin != null && message.hasOwnProperty("drawFrameMin"))
                    if (!$util.isInteger(message.drawFrameMin) && !(message.drawFrameMin && $util.isInteger(message.drawFrameMin.low) && $util.isInteger(message.drawFrameMin.high)))
                        return "drawFrameMin: integer|Long expected";
                if (message.drawFrameAvg != null && message.hasOwnProperty("drawFrameAvg"))
                    if (typeof message.drawFrameAvg !== "number")
                        return "drawFrameAvg: number expected";
                if (message.flushCount != null && message.hasOwnProperty("flushCount"))
                    if (!$util.isInteger(message.flushCount))
                        return "flushCount: integer expected";
                if (message.flushMax != null && message.hasOwnProperty("flushMax"))
                    if (!$util.isInteger(message.flushMax) && !(message.flushMax && $util.isInteger(message.flushMax.low) && $util.isInteger(message.flushMax.high)))
                        return "flushMax: integer|Long expected";
                if (message.flushMin != null && message.hasOwnProperty("flushMin"))
                    if (!$util.isInteger(message.flushMin) && !(message.flushMin && $util.isInteger(message.flushMin.low) && $util.isInteger(message.flushMin.high)))
                        return "flushMin: integer|Long expected";
                if (message.flushAvg != null && message.hasOwnProperty("flushAvg"))
                    if (typeof message.flushAvg !== "number")
                        return "flushAvg: number expected";
                if (message.prepareTreeCount != null && message.hasOwnProperty("prepareTreeCount"))
                    if (!$util.isInteger(message.prepareTreeCount))
                        return "prepareTreeCount: integer expected";
                if (message.prepareTreeMax != null && message.hasOwnProperty("prepareTreeMax"))
                    if (!$util.isInteger(message.prepareTreeMax) && !(message.prepareTreeMax && $util.isInteger(message.prepareTreeMax.low) && $util.isInteger(message.prepareTreeMax.high)))
                        return "prepareTreeMax: integer|Long expected";
                if (message.prepareTreeMin != null && message.hasOwnProperty("prepareTreeMin"))
                    if (!$util.isInteger(message.prepareTreeMin) && !(message.prepareTreeMin && $util.isInteger(message.prepareTreeMin.low) && $util.isInteger(message.prepareTreeMin.high)))
                        return "prepareTreeMin: integer|Long expected";
                if (message.prepareTreeAvg != null && message.hasOwnProperty("prepareTreeAvg"))
                    if (typeof message.prepareTreeAvg !== "number")
                        return "prepareTreeAvg: number expected";
                if (message.gpuCompletionCount != null && message.hasOwnProperty("gpuCompletionCount"))
                    if (!$util.isInteger(message.gpuCompletionCount))
                        return "gpuCompletionCount: integer expected";
                if (message.gpuCompletionMax != null && message.hasOwnProperty("gpuCompletionMax"))
                    if (!$util.isInteger(message.gpuCompletionMax) && !(message.gpuCompletionMax && $util.isInteger(message.gpuCompletionMax.low) && $util.isInteger(message.gpuCompletionMax.high)))
                        return "gpuCompletionMax: integer|Long expected";
                if (message.gpuCompletionMin != null && message.hasOwnProperty("gpuCompletionMin"))
                    if (!$util.isInteger(message.gpuCompletionMin) && !(message.gpuCompletionMin && $util.isInteger(message.gpuCompletionMin.low) && $util.isInteger(message.gpuCompletionMin.high)))
                        return "gpuCompletionMin: integer|Long expected";
                if (message.gpuCompletionAvg != null && message.hasOwnProperty("gpuCompletionAvg"))
                    if (typeof message.gpuCompletionAvg !== "number")
                        return "gpuCompletionAvg: number expected";
                if (message.uiRecordCount != null && message.hasOwnProperty("uiRecordCount"))
                    if (!$util.isInteger(message.uiRecordCount))
                        return "uiRecordCount: integer expected";
                if (message.uiRecordMax != null && message.hasOwnProperty("uiRecordMax"))
                    if (!$util.isInteger(message.uiRecordMax) && !(message.uiRecordMax && $util.isInteger(message.uiRecordMax.low) && $util.isInteger(message.uiRecordMax.high)))
                        return "uiRecordMax: integer|Long expected";
                if (message.uiRecordMin != null && message.hasOwnProperty("uiRecordMin"))
                    if (!$util.isInteger(message.uiRecordMin) && !(message.uiRecordMin && $util.isInteger(message.uiRecordMin.low) && $util.isInteger(message.uiRecordMin.high)))
                        return "uiRecordMin: integer|Long expected";
                if (message.uiRecordAvg != null && message.hasOwnProperty("uiRecordAvg"))
                    if (typeof message.uiRecordAvg !== "number")
                        return "uiRecordAvg: number expected";
                if (message.shaderCompileCount != null && message.hasOwnProperty("shaderCompileCount"))
                    if (!$util.isInteger(message.shaderCompileCount))
                        return "shaderCompileCount: integer expected";
                if (message.shaderCompileTime != null && message.hasOwnProperty("shaderCompileTime"))
                    if (!$util.isInteger(message.shaderCompileTime) && !(message.shaderCompileTime && $util.isInteger(message.shaderCompileTime.low) && $util.isInteger(message.shaderCompileTime.high)))
                        return "shaderCompileTime: integer|Long expected";
                if (message.shaderCompileAvg != null && message.hasOwnProperty("shaderCompileAvg"))
                    if (typeof message.shaderCompileAvg !== "number")
                        return "shaderCompileAvg: number expected";
                if (message.cacheHitCount != null && message.hasOwnProperty("cacheHitCount"))
                    if (!$util.isInteger(message.cacheHitCount))
                        return "cacheHitCount: integer expected";
                if (message.cacheHitTime != null && message.hasOwnProperty("cacheHitTime"))
                    if (!$util.isInteger(message.cacheHitTime) && !(message.cacheHitTime && $util.isInteger(message.cacheHitTime.low) && $util.isInteger(message.cacheHitTime.high)))
                        return "cacheHitTime: integer|Long expected";
                if (message.cacheHitAvg != null && message.hasOwnProperty("cacheHitAvg"))
                    if (typeof message.cacheHitAvg !== "number")
                        return "cacheHitAvg: number expected";
                if (message.cacheMissCount != null && message.hasOwnProperty("cacheMissCount"))
                    if (!$util.isInteger(message.cacheMissCount))
                        return "cacheMissCount: integer expected";
                if (message.cacheMissTime != null && message.hasOwnProperty("cacheMissTime"))
                    if (!$util.isInteger(message.cacheMissTime) && !(message.cacheMissTime && $util.isInteger(message.cacheMissTime.low) && $util.isInteger(message.cacheMissTime.high)))
                        return "cacheMissTime: integer|Long expected";
                if (message.cacheMissAvg != null && message.hasOwnProperty("cacheMissAvg"))
                    if (typeof message.cacheMissAvg !== "number")
                        return "cacheMissAvg: number expected";
                if (message.graphicsCpuMemMax != null && message.hasOwnProperty("graphicsCpuMemMax"))
                    if (!$util.isInteger(message.graphicsCpuMemMax) && !(message.graphicsCpuMemMax && $util.isInteger(message.graphicsCpuMemMax.low) && $util.isInteger(message.graphicsCpuMemMax.high)))
                        return "graphicsCpuMemMax: integer|Long expected";
                if (message.graphicsCpuMemMin != null && message.hasOwnProperty("graphicsCpuMemMin"))
                    if (!$util.isInteger(message.graphicsCpuMemMin) && !(message.graphicsCpuMemMin && $util.isInteger(message.graphicsCpuMemMin.low) && $util.isInteger(message.graphicsCpuMemMin.high)))
                        return "graphicsCpuMemMin: integer|Long expected";
                if (message.graphicsCpuMemAvg != null && message.hasOwnProperty("graphicsCpuMemAvg"))
                    if (typeof message.graphicsCpuMemAvg !== "number")
                        return "graphicsCpuMemAvg: number expected";
                if (message.graphicsGpuMemMax != null && message.hasOwnProperty("graphicsGpuMemMax"))
                    if (!$util.isInteger(message.graphicsGpuMemMax) && !(message.graphicsGpuMemMax && $util.isInteger(message.graphicsGpuMemMax.low) && $util.isInteger(message.graphicsGpuMemMax.high)))
                        return "graphicsGpuMemMax: integer|Long expected";
                if (message.graphicsGpuMemMin != null && message.hasOwnProperty("graphicsGpuMemMin"))
                    if (!$util.isInteger(message.graphicsGpuMemMin) && !(message.graphicsGpuMemMin && $util.isInteger(message.graphicsGpuMemMin.low) && $util.isInteger(message.graphicsGpuMemMin.high)))
                        return "graphicsGpuMemMin: integer|Long expected";
                if (message.graphicsGpuMemAvg != null && message.hasOwnProperty("graphicsGpuMemAvg"))
                    if (typeof message.graphicsGpuMemAvg !== "number")
                        return "graphicsGpuMemAvg: number expected";
                if (message.textureMemMax != null && message.hasOwnProperty("textureMemMax"))
                    if (!$util.isInteger(message.textureMemMax) && !(message.textureMemMax && $util.isInteger(message.textureMemMax.low) && $util.isInteger(message.textureMemMax.high)))
                        return "textureMemMax: integer|Long expected";
                if (message.textureMemMin != null && message.hasOwnProperty("textureMemMin"))
                    if (!$util.isInteger(message.textureMemMin) && !(message.textureMemMin && $util.isInteger(message.textureMemMin.low) && $util.isInteger(message.textureMemMin.high)))
                        return "textureMemMin: integer|Long expected";
                if (message.textureMemAvg != null && message.hasOwnProperty("textureMemAvg"))
                    if (typeof message.textureMemAvg !== "number")
                        return "textureMemAvg: number expected";
                if (message.allMemMax != null && message.hasOwnProperty("allMemMax"))
                    if (!$util.isInteger(message.allMemMax) && !(message.allMemMax && $util.isInteger(message.allMemMax.low) && $util.isInteger(message.allMemMax.high)))
                        return "allMemMax: integer|Long expected";
                if (message.allMemMin != null && message.hasOwnProperty("allMemMin"))
                    if (!$util.isInteger(message.allMemMin) && !(message.allMemMin && $util.isInteger(message.allMemMin.low) && $util.isInteger(message.allMemMin.high)))
                        return "allMemMin: integer|Long expected";
                if (message.allMemAvg != null && message.hasOwnProperty("allMemAvg"))
                    if (typeof message.allMemAvg !== "number")
                        return "allMemAvg: number expected";
                return null;
            };

            /**
             * Creates a ProcessRenderInfo message from a plain object. Also converts values to their respective internal types.
             * @function fromObject
             * @memberof perfetto.protos.ProcessRenderInfo
             * @static
             * @param {Object.<string,*>} object Plain object
             * @returns {perfetto.protos.ProcessRenderInfo} ProcessRenderInfo
             */
            ProcessRenderInfo.fromObject = function fromObject(object) {
                if (object instanceof $root.perfetto.protos.ProcessRenderInfo)
                    return object;
                var message = new $root.perfetto.protos.ProcessRenderInfo();
                if (object.processName != null)
                    message.processName = String(object.processName);
                if (object.rtCpuTimeMs != null)
                    if ($util.Long)
                        (message.rtCpuTimeMs = $util.Long.fromValue(object.rtCpuTimeMs)).unsigned = false;
                    else if (typeof object.rtCpuTimeMs === "string")
                        message.rtCpuTimeMs = parseInt(object.rtCpuTimeMs, 10);
                    else if (typeof object.rtCpuTimeMs === "number")
                        message.rtCpuTimeMs = object.rtCpuTimeMs;
                    else if (typeof object.rtCpuTimeMs === "object")
                        message.rtCpuTimeMs = new $util.LongBits(object.rtCpuTimeMs.low >>> 0, object.rtCpuTimeMs.high >>> 0).toNumber();
                if (object.drawFrameCount != null)
                    message.drawFrameCount = object.drawFrameCount >>> 0;
                if (object.drawFrameMax != null)
                    if ($util.Long)
                        (message.drawFrameMax = $util.Long.fromValue(object.drawFrameMax)).unsigned = false;
                    else if (typeof object.drawFrameMax === "string")
                        message.drawFrameMax = parseInt(object.drawFrameMax, 10);
                    else if (typeof object.drawFrameMax === "number")
                        message.drawFrameMax = object.drawFrameMax;
                    else if (typeof object.drawFrameMax === "object")
                        message.drawFrameMax = new $util.LongBits(object.drawFrameMax.low >>> 0, object.drawFrameMax.high >>> 0).toNumber();
                if (object.drawFrameMin != null)
                    if ($util.Long)
                        (message.drawFrameMin = $util.Long.fromValue(object.drawFrameMin)).unsigned = false;
                    else if (typeof object.drawFrameMin === "string")
                        message.drawFrameMin = parseInt(object.drawFrameMin, 10);
                    else if (typeof object.drawFrameMin === "number")
                        message.drawFrameMin = object.drawFrameMin;
                    else if (typeof object.drawFrameMin === "object")
                        message.drawFrameMin = new $util.LongBits(object.drawFrameMin.low >>> 0, object.drawFrameMin.high >>> 0).toNumber();
                if (object.drawFrameAvg != null)
                    message.drawFrameAvg = Number(object.drawFrameAvg);
                if (object.flushCount != null)
                    message.flushCount = object.flushCount >>> 0;
                if (object.flushMax != null)
                    if ($util.Long)
                        (message.flushMax = $util.Long.fromValue(object.flushMax)).unsigned = false;
                    else if (typeof object.flushMax === "string")
                        message.flushMax = parseInt(object.flushMax, 10);
                    else if (typeof object.flushMax === "number")
                        message.flushMax = object.flushMax;
                    else if (typeof object.flushMax === "object")
                        message.flushMax = new $util.LongBits(object.flushMax.low >>> 0, object.flushMax.high >>> 0).toNumber();
                if (object.flushMin != null)
                    if ($util.Long)
                        (message.flushMin = $util.Long.fromValue(object.flushMin)).unsigned = false;
                    else if (typeof object.flushMin === "string")
                        message.flushMin = parseInt(object.flushMin, 10);
                    else if (typeof object.flushMin === "number")
                        message.flushMin = object.flushMin;
                    else if (typeof object.flushMin === "object")
                        message.flushMin = new $util.LongBits(object.flushMin.low >>> 0, object.flushMin.high >>> 0).toNumber();
                if (object.flushAvg != null)
                    message.flushAvg = Number(object.flushAvg);
                if (object.prepareTreeCount != null)
                    message.prepareTreeCount = object.prepareTreeCount >>> 0;
                if (object.prepareTreeMax != null)
                    if ($util.Long)
                        (message.prepareTreeMax = $util.Long.fromValue(object.prepareTreeMax)).unsigned = false;
                    else if (typeof object.prepareTreeMax === "string")
                        message.prepareTreeMax = parseInt(object.prepareTreeMax, 10);
                    else if (typeof object.prepareTreeMax === "number")
                        message.prepareTreeMax = object.prepareTreeMax;
                    else if (typeof object.prepareTreeMax === "object")
                        message.prepareTreeMax = new $util.LongBits(object.prepareTreeMax.low >>> 0, object.prepareTreeMax.high >>> 0).toNumber();
                if (object.prepareTreeMin != null)
                    if ($util.Long)
                        (message.prepareTreeMin = $util.Long.fromValue(object.prepareTreeMin)).unsigned = false;
                    else if (typeof object.prepareTreeMin === "string")
                        message.prepareTreeMin = parseInt(object.prepareTreeMin, 10);
                    else if (typeof object.prepareTreeMin === "number")
                        message.prepareTreeMin = object.prepareTreeMin;
                    else if (typeof object.prepareTreeMin === "object")
                        message.prepareTreeMin = new $util.LongBits(object.prepareTreeMin.low >>> 0, object.prepareTreeMin.high >>> 0).toNumber();
                if (object.prepareTreeAvg != null)
                    message.prepareTreeAvg = Number(object.prepareTreeAvg);
                if (object.gpuCompletionCount != null)
                    message.gpuCompletionCount = object.gpuCompletionCount >>> 0;
                if (object.gpuCompletionMax != null)
                    if ($util.Long)
                        (message.gpuCompletionMax = $util.Long.fromValue(object.gpuCompletionMax)).unsigned = false;
                    else if (typeof object.gpuCompletionMax === "string")
                        message.gpuCompletionMax = parseInt(object.gpuCompletionMax, 10);
                    else if (typeof object.gpuCompletionMax === "number")
                        message.gpuCompletionMax = object.gpuCompletionMax;
                    else if (typeof object.gpuCompletionMax === "object")
                        message.gpuCompletionMax = new $util.LongBits(object.gpuCompletionMax.low >>> 0, object.gpuCompletionMax.high >>> 0).toNumber();
                if (object.gpuCompletionMin != null)
                    if ($util.Long)
                        (message.gpuCompletionMin = $util.Long.fromValue(object.gpuCompletionMin)).unsigned = false;
                    else if (typeof object.gpuCompletionMin === "string")
                        message.gpuCompletionMin = parseInt(object.gpuCompletionMin, 10);
                    else if (typeof object.gpuCompletionMin === "number")
                        message.gpuCompletionMin = object.gpuCompletionMin;
                    else if (typeof object.gpuCompletionMin === "object")
                        message.gpuCompletionMin = new $util.LongBits(object.gpuCompletionMin.low >>> 0, object.gpuCompletionMin.high >>> 0).toNumber();
                if (object.gpuCompletionAvg != null)
                    message.gpuCompletionAvg = Number(object.gpuCompletionAvg);
                if (object.uiRecordCount != null)
                    message.uiRecordCount = object.uiRecordCount >>> 0;
                if (object.uiRecordMax != null)
                    if ($util.Long)
                        (message.uiRecordMax = $util.Long.fromValue(object.uiRecordMax)).unsigned = false;
                    else if (typeof object.uiRecordMax === "string")
                        message.uiRecordMax = parseInt(object.uiRecordMax, 10);
                    else if (typeof object.uiRecordMax === "number")
                        message.uiRecordMax = object.uiRecordMax;
                    else if (typeof object.uiRecordMax === "object")
                        message.uiRecordMax = new $util.LongBits(object.uiRecordMax.low >>> 0, object.uiRecordMax.high >>> 0).toNumber();
                if (object.uiRecordMin != null)
                    if ($util.Long)
                        (message.uiRecordMin = $util.Long.fromValue(object.uiRecordMin)).unsigned = false;
                    else if (typeof object.uiRecordMin === "string")
                        message.uiRecordMin = parseInt(object.uiRecordMin, 10);
                    else if (typeof object.uiRecordMin === "number")
                        message.uiRecordMin = object.uiRecordMin;
                    else if (typeof object.uiRecordMin === "object")
                        message.uiRecordMin = new $util.LongBits(object.uiRecordMin.low >>> 0, object.uiRecordMin.high >>> 0).toNumber();
                if (object.uiRecordAvg != null)
                    message.uiRecordAvg = Number(object.uiRecordAvg);
                if (object.shaderCompileCount != null)
                    message.shaderCompileCount = object.shaderCompileCount >>> 0;
                if (object.shaderCompileTime != null)
                    if ($util.Long)
                        (message.shaderCompileTime = $util.Long.fromValue(object.shaderCompileTime)).unsigned = false;
                    else if (typeof object.shaderCompileTime === "string")
                        message.shaderCompileTime = parseInt(object.shaderCompileTime, 10);
                    else if (typeof object.shaderCompileTime === "number")
                        message.shaderCompileTime = object.shaderCompileTime;
                    else if (typeof object.shaderCompileTime === "object")
                        message.shaderCompileTime = new $util.LongBits(object.shaderCompileTime.low >>> 0, object.shaderCompileTime.high >>> 0).toNumber();
                if (object.shaderCompileAvg != null)
                    message.shaderCompileAvg = Number(object.shaderCompileAvg);
                if (object.cacheHitCount != null)
                    message.cacheHitCount = object.cacheHitCount >>> 0;
                if (object.cacheHitTime != null)
                    if ($util.Long)
                        (message.cacheHitTime = $util.Long.fromValue(object.cacheHitTime)).unsigned = false;
                    else if (typeof object.cacheHitTime === "string")
                        message.cacheHitTime = parseInt(object.cacheHitTime, 10);
                    else if (typeof object.cacheHitTime === "number")
                        message.cacheHitTime = object.cacheHitTime;
                    else if (typeof object.cacheHitTime === "object")
                        message.cacheHitTime = new $util.LongBits(object.cacheHitTime.low >>> 0, object.cacheHitTime.high >>> 0).toNumber();
                if (object.cacheHitAvg != null)
                    message.cacheHitAvg = Number(object.cacheHitAvg);
                if (object.cacheMissCount != null)
                    message.cacheMissCount = object.cacheMissCount >>> 0;
                if (object.cacheMissTime != null)
                    if ($util.Long)
                        (message.cacheMissTime = $util.Long.fromValue(object.cacheMissTime)).unsigned = false;
                    else if (typeof object.cacheMissTime === "string")
                        message.cacheMissTime = parseInt(object.cacheMissTime, 10);
                    else if (typeof object.cacheMissTime === "number")
                        message.cacheMissTime = object.cacheMissTime;
                    else if (typeof object.cacheMissTime === "object")
                        message.cacheMissTime = new $util.LongBits(object.cacheMissTime.low >>> 0, object.cacheMissTime.high >>> 0).toNumber();
                if (object.cacheMissAvg != null)
                    message.cacheMissAvg = Number(object.cacheMissAvg);
                if (object.graphicsCpuMemMax != null)
                    if ($util.Long)
                        (message.graphicsCpuMemMax = $util.Long.fromValue(object.graphicsCpuMemMax)).unsigned = false;
                    else if (typeof object.graphicsCpuMemMax === "string")
                        message.graphicsCpuMemMax = parseInt(object.graphicsCpuMemMax, 10);
                    else if (typeof object.graphicsCpuMemMax === "number")
                        message.graphicsCpuMemMax = object.graphicsCpuMemMax;
                    else if (typeof object.graphicsCpuMemMax === "object")
                        message.graphicsCpuMemMax = new $util.LongBits(object.graphicsCpuMemMax.low >>> 0, object.graphicsCpuMemMax.high >>> 0).toNumber();
                if (object.graphicsCpuMemMin != null)
                    if ($util.Long)
                        (message.graphicsCpuMemMin = $util.Long.fromValue(object.graphicsCpuMemMin)).unsigned = false;
                    else if (typeof object.graphicsCpuMemMin === "string")
                        message.graphicsCpuMemMin = parseInt(object.graphicsCpuMemMin, 10);
                    else if (typeof object.graphicsCpuMemMin === "number")
                        message.graphicsCpuMemMin = object.graphicsCpuMemMin;
                    else if (typeof object.graphicsCpuMemMin === "object")
                        message.graphicsCpuMemMin = new $util.LongBits(object.graphicsCpuMemMin.low >>> 0, object.graphicsCpuMemMin.high >>> 0).toNumber();
                if (object.graphicsCpuMemAvg != null)
                    message.graphicsCpuMemAvg = Number(object.graphicsCpuMemAvg);
                if (object.graphicsGpuMemMax != null)
                    if ($util.Long)
                        (message.graphicsGpuMemMax = $util.Long.fromValue(object.graphicsGpuMemMax)).unsigned = false;
                    else if (typeof object.graphicsGpuMemMax === "string")
                        message.graphicsGpuMemMax = parseInt(object.graphicsGpuMemMax, 10);
                    else if (typeof object.graphicsGpuMemMax === "number")
                        message.graphicsGpuMemMax = object.graphicsGpuMemMax;
                    else if (typeof object.graphicsGpuMemMax === "object")
                        message.graphicsGpuMemMax = new $util.LongBits(object.graphicsGpuMemMax.low >>> 0, object.graphicsGpuMemMax.high >>> 0).toNumber();
                if (object.graphicsGpuMemMin != null)
                    if ($util.Long)
                        (message.graphicsGpuMemMin = $util.Long.fromValue(object.graphicsGpuMemMin)).unsigned = false;
                    else if (typeof object.graphicsGpuMemMin === "string")
                        message.graphicsGpuMemMin = parseInt(object.graphicsGpuMemMin, 10);
                    else if (typeof object.graphicsGpuMemMin === "number")
                        message.graphicsGpuMemMin = object.graphicsGpuMemMin;
                    else if (typeof object.graphicsGpuMemMin === "object")
                        message.graphicsGpuMemMin = new $util.LongBits(object.graphicsGpuMemMin.low >>> 0, object.graphicsGpuMemMin.high >>> 0).toNumber();
                if (object.graphicsGpuMemAvg != null)
                    message.graphicsGpuMemAvg = Number(object.graphicsGpuMemAvg);
                if (object.textureMemMax != null)
                    if ($util.Long)
                        (message.textureMemMax = $util.Long.fromValue(object.textureMemMax)).unsigned = false;
                    else if (typeof object.textureMemMax === "string")
                        message.textureMemMax = parseInt(object.textureMemMax, 10);
                    else if (typeof object.textureMemMax === "number")
                        message.textureMemMax = object.textureMemMax;
                    else if (typeof object.textureMemMax === "object")
                        message.textureMemMax = new $util.LongBits(object.textureMemMax.low >>> 0, object.textureMemMax.high >>> 0).toNumber();
                if (object.textureMemMin != null)
                    if ($util.Long)
                        (message.textureMemMin = $util.Long.fromValue(object.textureMemMin)).unsigned = false;
                    else if (typeof object.textureMemMin === "string")
                        message.textureMemMin = parseInt(object.textureMemMin, 10);
                    else if (typeof object.textureMemMin === "number")
                        message.textureMemMin = object.textureMemMin;
                    else if (typeof object.textureMemMin === "object")
                        message.textureMemMin = new $util.LongBits(object.textureMemMin.low >>> 0, object.textureMemMin.high >>> 0).toNumber();
                if (object.textureMemAvg != null)
                    message.textureMemAvg = Number(object.textureMemAvg);
                if (object.allMemMax != null)
                    if ($util.Long)
                        (message.allMemMax = $util.Long.fromValue(object.allMemMax)).unsigned = false;
                    else if (typeof object.allMemMax === "string")
                        message.allMemMax = parseInt(object.allMemMax, 10);
                    else if (typeof object.allMemMax === "number")
                        message.allMemMax = object.allMemMax;
                    else if (typeof object.allMemMax === "object")
                        message.allMemMax = new $util.LongBits(object.allMemMax.low >>> 0, object.allMemMax.high >>> 0).toNumber();
                if (object.allMemMin != null)
                    if ($util.Long)
                        (message.allMemMin = $util.Long.fromValue(object.allMemMin)).unsigned = false;
                    else if (typeof object.allMemMin === "string")
                        message.allMemMin = parseInt(object.allMemMin, 10);
                    else if (typeof object.allMemMin === "number")
                        message.allMemMin = object.allMemMin;
                    else if (typeof object.allMemMin === "object")
                        message.allMemMin = new $util.LongBits(object.allMemMin.low >>> 0, object.allMemMin.high >>> 0).toNumber();
                if (object.allMemAvg != null)
                    message.allMemAvg = Number(object.allMemAvg);
                return message;
            };

            /**
             * Creates a plain object from a ProcessRenderInfo message. Also converts values to other types if specified.
             * @function toObject
             * @memberof perfetto.protos.ProcessRenderInfo
             * @static
             * @param {perfetto.protos.ProcessRenderInfo} message ProcessRenderInfo
             * @param {$protobuf.IConversionOptions} [options] Conversion options
             * @returns {Object.<string,*>} Plain object
             */
            ProcessRenderInfo.toObject = function toObject(message, options) {
                if (!options)
                    options = {};
                var object = {};
                if (options.defaults) {
                    object.processName = "";
                    if ($util.Long) {
                        var long = new $util.Long(0, 0, false);
                        object.rtCpuTimeMs = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
                    } else
                        object.rtCpuTimeMs = options.longs === String ? "0" : 0;
                    object.drawFrameCount = 0;
                    if ($util.Long) {
                        var long = new $util.Long(0, 0, false);
                        object.drawFrameMax = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
                    } else
                        object.drawFrameMax = options.longs === String ? "0" : 0;
                    if ($util.Long) {
                        var long = new $util.Long(0, 0, false);
                        object.drawFrameMin = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
                    } else
                        object.drawFrameMin = options.longs === String ? "0" : 0;
                    object.drawFrameAvg = 0;
                    object.flushCount = 0;
                    if ($util.Long) {
                        var long = new $util.Long(0, 0, false);
                        object.flushMax = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
                    } else
                        object.flushMax = options.longs === String ? "0" : 0;
                    if ($util.Long) {
                        var long = new $util.Long(0, 0, false);
                        object.flushMin = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
                    } else
                        object.flushMin = options.longs === String ? "0" : 0;
                    object.flushAvg = 0;
                    object.prepareTreeCount = 0;
                    if ($util.Long) {
                        var long = new $util.Long(0, 0, false);
                        object.prepareTreeMax = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
                    } else
                        object.prepareTreeMax = options.longs === String ? "0" : 0;
                    if ($util.Long) {
                        var long = new $util.Long(0, 0, false);
                        object.prepareTreeMin = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
                    } else
                        object.prepareTreeMin = options.longs === String ? "0" : 0;
                    object.prepareTreeAvg = 0;
                    object.gpuCompletionCount = 0;
                    if ($util.Long) {
                        var long = new $util.Long(0, 0, false);
                        object.gpuCompletionMax = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
                    } else
                        object.gpuCompletionMax = options.longs === String ? "0" : 0;
                    if ($util.Long) {
                        var long = new $util.Long(0, 0, false);
                        object.gpuCompletionMin = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
                    } else
                        object.gpuCompletionMin = options.longs === String ? "0" : 0;
                    object.gpuCompletionAvg = 0;
                    object.uiRecordCount = 0;
                    if ($util.Long) {
                        var long = new $util.Long(0, 0, false);
                        object.uiRecordMax = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
                    } else
                        object.uiRecordMax = options.longs === String ? "0" : 0;
                    if ($util.Long) {
                        var long = new $util.Long(0, 0, false);
                        object.uiRecordMin = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
                    } else
                        object.uiRecordMin = options.longs === String ? "0" : 0;
                    object.uiRecordAvg = 0;
                    object.shaderCompileCount = 0;
                    if ($util.Long) {
                        var long = new $util.Long(0, 0, false);
                        object.shaderCompileTime = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
                    } else
                        object.shaderCompileTime = options.longs === String ? "0" : 0;
                    object.shaderCompileAvg = 0;
                    object.cacheHitCount = 0;
                    if ($util.Long) {
                        var long = new $util.Long(0, 0, false);
                        object.cacheHitTime = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
                    } else
                        object.cacheHitTime = options.longs === String ? "0" : 0;
                    object.cacheHitAvg = 0;
                    object.cacheMissCount = 0;
                    if ($util.Long) {
                        var long = new $util.Long(0, 0, false);
                        object.cacheMissTime = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
                    } else
                        object.cacheMissTime = options.longs === String ? "0" : 0;
                    object.cacheMissAvg = 0;
                    if ($util.Long) {
                        var long = new $util.Long(0, 0, false);
                        object.graphicsCpuMemMax = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
                    } else
                        object.graphicsCpuMemMax = options.longs === String ? "0" : 0;
                    if ($util.Long) {
                        var long = new $util.Long(0, 0, false);
                        object.graphicsCpuMemMin = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
                    } else
                        object.graphicsCpuMemMin = options.longs === String ? "0" : 0;
                    object.graphicsCpuMemAvg = 0;
                    if ($util.Long) {
                        var long = new $util.Long(0, 0, false);
                        object.graphicsGpuMemMax = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
                    } else
                        object.graphicsGpuMemMax = options.longs === String ? "0" : 0;
                    if ($util.Long) {
                        var long = new $util.Long(0, 0, false);
                        object.graphicsGpuMemMin = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
                    } else
                        object.graphicsGpuMemMin = options.longs === String ? "0" : 0;
                    object.graphicsGpuMemAvg = 0;
                    if ($util.Long) {
                        var long = new $util.Long(0, 0, false);
                        object.textureMemMax = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
                    } else
                        object.textureMemMax = options.longs === String ? "0" : 0;
                    if ($util.Long) {
                        var long = new $util.Long(0, 0, false);
                        object.textureMemMin = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
                    } else
                        object.textureMemMin = options.longs === String ? "0" : 0;
                    object.textureMemAvg = 0;
                    if ($util.Long) {
                        var long = new $util.Long(0, 0, false);
                        object.allMemMax = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
                    } else
                        object.allMemMax = options.longs === String ? "0" : 0;
                    if ($util.Long) {
                        var long = new $util.Long(0, 0, false);
                        object.allMemMin = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
                    } else
                        object.allMemMin = options.longs === String ? "0" : 0;
                    object.allMemAvg = 0;
                }
                if (message.processName != null && message.hasOwnProperty("processName"))
                    object.processName = message.processName;
                if (message.rtCpuTimeMs != null && message.hasOwnProperty("rtCpuTimeMs"))
                    if (typeof message.rtCpuTimeMs === "number")
                        object.rtCpuTimeMs = options.longs === String ? String(message.rtCpuTimeMs) : message.rtCpuTimeMs;
                    else
                        object.rtCpuTimeMs = options.longs === String ? $util.Long.prototype.toString.call(message.rtCpuTimeMs) : options.longs === Number ? new $util.LongBits(message.rtCpuTimeMs.low >>> 0, message.rtCpuTimeMs.high >>> 0).toNumber() : message.rtCpuTimeMs;
                if (message.drawFrameCount != null && message.hasOwnProperty("drawFrameCount"))
                    object.drawFrameCount = message.drawFrameCount;
                if (message.drawFrameMax != null && message.hasOwnProperty("drawFrameMax"))
                    if (typeof message.drawFrameMax === "number")
                        object.drawFrameMax = options.longs === String ? String(message.drawFrameMax) : message.drawFrameMax;
                    else
                        object.drawFrameMax = options.longs === String ? $util.Long.prototype.toString.call(message.drawFrameMax) : options.longs === Number ? new $util.LongBits(message.drawFrameMax.low >>> 0, message.drawFrameMax.high >>> 0).toNumber() : message.drawFrameMax;
                if (message.drawFrameMin != null && message.hasOwnProperty("drawFrameMin"))
                    if (typeof message.drawFrameMin === "number")
                        object.drawFrameMin = options.longs === String ? String(message.drawFrameMin) : message.drawFrameMin;
                    else
                        object.drawFrameMin = options.longs === String ? $util.Long.prototype.toString.call(message.drawFrameMin) : options.longs === Number ? new $util.LongBits(message.drawFrameMin.low >>> 0, message.drawFrameMin.high >>> 0).toNumber() : message.drawFrameMin;
                if (message.drawFrameAvg != null && message.hasOwnProperty("drawFrameAvg"))
                    object.drawFrameAvg = options.json && !isFinite(message.drawFrameAvg) ? String(message.drawFrameAvg) : message.drawFrameAvg;
                if (message.flushCount != null && message.hasOwnProperty("flushCount"))
                    object.flushCount = message.flushCount;
                if (message.flushMax != null && message.hasOwnProperty("flushMax"))
                    if (typeof message.flushMax === "number")
                        object.flushMax = options.longs === String ? String(message.flushMax) : message.flushMax;
                    else
                        object.flushMax = options.longs === String ? $util.Long.prototype.toString.call(message.flushMax) : options.longs === Number ? new $util.LongBits(message.flushMax.low >>> 0, message.flushMax.high >>> 0).toNumber() : message.flushMax;
                if (message.flushMin != null && message.hasOwnProperty("flushMin"))
                    if (typeof message.flushMin === "number")
                        object.flushMin = options.longs === String ? String(message.flushMin) : message.flushMin;
                    else
                        object.flushMin = options.longs === String ? $util.Long.prototype.toString.call(message.flushMin) : options.longs === Number ? new $util.LongBits(message.flushMin.low >>> 0, message.flushMin.high >>> 0).toNumber() : message.flushMin;
                if (message.flushAvg != null && message.hasOwnProperty("flushAvg"))
                    object.flushAvg = options.json && !isFinite(message.flushAvg) ? String(message.flushAvg) : message.flushAvg;
                if (message.prepareTreeCount != null && message.hasOwnProperty("prepareTreeCount"))
                    object.prepareTreeCount = message.prepareTreeCount;
                if (message.prepareTreeMax != null && message.hasOwnProperty("prepareTreeMax"))
                    if (typeof message.prepareTreeMax === "number")
                        object.prepareTreeMax = options.longs === String ? String(message.prepareTreeMax) : message.prepareTreeMax;
                    else
                        object.prepareTreeMax = options.longs === String ? $util.Long.prototype.toString.call(message.prepareTreeMax) : options.longs === Number ? new $util.LongBits(message.prepareTreeMax.low >>> 0, message.prepareTreeMax.high >>> 0).toNumber() : message.prepareTreeMax;
                if (message.prepareTreeMin != null && message.hasOwnProperty("prepareTreeMin"))
                    if (typeof message.prepareTreeMin === "number")
                        object.prepareTreeMin = options.longs === String ? String(message.prepareTreeMin) : message.prepareTreeMin;
                    else
                        object.prepareTreeMin = options.longs === String ? $util.Long.prototype.toString.call(message.prepareTreeMin) : options.longs === Number ? new $util.LongBits(message.prepareTreeMin.low >>> 0, message.prepareTreeMin.high >>> 0).toNumber() : message.prepareTreeMin;
                if (message.prepareTreeAvg != null && message.hasOwnProperty("prepareTreeAvg"))
                    object.prepareTreeAvg = options.json && !isFinite(message.prepareTreeAvg) ? String(message.prepareTreeAvg) : message.prepareTreeAvg;
                if (message.gpuCompletionCount != null && message.hasOwnProperty("gpuCompletionCount"))
                    object.gpuCompletionCount = message.gpuCompletionCount;
                if (message.gpuCompletionMax != null && message.hasOwnProperty("gpuCompletionMax"))
                    if (typeof message.gpuCompletionMax === "number")
                        object.gpuCompletionMax = options.longs === String ? String(message.gpuCompletionMax) : message.gpuCompletionMax;
                    else
                        object.gpuCompletionMax = options.longs === String ? $util.Long.prototype.toString.call(message.gpuCompletionMax) : options.longs === Number ? new $util.LongBits(message.gpuCompletionMax.low >>> 0, message.gpuCompletionMax.high >>> 0).toNumber() : message.gpuCompletionMax;
                if (message.gpuCompletionMin != null && message.hasOwnProperty("gpuCompletionMin"))
                    if (typeof message.gpuCompletionMin === "number")
                        object.gpuCompletionMin = options.longs === String ? String(message.gpuCompletionMin) : message.gpuCompletionMin;
                    else
                        object.gpuCompletionMin = options.longs === String ? $util.Long.prototype.toString.call(message.gpuCompletionMin) : options.longs === Number ? new $util.LongBits(message.gpuCompletionMin.low >>> 0, message.gpuCompletionMin.high >>> 0).toNumber() : message.gpuCompletionMin;
                if (message.gpuCompletionAvg != null && message.hasOwnProperty("gpuCompletionAvg"))
                    object.gpuCompletionAvg = options.json && !isFinite(message.gpuCompletionAvg) ? String(message.gpuCompletionAvg) : message.gpuCompletionAvg;
                if (message.uiRecordCount != null && message.hasOwnProperty("uiRecordCount"))
                    object.uiRecordCount = message.uiRecordCount;
                if (message.uiRecordMax != null && message.hasOwnProperty("uiRecordMax"))
                    if (typeof message.uiRecordMax === "number")
                        object.uiRecordMax = options.longs === String ? String(message.uiRecordMax) : message.uiRecordMax;
                    else
                        object.uiRecordMax = options.longs === String ? $util.Long.prototype.toString.call(message.uiRecordMax) : options.longs === Number ? new $util.LongBits(message.uiRecordMax.low >>> 0, message.uiRecordMax.high >>> 0).toNumber() : message.uiRecordMax;
                if (message.uiRecordMin != null && message.hasOwnProperty("uiRecordMin"))
                    if (typeof message.uiRecordMin === "number")
                        object.uiRecordMin = options.longs === String ? String(message.uiRecordMin) : message.uiRecordMin;
                    else
                        object.uiRecordMin = options.longs === String ? $util.Long.prototype.toString.call(message.uiRecordMin) : options.longs === Number ? new $util.LongBits(message.uiRecordMin.low >>> 0, message.uiRecordMin.high >>> 0).toNumber() : message.uiRecordMin;
                if (message.uiRecordAvg != null && message.hasOwnProperty("uiRecordAvg"))
                    object.uiRecordAvg = options.json && !isFinite(message.uiRecordAvg) ? String(message.uiRecordAvg) : message.uiRecordAvg;
                if (message.shaderCompileCount != null && message.hasOwnProperty("shaderCompileCount"))
                    object.shaderCompileCount = message.shaderCompileCount;
                if (message.shaderCompileTime != null && message.hasOwnProperty("shaderCompileTime"))
                    if (typeof message.shaderCompileTime === "number")
                        object.shaderCompileTime = options.longs === String ? String(message.shaderCompileTime) : message.shaderCompileTime;
                    else
                        object.shaderCompileTime = options.longs === String ? $util.Long.prototype.toString.call(message.shaderCompileTime) : options.longs === Number ? new $util.LongBits(message.shaderCompileTime.low >>> 0, message.shaderCompileTime.high >>> 0).toNumber() : message.shaderCompileTime;
                if (message.shaderCompileAvg != null && message.hasOwnProperty("shaderCompileAvg"))
                    object.shaderCompileAvg = options.json && !isFinite(message.shaderCompileAvg) ? String(message.shaderCompileAvg) : message.shaderCompileAvg;
                if (message.cacheHitCount != null && message.hasOwnProperty("cacheHitCount"))
                    object.cacheHitCount = message.cacheHitCount;
                if (message.cacheHitTime != null && message.hasOwnProperty("cacheHitTime"))
                    if (typeof message.cacheHitTime === "number")
                        object.cacheHitTime = options.longs === String ? String(message.cacheHitTime) : message.cacheHitTime;
                    else
                        object.cacheHitTime = options.longs === String ? $util.Long.prototype.toString.call(message.cacheHitTime) : options.longs === Number ? new $util.LongBits(message.cacheHitTime.low >>> 0, message.cacheHitTime.high >>> 0).toNumber() : message.cacheHitTime;
                if (message.cacheHitAvg != null && message.hasOwnProperty("cacheHitAvg"))
                    object.cacheHitAvg = options.json && !isFinite(message.cacheHitAvg) ? String(message.cacheHitAvg) : message.cacheHitAvg;
                if (message.cacheMissCount != null && message.hasOwnProperty("cacheMissCount"))
                    object.cacheMissCount = message.cacheMissCount;
                if (message.cacheMissTime != null && message.hasOwnProperty("cacheMissTime"))
                    if (typeof message.cacheMissTime === "number")
                        object.cacheMissTime = options.longs === String ? String(message.cacheMissTime) : message.cacheMissTime;
                    else
                        object.cacheMissTime = options.longs === String ? $util.Long.prototype.toString.call(message.cacheMissTime) : options.longs === Number ? new $util.LongBits(message.cacheMissTime.low >>> 0, message.cacheMissTime.high >>> 0).toNumber() : message.cacheMissTime;
                if (message.cacheMissAvg != null && message.hasOwnProperty("cacheMissAvg"))
                    object.cacheMissAvg = options.json && !isFinite(message.cacheMissAvg) ? String(message.cacheMissAvg) : message.cacheMissAvg;
                if (message.graphicsCpuMemMax != null && message.hasOwnProperty("graphicsCpuMemMax"))
                    if (typeof message.graphicsCpuMemMax === "number")
                        object.graphicsCpuMemMax = options.longs === String ? String(message.graphicsCpuMemMax) : message.graphicsCpuMemMax;
                    else
                        object.graphicsCpuMemMax = options.longs === String ? $util.Long.prototype.toString.call(message.graphicsCpuMemMax) : options.longs === Number ? new $util.LongBits(message.graphicsCpuMemMax.low >>> 0, message.graphicsCpuMemMax.high >>> 0).toNumber() : message.graphicsCpuMemMax;
                if (message.graphicsCpuMemMin != null && message.hasOwnProperty("graphicsCpuMemMin"))
                    if (typeof message.graphicsCpuMemMin === "number")
                        object.graphicsCpuMemMin = options.longs === String ? String(message.graphicsCpuMemMin) : message.graphicsCpuMemMin;
                    else
                        object.graphicsCpuMemMin = options.longs === String ? $util.Long.prototype.toString.call(message.graphicsCpuMemMin) : options.longs === Number ? new $util.LongBits(message.graphicsCpuMemMin.low >>> 0, message.graphicsCpuMemMin.high >>> 0).toNumber() : message.graphicsCpuMemMin;
                if (message.graphicsCpuMemAvg != null && message.hasOwnProperty("graphicsCpuMemAvg"))
                    object.graphicsCpuMemAvg = options.json && !isFinite(message.graphicsCpuMemAvg) ? String(message.graphicsCpuMemAvg) : message.graphicsCpuMemAvg;
                if (message.graphicsGpuMemMax != null && message.hasOwnProperty("graphicsGpuMemMax"))
                    if (typeof message.graphicsGpuMemMax === "number")
                        object.graphicsGpuMemMax = options.longs === String ? String(message.graphicsGpuMemMax) : message.graphicsGpuMemMax;
                    else
                        object.graphicsGpuMemMax = options.longs === String ? $util.Long.prototype.toString.call(message.graphicsGpuMemMax) : options.longs === Number ? new $util.LongBits(message.graphicsGpuMemMax.low >>> 0, message.graphicsGpuMemMax.high >>> 0).toNumber() : message.graphicsGpuMemMax;
                if (message.graphicsGpuMemMin != null && message.hasOwnProperty("graphicsGpuMemMin"))
                    if (typeof message.graphicsGpuMemMin === "number")
                        object.graphicsGpuMemMin = options.longs === String ? String(message.graphicsGpuMemMin) : message.graphicsGpuMemMin;
                    else
                        object.graphicsGpuMemMin = options.longs === String ? $util.Long.prototype.toString.call(message.graphicsGpuMemMin) : options.longs === Number ? new $util.LongBits(message.graphicsGpuMemMin.low >>> 0, message.graphicsGpuMemMin.high >>> 0).toNumber() : message.graphicsGpuMemMin;
                if (message.graphicsGpuMemAvg != null && message.hasOwnProperty("graphicsGpuMemAvg"))
                    object.graphicsGpuMemAvg = options.json && !isFinite(message.graphicsGpuMemAvg) ? String(message.graphicsGpuMemAvg) : message.graphicsGpuMemAvg;
                if (message.textureMemMax != null && message.hasOwnProperty("textureMemMax"))
                    if (typeof message.textureMemMax === "number")
                        object.textureMemMax = options.longs === String ? String(message.textureMemMax) : message.textureMemMax;
                    else
                        object.textureMemMax = options.longs === String ? $util.Long.prototype.toString.call(message.textureMemMax) : options.longs === Number ? new $util.LongBits(message.textureMemMax.low >>> 0, message.textureMemMax.high >>> 0).toNumber() : message.textureMemMax;
                if (message.textureMemMin != null && message.hasOwnProperty("textureMemMin"))
                    if (typeof message.textureMemMin === "number")
                        object.textureMemMin = options.longs === String ? String(message.textureMemMin) : message.textureMemMin;
                    else
                        object.textureMemMin = options.longs === String ? $util.Long.prototype.toString.call(message.textureMemMin) : options.longs === Number ? new $util.LongBits(message.textureMemMin.low >>> 0, message.textureMemMin.high >>> 0).toNumber() : message.textureMemMin;
                if (message.textureMemAvg != null && message.hasOwnProperty("textureMemAvg"))
                    object.textureMemAvg = options.json && !isFinite(message.textureMemAvg) ? String(message.textureMemAvg) : message.textureMemAvg;
                if (message.allMemMax != null && message.hasOwnProperty("allMemMax"))
                    if (typeof message.allMemMax === "number")
                        object.allMemMax = options.longs === String ? String(message.allMemMax) : message.allMemMax;
                    else
                        object.allMemMax = options.longs === String ? $util.Long.prototype.toString.call(message.allMemMax) : options.longs === Number ? new $util.LongBits(message.allMemMax.low >>> 0, message.allMemMax.high >>> 0).toNumber() : message.allMemMax;
                if (message.allMemMin != null && message.hasOwnProperty("allMemMin"))
                    if (typeof message.allMemMin === "number")
                        object.allMemMin = options.longs === String ? String(message.allMemMin) : message.allMemMin;
                    else
                        object.allMemMin = options.longs === String ? $util.Long.prototype.toString.call(message.allMemMin) : options.longs === Number ? new $util.LongBits(message.allMemMin.low >>> 0, message.allMemMin.high >>> 0).toNumber() : message.allMemMin;
                if (message.allMemAvg != null && message.hasOwnProperty("allMemAvg"))
                    object.allMemAvg = options.json && !isFinite(message.allMemAvg) ? String(message.allMemAvg) : message.allMemAvg;
                return object;
            };

            /**
             * Converts this ProcessRenderInfo to JSON.
             * @function toJSON
             * @memberof perfetto.protos.ProcessRenderInfo
             * @instance
             * @returns {Object.<string,*>} JSON object
             */
            ProcessRenderInfo.prototype.toJSON = function toJSON() {
                return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
            };

            return ProcessRenderInfo;
        })();

        protos.AndroidHwuiMetric = (function() {

            /**
             * Properties of an AndroidHwuiMetric.
             * @memberof perfetto.protos
             * @interface IAndroidHwuiMetric
             * @property {Array.<perfetto.protos.IProcessRenderInfo>|null} [processInfo] AndroidHwuiMetric processInfo
             */

            /**
             * Constructs a new AndroidHwuiMetric.
             * @memberof perfetto.protos
             * @classdesc Represents an AndroidHwuiMetric.
             * @implements IAndroidHwuiMetric
             * @constructor
             * @param {perfetto.protos.IAndroidHwuiMetric=} [properties] Properties to set
             */
            function AndroidHwuiMetric(properties) {
                this.processInfo = [];
                if (properties)
                    for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                        if (properties[keys[i]] != null)
                            this[keys[i]] = properties[keys[i]];
            }

            /**
             * AndroidHwuiMetric processInfo.
             * @member {Array.<perfetto.protos.IProcessRenderInfo>} processInfo
             * @memberof perfetto.protos.AndroidHwuiMetric
             * @instance
             */
            AndroidHwuiMetric.prototype.processInfo = $util.emptyArray;

            /**
             * Creates a new AndroidHwuiMetric instance using the specified properties.
             * @function create
             * @memberof perfetto.protos.AndroidHwuiMetric
             * @static
             * @param {perfetto.protos.IAndroidHwuiMetric=} [properties] Properties to set
             * @returns {perfetto.protos.AndroidHwuiMetric} AndroidHwuiMetric instance
             */
            AndroidHwuiMetric.create = function create(properties) {
                return new AndroidHwuiMetric(properties);
            };

            /**
             * Encodes the specified AndroidHwuiMetric message. Does not implicitly {@link perfetto.protos.AndroidHwuiMetric.verify|verify} messages.
             * @function encode
             * @memberof perfetto.protos.AndroidHwuiMetric
             * @static
             * @param {perfetto.protos.IAndroidHwuiMetric} message AndroidHwuiMetric message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            AndroidHwuiMetric.encode = function encode(message, writer) {
                if (!writer)
                    writer = $Writer.create();
                if (message.processInfo != null && message.processInfo.length)
                    for (var i = 0; i < message.processInfo.length; ++i)
                        $root.perfetto.protos.ProcessRenderInfo.encode(message.processInfo[i], writer.uint32(/* id 1, wireType 2 =*/10).fork()).ldelim();
                return writer;
            };

            /**
             * Encodes the specified AndroidHwuiMetric message, length delimited. Does not implicitly {@link perfetto.protos.AndroidHwuiMetric.verify|verify} messages.
             * @function encodeDelimited
             * @memberof perfetto.protos.AndroidHwuiMetric
             * @static
             * @param {perfetto.protos.IAndroidHwuiMetric} message AndroidHwuiMetric message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            AndroidHwuiMetric.encodeDelimited = function encodeDelimited(message, writer) {
                return this.encode(message, writer).ldelim();
            };

            /**
             * Decodes an AndroidHwuiMetric message from the specified reader or buffer.
             * @function decode
             * @memberof perfetto.protos.AndroidHwuiMetric
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @param {number} [length] Message length if known beforehand
             * @returns {perfetto.protos.AndroidHwuiMetric} AndroidHwuiMetric
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            AndroidHwuiMetric.decode = function decode(reader, length) {
                if (!(reader instanceof $Reader))
                    reader = $Reader.create(reader);
                var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.AndroidHwuiMetric();
                while (reader.pos < end) {
                    var tag = reader.uint32();
                    switch (tag >>> 3) {
                    case 1:
                        if (!(message.processInfo && message.processInfo.length))
                            message.processInfo = [];
                        message.processInfo.push($root.perfetto.protos.ProcessRenderInfo.decode(reader, reader.uint32()));
                        break;
                    default:
                        reader.skipType(tag & 7);
                        break;
                    }
                }
                return message;
            };

            /**
             * Decodes an AndroidHwuiMetric message from the specified reader or buffer, length delimited.
             * @function decodeDelimited
             * @memberof perfetto.protos.AndroidHwuiMetric
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @returns {perfetto.protos.AndroidHwuiMetric} AndroidHwuiMetric
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            AndroidHwuiMetric.decodeDelimited = function decodeDelimited(reader) {
                if (!(reader instanceof $Reader))
                    reader = new $Reader(reader);
                return this.decode(reader, reader.uint32());
            };

            /**
             * Verifies an AndroidHwuiMetric message.
             * @function verify
             * @memberof perfetto.protos.AndroidHwuiMetric
             * @static
             * @param {Object.<string,*>} message Plain object to verify
             * @returns {string|null} `null` if valid, otherwise the reason why it is not
             */
            AndroidHwuiMetric.verify = function verify(message) {
                if (typeof message !== "object" || message === null)
                    return "object expected";
                if (message.processInfo != null && message.hasOwnProperty("processInfo")) {
                    if (!Array.isArray(message.processInfo))
                        return "processInfo: array expected";
                    for (var i = 0; i < message.processInfo.length; ++i) {
                        var error = $root.perfetto.protos.ProcessRenderInfo.verify(message.processInfo[i]);
                        if (error)
                            return "processInfo." + error;
                    }
                }
                return null;
            };

            /**
             * Creates an AndroidHwuiMetric message from a plain object. Also converts values to their respective internal types.
             * @function fromObject
             * @memberof perfetto.protos.AndroidHwuiMetric
             * @static
             * @param {Object.<string,*>} object Plain object
             * @returns {perfetto.protos.AndroidHwuiMetric} AndroidHwuiMetric
             */
            AndroidHwuiMetric.fromObject = function fromObject(object) {
                if (object instanceof $root.perfetto.protos.AndroidHwuiMetric)
                    return object;
                var message = new $root.perfetto.protos.AndroidHwuiMetric();
                if (object.processInfo) {
                    if (!Array.isArray(object.processInfo))
                        throw TypeError(".perfetto.protos.AndroidHwuiMetric.processInfo: array expected");
                    message.processInfo = [];
                    for (var i = 0; i < object.processInfo.length; ++i) {
                        if (typeof object.processInfo[i] !== "object")
                            throw TypeError(".perfetto.protos.AndroidHwuiMetric.processInfo: object expected");
                        message.processInfo[i] = $root.perfetto.protos.ProcessRenderInfo.fromObject(object.processInfo[i]);
                    }
                }
                return message;
            };

            /**
             * Creates a plain object from an AndroidHwuiMetric message. Also converts values to other types if specified.
             * @function toObject
             * @memberof perfetto.protos.AndroidHwuiMetric
             * @static
             * @param {perfetto.protos.AndroidHwuiMetric} message AndroidHwuiMetric
             * @param {$protobuf.IConversionOptions} [options] Conversion options
             * @returns {Object.<string,*>} Plain object
             */
            AndroidHwuiMetric.toObject = function toObject(message, options) {
                if (!options)
                    options = {};
                var object = {};
                if (options.arrays || options.defaults)
                    object.processInfo = [];
                if (message.processInfo && message.processInfo.length) {
                    object.processInfo = [];
                    for (var j = 0; j < message.processInfo.length; ++j)
                        object.processInfo[j] = $root.perfetto.protos.ProcessRenderInfo.toObject(message.processInfo[j], options);
                }
                return object;
            };

            /**
             * Converts this AndroidHwuiMetric to JSON.
             * @function toJSON
             * @memberof perfetto.protos.AndroidHwuiMetric
             * @instance
             * @returns {Object.<string,*>} JSON object
             */
            AndroidHwuiMetric.prototype.toJSON = function toJSON() {
                return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
            };

            return AndroidHwuiMetric;
        })();

        protos.AndroidIonMetric = (function() {

            /**
             * Properties of an AndroidIonMetric.
             * @memberof perfetto.protos
             * @interface IAndroidIonMetric
             * @property {Array.<perfetto.protos.AndroidIonMetric.IBuffer>|null} [buffer] AndroidIonMetric buffer
             */

            /**
             * Constructs a new AndroidIonMetric.
             * @memberof perfetto.protos
             * @classdesc Represents an AndroidIonMetric.
             * @implements IAndroidIonMetric
             * @constructor
             * @param {perfetto.protos.IAndroidIonMetric=} [properties] Properties to set
             */
            function AndroidIonMetric(properties) {
                this.buffer = [];
                if (properties)
                    for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                        if (properties[keys[i]] != null)
                            this[keys[i]] = properties[keys[i]];
            }

            /**
             * AndroidIonMetric buffer.
             * @member {Array.<perfetto.protos.AndroidIonMetric.IBuffer>} buffer
             * @memberof perfetto.protos.AndroidIonMetric
             * @instance
             */
            AndroidIonMetric.prototype.buffer = $util.emptyArray;

            /**
             * Creates a new AndroidIonMetric instance using the specified properties.
             * @function create
             * @memberof perfetto.protos.AndroidIonMetric
             * @static
             * @param {perfetto.protos.IAndroidIonMetric=} [properties] Properties to set
             * @returns {perfetto.protos.AndroidIonMetric} AndroidIonMetric instance
             */
            AndroidIonMetric.create = function create(properties) {
                return new AndroidIonMetric(properties);
            };

            /**
             * Encodes the specified AndroidIonMetric message. Does not implicitly {@link perfetto.protos.AndroidIonMetric.verify|verify} messages.
             * @function encode
             * @memberof perfetto.protos.AndroidIonMetric
             * @static
             * @param {perfetto.protos.IAndroidIonMetric} message AndroidIonMetric message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            AndroidIonMetric.encode = function encode(message, writer) {
                if (!writer)
                    writer = $Writer.create();
                if (message.buffer != null && message.buffer.length)
                    for (var i = 0; i < message.buffer.length; ++i)
                        $root.perfetto.protos.AndroidIonMetric.Buffer.encode(message.buffer[i], writer.uint32(/* id 1, wireType 2 =*/10).fork()).ldelim();
                return writer;
            };

            /**
             * Encodes the specified AndroidIonMetric message, length delimited. Does not implicitly {@link perfetto.protos.AndroidIonMetric.verify|verify} messages.
             * @function encodeDelimited
             * @memberof perfetto.protos.AndroidIonMetric
             * @static
             * @param {perfetto.protos.IAndroidIonMetric} message AndroidIonMetric message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            AndroidIonMetric.encodeDelimited = function encodeDelimited(message, writer) {
                return this.encode(message, writer).ldelim();
            };

            /**
             * Decodes an AndroidIonMetric message from the specified reader or buffer.
             * @function decode
             * @memberof perfetto.protos.AndroidIonMetric
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @param {number} [length] Message length if known beforehand
             * @returns {perfetto.protos.AndroidIonMetric} AndroidIonMetric
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            AndroidIonMetric.decode = function decode(reader, length) {
                if (!(reader instanceof $Reader))
                    reader = $Reader.create(reader);
                var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.AndroidIonMetric();
                while (reader.pos < end) {
                    var tag = reader.uint32();
                    switch (tag >>> 3) {
                    case 1:
                        if (!(message.buffer && message.buffer.length))
                            message.buffer = [];
                        message.buffer.push($root.perfetto.protos.AndroidIonMetric.Buffer.decode(reader, reader.uint32()));
                        break;
                    default:
                        reader.skipType(tag & 7);
                        break;
                    }
                }
                return message;
            };

            /**
             * Decodes an AndroidIonMetric message from the specified reader or buffer, length delimited.
             * @function decodeDelimited
             * @memberof perfetto.protos.AndroidIonMetric
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @returns {perfetto.protos.AndroidIonMetric} AndroidIonMetric
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            AndroidIonMetric.decodeDelimited = function decodeDelimited(reader) {
                if (!(reader instanceof $Reader))
                    reader = new $Reader(reader);
                return this.decode(reader, reader.uint32());
            };

            /**
             * Verifies an AndroidIonMetric message.
             * @function verify
             * @memberof perfetto.protos.AndroidIonMetric
             * @static
             * @param {Object.<string,*>} message Plain object to verify
             * @returns {string|null} `null` if valid, otherwise the reason why it is not
             */
            AndroidIonMetric.verify = function verify(message) {
                if (typeof message !== "object" || message === null)
                    return "object expected";
                if (message.buffer != null && message.hasOwnProperty("buffer")) {
                    if (!Array.isArray(message.buffer))
                        return "buffer: array expected";
                    for (var i = 0; i < message.buffer.length; ++i) {
                        var error = $root.perfetto.protos.AndroidIonMetric.Buffer.verify(message.buffer[i]);
                        if (error)
                            return "buffer." + error;
                    }
                }
                return null;
            };

            /**
             * Creates an AndroidIonMetric message from a plain object. Also converts values to their respective internal types.
             * @function fromObject
             * @memberof perfetto.protos.AndroidIonMetric
             * @static
             * @param {Object.<string,*>} object Plain object
             * @returns {perfetto.protos.AndroidIonMetric} AndroidIonMetric
             */
            AndroidIonMetric.fromObject = function fromObject(object) {
                if (object instanceof $root.perfetto.protos.AndroidIonMetric)
                    return object;
                var message = new $root.perfetto.protos.AndroidIonMetric();
                if (object.buffer) {
                    if (!Array.isArray(object.buffer))
                        throw TypeError(".perfetto.protos.AndroidIonMetric.buffer: array expected");
                    message.buffer = [];
                    for (var i = 0; i < object.buffer.length; ++i) {
                        if (typeof object.buffer[i] !== "object")
                            throw TypeError(".perfetto.protos.AndroidIonMetric.buffer: object expected");
                        message.buffer[i] = $root.perfetto.protos.AndroidIonMetric.Buffer.fromObject(object.buffer[i]);
                    }
                }
                return message;
            };

            /**
             * Creates a plain object from an AndroidIonMetric message. Also converts values to other types if specified.
             * @function toObject
             * @memberof perfetto.protos.AndroidIonMetric
             * @static
             * @param {perfetto.protos.AndroidIonMetric} message AndroidIonMetric
             * @param {$protobuf.IConversionOptions} [options] Conversion options
             * @returns {Object.<string,*>} Plain object
             */
            AndroidIonMetric.toObject = function toObject(message, options) {
                if (!options)
                    options = {};
                var object = {};
                if (options.arrays || options.defaults)
                    object.buffer = [];
                if (message.buffer && message.buffer.length) {
                    object.buffer = [];
                    for (var j = 0; j < message.buffer.length; ++j)
                        object.buffer[j] = $root.perfetto.protos.AndroidIonMetric.Buffer.toObject(message.buffer[j], options);
                }
                return object;
            };

            /**
             * Converts this AndroidIonMetric to JSON.
             * @function toJSON
             * @memberof perfetto.protos.AndroidIonMetric
             * @instance
             * @returns {Object.<string,*>} JSON object
             */
            AndroidIonMetric.prototype.toJSON = function toJSON() {
                return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
            };

            AndroidIonMetric.Buffer = (function() {

                /**
                 * Properties of a Buffer.
                 * @memberof perfetto.protos.AndroidIonMetric
                 * @interface IBuffer
                 * @property {string|null} [name] Buffer name
                 * @property {number|null} [avgSizeBytes] Buffer avgSizeBytes
                 * @property {number|null} [minSizeBytes] Buffer minSizeBytes
                 * @property {number|null} [maxSizeBytes] Buffer maxSizeBytes
                 * @property {number|null} [totalAllocSizeBytes] Buffer totalAllocSizeBytes
                 */

                /**
                 * Constructs a new Buffer.
                 * @memberof perfetto.protos.AndroidIonMetric
                 * @classdesc Represents a Buffer.
                 * @implements IBuffer
                 * @constructor
                 * @param {perfetto.protos.AndroidIonMetric.IBuffer=} [properties] Properties to set
                 */
                function Buffer(properties) {
                    if (properties)
                        for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                            if (properties[keys[i]] != null)
                                this[keys[i]] = properties[keys[i]];
                }

                /**
                 * Buffer name.
                 * @member {string} name
                 * @memberof perfetto.protos.AndroidIonMetric.Buffer
                 * @instance
                 */
                Buffer.prototype.name = "";

                /**
                 * Buffer avgSizeBytes.
                 * @member {number} avgSizeBytes
                 * @memberof perfetto.protos.AndroidIonMetric.Buffer
                 * @instance
                 */
                Buffer.prototype.avgSizeBytes = 0;

                /**
                 * Buffer minSizeBytes.
                 * @member {number} minSizeBytes
                 * @memberof perfetto.protos.AndroidIonMetric.Buffer
                 * @instance
                 */
                Buffer.prototype.minSizeBytes = 0;

                /**
                 * Buffer maxSizeBytes.
                 * @member {number} maxSizeBytes
                 * @memberof perfetto.protos.AndroidIonMetric.Buffer
                 * @instance
                 */
                Buffer.prototype.maxSizeBytes = 0;

                /**
                 * Buffer totalAllocSizeBytes.
                 * @member {number} totalAllocSizeBytes
                 * @memberof perfetto.protos.AndroidIonMetric.Buffer
                 * @instance
                 */
                Buffer.prototype.totalAllocSizeBytes = 0;

                /**
                 * Creates a new Buffer instance using the specified properties.
                 * @function create
                 * @memberof perfetto.protos.AndroidIonMetric.Buffer
                 * @static
                 * @param {perfetto.protos.AndroidIonMetric.IBuffer=} [properties] Properties to set
                 * @returns {perfetto.protos.AndroidIonMetric.Buffer} Buffer instance
                 */
                Buffer.create = function create(properties) {
                    return new Buffer(properties);
                };

                /**
                 * Encodes the specified Buffer message. Does not implicitly {@link perfetto.protos.AndroidIonMetric.Buffer.verify|verify} messages.
                 * @function encode
                 * @memberof perfetto.protos.AndroidIonMetric.Buffer
                 * @static
                 * @param {perfetto.protos.AndroidIonMetric.IBuffer} message Buffer message or plain object to encode
                 * @param {$protobuf.Writer} [writer] Writer to encode to
                 * @returns {$protobuf.Writer} Writer
                 */
                Buffer.encode = function encode(message, writer) {
                    if (!writer)
                        writer = $Writer.create();
                    if (message.name != null && Object.hasOwnProperty.call(message, "name"))
                        writer.uint32(/* id 1, wireType 2 =*/10).string(message.name);
                    if (message.avgSizeBytes != null && Object.hasOwnProperty.call(message, "avgSizeBytes"))
                        writer.uint32(/* id 2, wireType 1 =*/17).double(message.avgSizeBytes);
                    if (message.minSizeBytes != null && Object.hasOwnProperty.call(message, "minSizeBytes"))
                        writer.uint32(/* id 3, wireType 1 =*/25).double(message.minSizeBytes);
                    if (message.maxSizeBytes != null && Object.hasOwnProperty.call(message, "maxSizeBytes"))
                        writer.uint32(/* id 4, wireType 1 =*/33).double(message.maxSizeBytes);
                    if (message.totalAllocSizeBytes != null && Object.hasOwnProperty.call(message, "totalAllocSizeBytes"))
                        writer.uint32(/* id 5, wireType 1 =*/41).double(message.totalAllocSizeBytes);
                    return writer;
                };

                /**
                 * Encodes the specified Buffer message, length delimited. Does not implicitly {@link perfetto.protos.AndroidIonMetric.Buffer.verify|verify} messages.
                 * @function encodeDelimited
                 * @memberof perfetto.protos.AndroidIonMetric.Buffer
                 * @static
                 * @param {perfetto.protos.AndroidIonMetric.IBuffer} message Buffer message or plain object to encode
                 * @param {$protobuf.Writer} [writer] Writer to encode to
                 * @returns {$protobuf.Writer} Writer
                 */
                Buffer.encodeDelimited = function encodeDelimited(message, writer) {
                    return this.encode(message, writer).ldelim();
                };

                /**
                 * Decodes a Buffer message from the specified reader or buffer.
                 * @function decode
                 * @memberof perfetto.protos.AndroidIonMetric.Buffer
                 * @static
                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                 * @param {number} [length] Message length if known beforehand
                 * @returns {perfetto.protos.AndroidIonMetric.Buffer} Buffer
                 * @throws {Error} If the payload is not a reader or valid buffer
                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
                 */
                Buffer.decode = function decode(reader, length) {
                    if (!(reader instanceof $Reader))
                        reader = $Reader.create(reader);
                    var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.AndroidIonMetric.Buffer();
                    while (reader.pos < end) {
                        var tag = reader.uint32();
                        switch (tag >>> 3) {
                        case 1:
                            message.name = reader.string();
                            break;
                        case 2:
                            message.avgSizeBytes = reader.double();
                            break;
                        case 3:
                            message.minSizeBytes = reader.double();
                            break;
                        case 4:
                            message.maxSizeBytes = reader.double();
                            break;
                        case 5:
                            message.totalAllocSizeBytes = reader.double();
                            break;
                        default:
                            reader.skipType(tag & 7);
                            break;
                        }
                    }
                    return message;
                };

                /**
                 * Decodes a Buffer message from the specified reader or buffer, length delimited.
                 * @function decodeDelimited
                 * @memberof perfetto.protos.AndroidIonMetric.Buffer
                 * @static
                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                 * @returns {perfetto.protos.AndroidIonMetric.Buffer} Buffer
                 * @throws {Error} If the payload is not a reader or valid buffer
                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
                 */
                Buffer.decodeDelimited = function decodeDelimited(reader) {
                    if (!(reader instanceof $Reader))
                        reader = new $Reader(reader);
                    return this.decode(reader, reader.uint32());
                };

                /**
                 * Verifies a Buffer message.
                 * @function verify
                 * @memberof perfetto.protos.AndroidIonMetric.Buffer
                 * @static
                 * @param {Object.<string,*>} message Plain object to verify
                 * @returns {string|null} `null` if valid, otherwise the reason why it is not
                 */
                Buffer.verify = function verify(message) {
                    if (typeof message !== "object" || message === null)
                        return "object expected";
                    if (message.name != null && message.hasOwnProperty("name"))
                        if (!$util.isString(message.name))
                            return "name: string expected";
                    if (message.avgSizeBytes != null && message.hasOwnProperty("avgSizeBytes"))
                        if (typeof message.avgSizeBytes !== "number")
                            return "avgSizeBytes: number expected";
                    if (message.minSizeBytes != null && message.hasOwnProperty("minSizeBytes"))
                        if (typeof message.minSizeBytes !== "number")
                            return "minSizeBytes: number expected";
                    if (message.maxSizeBytes != null && message.hasOwnProperty("maxSizeBytes"))
                        if (typeof message.maxSizeBytes !== "number")
                            return "maxSizeBytes: number expected";
                    if (message.totalAllocSizeBytes != null && message.hasOwnProperty("totalAllocSizeBytes"))
                        if (typeof message.totalAllocSizeBytes !== "number")
                            return "totalAllocSizeBytes: number expected";
                    return null;
                };

                /**
                 * Creates a Buffer message from a plain object. Also converts values to their respective internal types.
                 * @function fromObject
                 * @memberof perfetto.protos.AndroidIonMetric.Buffer
                 * @static
                 * @param {Object.<string,*>} object Plain object
                 * @returns {perfetto.protos.AndroidIonMetric.Buffer} Buffer
                 */
                Buffer.fromObject = function fromObject(object) {
                    if (object instanceof $root.perfetto.protos.AndroidIonMetric.Buffer)
                        return object;
                    var message = new $root.perfetto.protos.AndroidIonMetric.Buffer();
                    if (object.name != null)
                        message.name = String(object.name);
                    if (object.avgSizeBytes != null)
                        message.avgSizeBytes = Number(object.avgSizeBytes);
                    if (object.minSizeBytes != null)
                        message.minSizeBytes = Number(object.minSizeBytes);
                    if (object.maxSizeBytes != null)
                        message.maxSizeBytes = Number(object.maxSizeBytes);
                    if (object.totalAllocSizeBytes != null)
                        message.totalAllocSizeBytes = Number(object.totalAllocSizeBytes);
                    return message;
                };

                /**
                 * Creates a plain object from a Buffer message. Also converts values to other types if specified.
                 * @function toObject
                 * @memberof perfetto.protos.AndroidIonMetric.Buffer
                 * @static
                 * @param {perfetto.protos.AndroidIonMetric.Buffer} message Buffer
                 * @param {$protobuf.IConversionOptions} [options] Conversion options
                 * @returns {Object.<string,*>} Plain object
                 */
                Buffer.toObject = function toObject(message, options) {
                    if (!options)
                        options = {};
                    var object = {};
                    if (options.defaults) {
                        object.name = "";
                        object.avgSizeBytes = 0;
                        object.minSizeBytes = 0;
                        object.maxSizeBytes = 0;
                        object.totalAllocSizeBytes = 0;
                    }
                    if (message.name != null && message.hasOwnProperty("name"))
                        object.name = message.name;
                    if (message.avgSizeBytes != null && message.hasOwnProperty("avgSizeBytes"))
                        object.avgSizeBytes = options.json && !isFinite(message.avgSizeBytes) ? String(message.avgSizeBytes) : message.avgSizeBytes;
                    if (message.minSizeBytes != null && message.hasOwnProperty("minSizeBytes"))
                        object.minSizeBytes = options.json && !isFinite(message.minSizeBytes) ? String(message.minSizeBytes) : message.minSizeBytes;
                    if (message.maxSizeBytes != null && message.hasOwnProperty("maxSizeBytes"))
                        object.maxSizeBytes = options.json && !isFinite(message.maxSizeBytes) ? String(message.maxSizeBytes) : message.maxSizeBytes;
                    if (message.totalAllocSizeBytes != null && message.hasOwnProperty("totalAllocSizeBytes"))
                        object.totalAllocSizeBytes = options.json && !isFinite(message.totalAllocSizeBytes) ? String(message.totalAllocSizeBytes) : message.totalAllocSizeBytes;
                    return object;
                };

                /**
                 * Converts this Buffer to JSON.
                 * @function toJSON
                 * @memberof perfetto.protos.AndroidIonMetric.Buffer
                 * @instance
                 * @returns {Object.<string,*>} JSON object
                 */
                Buffer.prototype.toJSON = function toJSON() {
                    return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
                };

                return Buffer;
            })();

            return AndroidIonMetric;
        })();

        protos.AndroidJankMetrics = (function() {

            /**
             * Properties of an AndroidJankMetrics.
             * @memberof perfetto.protos
             * @interface IAndroidJankMetrics
             * @property {Array.<perfetto.protos.AndroidJankMetrics.IWarning>|null} [warnings] AndroidJankMetrics warnings
             */

            /**
             * Constructs a new AndroidJankMetrics.
             * @memberof perfetto.protos
             * @classdesc Represents an AndroidJankMetrics.
             * @implements IAndroidJankMetrics
             * @constructor
             * @param {perfetto.protos.IAndroidJankMetrics=} [properties] Properties to set
             */
            function AndroidJankMetrics(properties) {
                this.warnings = [];
                if (properties)
                    for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                        if (properties[keys[i]] != null)
                            this[keys[i]] = properties[keys[i]];
            }

            /**
             * AndroidJankMetrics warnings.
             * @member {Array.<perfetto.protos.AndroidJankMetrics.IWarning>} warnings
             * @memberof perfetto.protos.AndroidJankMetrics
             * @instance
             */
            AndroidJankMetrics.prototype.warnings = $util.emptyArray;

            /**
             * Creates a new AndroidJankMetrics instance using the specified properties.
             * @function create
             * @memberof perfetto.protos.AndroidJankMetrics
             * @static
             * @param {perfetto.protos.IAndroidJankMetrics=} [properties] Properties to set
             * @returns {perfetto.protos.AndroidJankMetrics} AndroidJankMetrics instance
             */
            AndroidJankMetrics.create = function create(properties) {
                return new AndroidJankMetrics(properties);
            };

            /**
             * Encodes the specified AndroidJankMetrics message. Does not implicitly {@link perfetto.protos.AndroidJankMetrics.verify|verify} messages.
             * @function encode
             * @memberof perfetto.protos.AndroidJankMetrics
             * @static
             * @param {perfetto.protos.IAndroidJankMetrics} message AndroidJankMetrics message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            AndroidJankMetrics.encode = function encode(message, writer) {
                if (!writer)
                    writer = $Writer.create();
                if (message.warnings != null && message.warnings.length)
                    for (var i = 0; i < message.warnings.length; ++i)
                        $root.perfetto.protos.AndroidJankMetrics.Warning.encode(message.warnings[i], writer.uint32(/* id 1, wireType 2 =*/10).fork()).ldelim();
                return writer;
            };

            /**
             * Encodes the specified AndroidJankMetrics message, length delimited. Does not implicitly {@link perfetto.protos.AndroidJankMetrics.verify|verify} messages.
             * @function encodeDelimited
             * @memberof perfetto.protos.AndroidJankMetrics
             * @static
             * @param {perfetto.protos.IAndroidJankMetrics} message AndroidJankMetrics message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            AndroidJankMetrics.encodeDelimited = function encodeDelimited(message, writer) {
                return this.encode(message, writer).ldelim();
            };

            /**
             * Decodes an AndroidJankMetrics message from the specified reader or buffer.
             * @function decode
             * @memberof perfetto.protos.AndroidJankMetrics
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @param {number} [length] Message length if known beforehand
             * @returns {perfetto.protos.AndroidJankMetrics} AndroidJankMetrics
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            AndroidJankMetrics.decode = function decode(reader, length) {
                if (!(reader instanceof $Reader))
                    reader = $Reader.create(reader);
                var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.AndroidJankMetrics();
                while (reader.pos < end) {
                    var tag = reader.uint32();
                    switch (tag >>> 3) {
                    case 1:
                        if (!(message.warnings && message.warnings.length))
                            message.warnings = [];
                        message.warnings.push($root.perfetto.protos.AndroidJankMetrics.Warning.decode(reader, reader.uint32()));
                        break;
                    default:
                        reader.skipType(tag & 7);
                        break;
                    }
                }
                return message;
            };

            /**
             * Decodes an AndroidJankMetrics message from the specified reader or buffer, length delimited.
             * @function decodeDelimited
             * @memberof perfetto.protos.AndroidJankMetrics
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @returns {perfetto.protos.AndroidJankMetrics} AndroidJankMetrics
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            AndroidJankMetrics.decodeDelimited = function decodeDelimited(reader) {
                if (!(reader instanceof $Reader))
                    reader = new $Reader(reader);
                return this.decode(reader, reader.uint32());
            };

            /**
             * Verifies an AndroidJankMetrics message.
             * @function verify
             * @memberof perfetto.protos.AndroidJankMetrics
             * @static
             * @param {Object.<string,*>} message Plain object to verify
             * @returns {string|null} `null` if valid, otherwise the reason why it is not
             */
            AndroidJankMetrics.verify = function verify(message) {
                if (typeof message !== "object" || message === null)
                    return "object expected";
                if (message.warnings != null && message.hasOwnProperty("warnings")) {
                    if (!Array.isArray(message.warnings))
                        return "warnings: array expected";
                    for (var i = 0; i < message.warnings.length; ++i) {
                        var error = $root.perfetto.protos.AndroidJankMetrics.Warning.verify(message.warnings[i]);
                        if (error)
                            return "warnings." + error;
                    }
                }
                return null;
            };

            /**
             * Creates an AndroidJankMetrics message from a plain object. Also converts values to their respective internal types.
             * @function fromObject
             * @memberof perfetto.protos.AndroidJankMetrics
             * @static
             * @param {Object.<string,*>} object Plain object
             * @returns {perfetto.protos.AndroidJankMetrics} AndroidJankMetrics
             */
            AndroidJankMetrics.fromObject = function fromObject(object) {
                if (object instanceof $root.perfetto.protos.AndroidJankMetrics)
                    return object;
                var message = new $root.perfetto.protos.AndroidJankMetrics();
                if (object.warnings) {
                    if (!Array.isArray(object.warnings))
                        throw TypeError(".perfetto.protos.AndroidJankMetrics.warnings: array expected");
                    message.warnings = [];
                    for (var i = 0; i < object.warnings.length; ++i) {
                        if (typeof object.warnings[i] !== "object")
                            throw TypeError(".perfetto.protos.AndroidJankMetrics.warnings: object expected");
                        message.warnings[i] = $root.perfetto.protos.AndroidJankMetrics.Warning.fromObject(object.warnings[i]);
                    }
                }
                return message;
            };

            /**
             * Creates a plain object from an AndroidJankMetrics message. Also converts values to other types if specified.
             * @function toObject
             * @memberof perfetto.protos.AndroidJankMetrics
             * @static
             * @param {perfetto.protos.AndroidJankMetrics} message AndroidJankMetrics
             * @param {$protobuf.IConversionOptions} [options] Conversion options
             * @returns {Object.<string,*>} Plain object
             */
            AndroidJankMetrics.toObject = function toObject(message, options) {
                if (!options)
                    options = {};
                var object = {};
                if (options.arrays || options.defaults)
                    object.warnings = [];
                if (message.warnings && message.warnings.length) {
                    object.warnings = [];
                    for (var j = 0; j < message.warnings.length; ++j)
                        object.warnings[j] = $root.perfetto.protos.AndroidJankMetrics.Warning.toObject(message.warnings[j], options);
                }
                return object;
            };

            /**
             * Converts this AndroidJankMetrics to JSON.
             * @function toJSON
             * @memberof perfetto.protos.AndroidJankMetrics
             * @instance
             * @returns {Object.<string,*>} JSON object
             */
            AndroidJankMetrics.prototype.toJSON = function toJSON() {
                return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
            };

            AndroidJankMetrics.Warning = (function() {

                /**
                 * Properties of a Warning.
                 * @memberof perfetto.protos.AndroidJankMetrics
                 * @interface IWarning
                 * @property {number|null} [ts] Warning ts
                 * @property {number|null} [dur] Warning dur
                 * @property {string|null} [processName] Warning processName
                 * @property {string|null} [warningText] Warning warningText
                 */

                /**
                 * Constructs a new Warning.
                 * @memberof perfetto.protos.AndroidJankMetrics
                 * @classdesc Represents a Warning.
                 * @implements IWarning
                 * @constructor
                 * @param {perfetto.protos.AndroidJankMetrics.IWarning=} [properties] Properties to set
                 */
                function Warning(properties) {
                    if (properties)
                        for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                            if (properties[keys[i]] != null)
                                this[keys[i]] = properties[keys[i]];
                }

                /**
                 * Warning ts.
                 * @member {number} ts
                 * @memberof perfetto.protos.AndroidJankMetrics.Warning
                 * @instance
                 */
                Warning.prototype.ts = $util.Long ? $util.Long.fromBits(0,0,false) : 0;

                /**
                 * Warning dur.
                 * @member {number} dur
                 * @memberof perfetto.protos.AndroidJankMetrics.Warning
                 * @instance
                 */
                Warning.prototype.dur = $util.Long ? $util.Long.fromBits(0,0,false) : 0;

                /**
                 * Warning processName.
                 * @member {string} processName
                 * @memberof perfetto.protos.AndroidJankMetrics.Warning
                 * @instance
                 */
                Warning.prototype.processName = "";

                /**
                 * Warning warningText.
                 * @member {string} warningText
                 * @memberof perfetto.protos.AndroidJankMetrics.Warning
                 * @instance
                 */
                Warning.prototype.warningText = "";

                /**
                 * Creates a new Warning instance using the specified properties.
                 * @function create
                 * @memberof perfetto.protos.AndroidJankMetrics.Warning
                 * @static
                 * @param {perfetto.protos.AndroidJankMetrics.IWarning=} [properties] Properties to set
                 * @returns {perfetto.protos.AndroidJankMetrics.Warning} Warning instance
                 */
                Warning.create = function create(properties) {
                    return new Warning(properties);
                };

                /**
                 * Encodes the specified Warning message. Does not implicitly {@link perfetto.protos.AndroidJankMetrics.Warning.verify|verify} messages.
                 * @function encode
                 * @memberof perfetto.protos.AndroidJankMetrics.Warning
                 * @static
                 * @param {perfetto.protos.AndroidJankMetrics.IWarning} message Warning message or plain object to encode
                 * @param {$protobuf.Writer} [writer] Writer to encode to
                 * @returns {$protobuf.Writer} Writer
                 */
                Warning.encode = function encode(message, writer) {
                    if (!writer)
                        writer = $Writer.create();
                    if (message.ts != null && Object.hasOwnProperty.call(message, "ts"))
                        writer.uint32(/* id 1, wireType 0 =*/8).int64(message.ts);
                    if (message.dur != null && Object.hasOwnProperty.call(message, "dur"))
                        writer.uint32(/* id 2, wireType 0 =*/16).int64(message.dur);
                    if (message.processName != null && Object.hasOwnProperty.call(message, "processName"))
                        writer.uint32(/* id 3, wireType 2 =*/26).string(message.processName);
                    if (message.warningText != null && Object.hasOwnProperty.call(message, "warningText"))
                        writer.uint32(/* id 4, wireType 2 =*/34).string(message.warningText);
                    return writer;
                };

                /**
                 * Encodes the specified Warning message, length delimited. Does not implicitly {@link perfetto.protos.AndroidJankMetrics.Warning.verify|verify} messages.
                 * @function encodeDelimited
                 * @memberof perfetto.protos.AndroidJankMetrics.Warning
                 * @static
                 * @param {perfetto.protos.AndroidJankMetrics.IWarning} message Warning message or plain object to encode
                 * @param {$protobuf.Writer} [writer] Writer to encode to
                 * @returns {$protobuf.Writer} Writer
                 */
                Warning.encodeDelimited = function encodeDelimited(message, writer) {
                    return this.encode(message, writer).ldelim();
                };

                /**
                 * Decodes a Warning message from the specified reader or buffer.
                 * @function decode
                 * @memberof perfetto.protos.AndroidJankMetrics.Warning
                 * @static
                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                 * @param {number} [length] Message length if known beforehand
                 * @returns {perfetto.protos.AndroidJankMetrics.Warning} Warning
                 * @throws {Error} If the payload is not a reader or valid buffer
                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
                 */
                Warning.decode = function decode(reader, length) {
                    if (!(reader instanceof $Reader))
                        reader = $Reader.create(reader);
                    var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.AndroidJankMetrics.Warning();
                    while (reader.pos < end) {
                        var tag = reader.uint32();
                        switch (tag >>> 3) {
                        case 1:
                            message.ts = reader.int64();
                            break;
                        case 2:
                            message.dur = reader.int64();
                            break;
                        case 3:
                            message.processName = reader.string();
                            break;
                        case 4:
                            message.warningText = reader.string();
                            break;
                        default:
                            reader.skipType(tag & 7);
                            break;
                        }
                    }
                    return message;
                };

                /**
                 * Decodes a Warning message from the specified reader or buffer, length delimited.
                 * @function decodeDelimited
                 * @memberof perfetto.protos.AndroidJankMetrics.Warning
                 * @static
                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                 * @returns {perfetto.protos.AndroidJankMetrics.Warning} Warning
                 * @throws {Error} If the payload is not a reader or valid buffer
                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
                 */
                Warning.decodeDelimited = function decodeDelimited(reader) {
                    if (!(reader instanceof $Reader))
                        reader = new $Reader(reader);
                    return this.decode(reader, reader.uint32());
                };

                /**
                 * Verifies a Warning message.
                 * @function verify
                 * @memberof perfetto.protos.AndroidJankMetrics.Warning
                 * @static
                 * @param {Object.<string,*>} message Plain object to verify
                 * @returns {string|null} `null` if valid, otherwise the reason why it is not
                 */
                Warning.verify = function verify(message) {
                    if (typeof message !== "object" || message === null)
                        return "object expected";
                    if (message.ts != null && message.hasOwnProperty("ts"))
                        if (!$util.isInteger(message.ts) && !(message.ts && $util.isInteger(message.ts.low) && $util.isInteger(message.ts.high)))
                            return "ts: integer|Long expected";
                    if (message.dur != null && message.hasOwnProperty("dur"))
                        if (!$util.isInteger(message.dur) && !(message.dur && $util.isInteger(message.dur.low) && $util.isInteger(message.dur.high)))
                            return "dur: integer|Long expected";
                    if (message.processName != null && message.hasOwnProperty("processName"))
                        if (!$util.isString(message.processName))
                            return "processName: string expected";
                    if (message.warningText != null && message.hasOwnProperty("warningText"))
                        if (!$util.isString(message.warningText))
                            return "warningText: string expected";
                    return null;
                };

                /**
                 * Creates a Warning message from a plain object. Also converts values to their respective internal types.
                 * @function fromObject
                 * @memberof perfetto.protos.AndroidJankMetrics.Warning
                 * @static
                 * @param {Object.<string,*>} object Plain object
                 * @returns {perfetto.protos.AndroidJankMetrics.Warning} Warning
                 */
                Warning.fromObject = function fromObject(object) {
                    if (object instanceof $root.perfetto.protos.AndroidJankMetrics.Warning)
                        return object;
                    var message = new $root.perfetto.protos.AndroidJankMetrics.Warning();
                    if (object.ts != null)
                        if ($util.Long)
                            (message.ts = $util.Long.fromValue(object.ts)).unsigned = false;
                        else if (typeof object.ts === "string")
                            message.ts = parseInt(object.ts, 10);
                        else if (typeof object.ts === "number")
                            message.ts = object.ts;
                        else if (typeof object.ts === "object")
                            message.ts = new $util.LongBits(object.ts.low >>> 0, object.ts.high >>> 0).toNumber();
                    if (object.dur != null)
                        if ($util.Long)
                            (message.dur = $util.Long.fromValue(object.dur)).unsigned = false;
                        else if (typeof object.dur === "string")
                            message.dur = parseInt(object.dur, 10);
                        else if (typeof object.dur === "number")
                            message.dur = object.dur;
                        else if (typeof object.dur === "object")
                            message.dur = new $util.LongBits(object.dur.low >>> 0, object.dur.high >>> 0).toNumber();
                    if (object.processName != null)
                        message.processName = String(object.processName);
                    if (object.warningText != null)
                        message.warningText = String(object.warningText);
                    return message;
                };

                /**
                 * Creates a plain object from a Warning message. Also converts values to other types if specified.
                 * @function toObject
                 * @memberof perfetto.protos.AndroidJankMetrics.Warning
                 * @static
                 * @param {perfetto.protos.AndroidJankMetrics.Warning} message Warning
                 * @param {$protobuf.IConversionOptions} [options] Conversion options
                 * @returns {Object.<string,*>} Plain object
                 */
                Warning.toObject = function toObject(message, options) {
                    if (!options)
                        options = {};
                    var object = {};
                    if (options.defaults) {
                        if ($util.Long) {
                            var long = new $util.Long(0, 0, false);
                            object.ts = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
                        } else
                            object.ts = options.longs === String ? "0" : 0;
                        if ($util.Long) {
                            var long = new $util.Long(0, 0, false);
                            object.dur = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
                        } else
                            object.dur = options.longs === String ? "0" : 0;
                        object.processName = "";
                        object.warningText = "";
                    }
                    if (message.ts != null && message.hasOwnProperty("ts"))
                        if (typeof message.ts === "number")
                            object.ts = options.longs === String ? String(message.ts) : message.ts;
                        else
                            object.ts = options.longs === String ? $util.Long.prototype.toString.call(message.ts) : options.longs === Number ? new $util.LongBits(message.ts.low >>> 0, message.ts.high >>> 0).toNumber() : message.ts;
                    if (message.dur != null && message.hasOwnProperty("dur"))
                        if (typeof message.dur === "number")
                            object.dur = options.longs === String ? String(message.dur) : message.dur;
                        else
                            object.dur = options.longs === String ? $util.Long.prototype.toString.call(message.dur) : options.longs === Number ? new $util.LongBits(message.dur.low >>> 0, message.dur.high >>> 0).toNumber() : message.dur;
                    if (message.processName != null && message.hasOwnProperty("processName"))
                        object.processName = message.processName;
                    if (message.warningText != null && message.hasOwnProperty("warningText"))
                        object.warningText = message.warningText;
                    return object;
                };

                /**
                 * Converts this Warning to JSON.
                 * @function toJSON
                 * @memberof perfetto.protos.AndroidJankMetrics.Warning
                 * @instance
                 * @returns {Object.<string,*>} JSON object
                 */
                Warning.prototype.toJSON = function toJSON() {
                    return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
                };

                return Warning;
            })();

            return AndroidJankMetrics;
        })();

        protos.JavaHeapHistogram = (function() {

            /**
             * Properties of a JavaHeapHistogram.
             * @memberof perfetto.protos
             * @interface IJavaHeapHistogram
             * @property {Array.<perfetto.protos.JavaHeapHistogram.IInstanceStats>|null} [instanceStats] JavaHeapHistogram instanceStats
             */

            /**
             * Constructs a new JavaHeapHistogram.
             * @memberof perfetto.protos
             * @classdesc Represents a JavaHeapHistogram.
             * @implements IJavaHeapHistogram
             * @constructor
             * @param {perfetto.protos.IJavaHeapHistogram=} [properties] Properties to set
             */
            function JavaHeapHistogram(properties) {
                this.instanceStats = [];
                if (properties)
                    for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                        if (properties[keys[i]] != null)
                            this[keys[i]] = properties[keys[i]];
            }

            /**
             * JavaHeapHistogram instanceStats.
             * @member {Array.<perfetto.protos.JavaHeapHistogram.IInstanceStats>} instanceStats
             * @memberof perfetto.protos.JavaHeapHistogram
             * @instance
             */
            JavaHeapHistogram.prototype.instanceStats = $util.emptyArray;

            /**
             * Creates a new JavaHeapHistogram instance using the specified properties.
             * @function create
             * @memberof perfetto.protos.JavaHeapHistogram
             * @static
             * @param {perfetto.protos.IJavaHeapHistogram=} [properties] Properties to set
             * @returns {perfetto.protos.JavaHeapHistogram} JavaHeapHistogram instance
             */
            JavaHeapHistogram.create = function create(properties) {
                return new JavaHeapHistogram(properties);
            };

            /**
             * Encodes the specified JavaHeapHistogram message. Does not implicitly {@link perfetto.protos.JavaHeapHistogram.verify|verify} messages.
             * @function encode
             * @memberof perfetto.protos.JavaHeapHistogram
             * @static
             * @param {perfetto.protos.IJavaHeapHistogram} message JavaHeapHistogram message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            JavaHeapHistogram.encode = function encode(message, writer) {
                if (!writer)
                    writer = $Writer.create();
                if (message.instanceStats != null && message.instanceStats.length)
                    for (var i = 0; i < message.instanceStats.length; ++i)
                        $root.perfetto.protos.JavaHeapHistogram.InstanceStats.encode(message.instanceStats[i], writer.uint32(/* id 1, wireType 2 =*/10).fork()).ldelim();
                return writer;
            };

            /**
             * Encodes the specified JavaHeapHistogram message, length delimited. Does not implicitly {@link perfetto.protos.JavaHeapHistogram.verify|verify} messages.
             * @function encodeDelimited
             * @memberof perfetto.protos.JavaHeapHistogram
             * @static
             * @param {perfetto.protos.IJavaHeapHistogram} message JavaHeapHistogram message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            JavaHeapHistogram.encodeDelimited = function encodeDelimited(message, writer) {
                return this.encode(message, writer).ldelim();
            };

            /**
             * Decodes a JavaHeapHistogram message from the specified reader or buffer.
             * @function decode
             * @memberof perfetto.protos.JavaHeapHistogram
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @param {number} [length] Message length if known beforehand
             * @returns {perfetto.protos.JavaHeapHistogram} JavaHeapHistogram
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            JavaHeapHistogram.decode = function decode(reader, length) {
                if (!(reader instanceof $Reader))
                    reader = $Reader.create(reader);
                var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.JavaHeapHistogram();
                while (reader.pos < end) {
                    var tag = reader.uint32();
                    switch (tag >>> 3) {
                    case 1:
                        if (!(message.instanceStats && message.instanceStats.length))
                            message.instanceStats = [];
                        message.instanceStats.push($root.perfetto.protos.JavaHeapHistogram.InstanceStats.decode(reader, reader.uint32()));
                        break;
                    default:
                        reader.skipType(tag & 7);
                        break;
                    }
                }
                return message;
            };

            /**
             * Decodes a JavaHeapHistogram message from the specified reader or buffer, length delimited.
             * @function decodeDelimited
             * @memberof perfetto.protos.JavaHeapHistogram
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @returns {perfetto.protos.JavaHeapHistogram} JavaHeapHistogram
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            JavaHeapHistogram.decodeDelimited = function decodeDelimited(reader) {
                if (!(reader instanceof $Reader))
                    reader = new $Reader(reader);
                return this.decode(reader, reader.uint32());
            };

            /**
             * Verifies a JavaHeapHistogram message.
             * @function verify
             * @memberof perfetto.protos.JavaHeapHistogram
             * @static
             * @param {Object.<string,*>} message Plain object to verify
             * @returns {string|null} `null` if valid, otherwise the reason why it is not
             */
            JavaHeapHistogram.verify = function verify(message) {
                if (typeof message !== "object" || message === null)
                    return "object expected";
                if (message.instanceStats != null && message.hasOwnProperty("instanceStats")) {
                    if (!Array.isArray(message.instanceStats))
                        return "instanceStats: array expected";
                    for (var i = 0; i < message.instanceStats.length; ++i) {
                        var error = $root.perfetto.protos.JavaHeapHistogram.InstanceStats.verify(message.instanceStats[i]);
                        if (error)
                            return "instanceStats." + error;
                    }
                }
                return null;
            };

            /**
             * Creates a JavaHeapHistogram message from a plain object. Also converts values to their respective internal types.
             * @function fromObject
             * @memberof perfetto.protos.JavaHeapHistogram
             * @static
             * @param {Object.<string,*>} object Plain object
             * @returns {perfetto.protos.JavaHeapHistogram} JavaHeapHistogram
             */
            JavaHeapHistogram.fromObject = function fromObject(object) {
                if (object instanceof $root.perfetto.protos.JavaHeapHistogram)
                    return object;
                var message = new $root.perfetto.protos.JavaHeapHistogram();
                if (object.instanceStats) {
                    if (!Array.isArray(object.instanceStats))
                        throw TypeError(".perfetto.protos.JavaHeapHistogram.instanceStats: array expected");
                    message.instanceStats = [];
                    for (var i = 0; i < object.instanceStats.length; ++i) {
                        if (typeof object.instanceStats[i] !== "object")
                            throw TypeError(".perfetto.protos.JavaHeapHistogram.instanceStats: object expected");
                        message.instanceStats[i] = $root.perfetto.protos.JavaHeapHistogram.InstanceStats.fromObject(object.instanceStats[i]);
                    }
                }
                return message;
            };

            /**
             * Creates a plain object from a JavaHeapHistogram message. Also converts values to other types if specified.
             * @function toObject
             * @memberof perfetto.protos.JavaHeapHistogram
             * @static
             * @param {perfetto.protos.JavaHeapHistogram} message JavaHeapHistogram
             * @param {$protobuf.IConversionOptions} [options] Conversion options
             * @returns {Object.<string,*>} Plain object
             */
            JavaHeapHistogram.toObject = function toObject(message, options) {
                if (!options)
                    options = {};
                var object = {};
                if (options.arrays || options.defaults)
                    object.instanceStats = [];
                if (message.instanceStats && message.instanceStats.length) {
                    object.instanceStats = [];
                    for (var j = 0; j < message.instanceStats.length; ++j)
                        object.instanceStats[j] = $root.perfetto.protos.JavaHeapHistogram.InstanceStats.toObject(message.instanceStats[j], options);
                }
                return object;
            };

            /**
             * Converts this JavaHeapHistogram to JSON.
             * @function toJSON
             * @memberof perfetto.protos.JavaHeapHistogram
             * @instance
             * @returns {Object.<string,*>} JSON object
             */
            JavaHeapHistogram.prototype.toJSON = function toJSON() {
                return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
            };

            JavaHeapHistogram.TypeCount = (function() {

                /**
                 * Properties of a TypeCount.
                 * @memberof perfetto.protos.JavaHeapHistogram
                 * @interface ITypeCount
                 * @property {string|null} [typeName] TypeCount typeName
                 * @property {string|null} [category] TypeCount category
                 * @property {number|null} [objCount] TypeCount objCount
                 * @property {number|null} [reachableObjCount] TypeCount reachableObjCount
                 */

                /**
                 * Constructs a new TypeCount.
                 * @memberof perfetto.protos.JavaHeapHistogram
                 * @classdesc Represents a TypeCount.
                 * @implements ITypeCount
                 * @constructor
                 * @param {perfetto.protos.JavaHeapHistogram.ITypeCount=} [properties] Properties to set
                 */
                function TypeCount(properties) {
                    if (properties)
                        for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                            if (properties[keys[i]] != null)
                                this[keys[i]] = properties[keys[i]];
                }

                /**
                 * TypeCount typeName.
                 * @member {string} typeName
                 * @memberof perfetto.protos.JavaHeapHistogram.TypeCount
                 * @instance
                 */
                TypeCount.prototype.typeName = "";

                /**
                 * TypeCount category.
                 * @member {string} category
                 * @memberof perfetto.protos.JavaHeapHistogram.TypeCount
                 * @instance
                 */
                TypeCount.prototype.category = "";

                /**
                 * TypeCount objCount.
                 * @member {number} objCount
                 * @memberof perfetto.protos.JavaHeapHistogram.TypeCount
                 * @instance
                 */
                TypeCount.prototype.objCount = 0;

                /**
                 * TypeCount reachableObjCount.
                 * @member {number} reachableObjCount
                 * @memberof perfetto.protos.JavaHeapHistogram.TypeCount
                 * @instance
                 */
                TypeCount.prototype.reachableObjCount = 0;

                /**
                 * Creates a new TypeCount instance using the specified properties.
                 * @function create
                 * @memberof perfetto.protos.JavaHeapHistogram.TypeCount
                 * @static
                 * @param {perfetto.protos.JavaHeapHistogram.ITypeCount=} [properties] Properties to set
                 * @returns {perfetto.protos.JavaHeapHistogram.TypeCount} TypeCount instance
                 */
                TypeCount.create = function create(properties) {
                    return new TypeCount(properties);
                };

                /**
                 * Encodes the specified TypeCount message. Does not implicitly {@link perfetto.protos.JavaHeapHistogram.TypeCount.verify|verify} messages.
                 * @function encode
                 * @memberof perfetto.protos.JavaHeapHistogram.TypeCount
                 * @static
                 * @param {perfetto.protos.JavaHeapHistogram.ITypeCount} message TypeCount message or plain object to encode
                 * @param {$protobuf.Writer} [writer] Writer to encode to
                 * @returns {$protobuf.Writer} Writer
                 */
                TypeCount.encode = function encode(message, writer) {
                    if (!writer)
                        writer = $Writer.create();
                    if (message.typeName != null && Object.hasOwnProperty.call(message, "typeName"))
                        writer.uint32(/* id 1, wireType 2 =*/10).string(message.typeName);
                    if (message.objCount != null && Object.hasOwnProperty.call(message, "objCount"))
                        writer.uint32(/* id 2, wireType 0 =*/16).uint32(message.objCount);
                    if (message.reachableObjCount != null && Object.hasOwnProperty.call(message, "reachableObjCount"))
                        writer.uint32(/* id 3, wireType 0 =*/24).uint32(message.reachableObjCount);
                    if (message.category != null && Object.hasOwnProperty.call(message, "category"))
                        writer.uint32(/* id 4, wireType 2 =*/34).string(message.category);
                    return writer;
                };

                /**
                 * Encodes the specified TypeCount message, length delimited. Does not implicitly {@link perfetto.protos.JavaHeapHistogram.TypeCount.verify|verify} messages.
                 * @function encodeDelimited
                 * @memberof perfetto.protos.JavaHeapHistogram.TypeCount
                 * @static
                 * @param {perfetto.protos.JavaHeapHistogram.ITypeCount} message TypeCount message or plain object to encode
                 * @param {$protobuf.Writer} [writer] Writer to encode to
                 * @returns {$protobuf.Writer} Writer
                 */
                TypeCount.encodeDelimited = function encodeDelimited(message, writer) {
                    return this.encode(message, writer).ldelim();
                };

                /**
                 * Decodes a TypeCount message from the specified reader or buffer.
                 * @function decode
                 * @memberof perfetto.protos.JavaHeapHistogram.TypeCount
                 * @static
                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                 * @param {number} [length] Message length if known beforehand
                 * @returns {perfetto.protos.JavaHeapHistogram.TypeCount} TypeCount
                 * @throws {Error} If the payload is not a reader or valid buffer
                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
                 */
                TypeCount.decode = function decode(reader, length) {
                    if (!(reader instanceof $Reader))
                        reader = $Reader.create(reader);
                    var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.JavaHeapHistogram.TypeCount();
                    while (reader.pos < end) {
                        var tag = reader.uint32();
                        switch (tag >>> 3) {
                        case 1:
                            message.typeName = reader.string();
                            break;
                        case 4:
                            message.category = reader.string();
                            break;
                        case 2:
                            message.objCount = reader.uint32();
                            break;
                        case 3:
                            message.reachableObjCount = reader.uint32();
                            break;
                        default:
                            reader.skipType(tag & 7);
                            break;
                        }
                    }
                    return message;
                };

                /**
                 * Decodes a TypeCount message from the specified reader or buffer, length delimited.
                 * @function decodeDelimited
                 * @memberof perfetto.protos.JavaHeapHistogram.TypeCount
                 * @static
                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                 * @returns {perfetto.protos.JavaHeapHistogram.TypeCount} TypeCount
                 * @throws {Error} If the payload is not a reader or valid buffer
                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
                 */
                TypeCount.decodeDelimited = function decodeDelimited(reader) {
                    if (!(reader instanceof $Reader))
                        reader = new $Reader(reader);
                    return this.decode(reader, reader.uint32());
                };

                /**
                 * Verifies a TypeCount message.
                 * @function verify
                 * @memberof perfetto.protos.JavaHeapHistogram.TypeCount
                 * @static
                 * @param {Object.<string,*>} message Plain object to verify
                 * @returns {string|null} `null` if valid, otherwise the reason why it is not
                 */
                TypeCount.verify = function verify(message) {
                    if (typeof message !== "object" || message === null)
                        return "object expected";
                    if (message.typeName != null && message.hasOwnProperty("typeName"))
                        if (!$util.isString(message.typeName))
                            return "typeName: string expected";
                    if (message.category != null && message.hasOwnProperty("category"))
                        if (!$util.isString(message.category))
                            return "category: string expected";
                    if (message.objCount != null && message.hasOwnProperty("objCount"))
                        if (!$util.isInteger(message.objCount))
                            return "objCount: integer expected";
                    if (message.reachableObjCount != null && message.hasOwnProperty("reachableObjCount"))
                        if (!$util.isInteger(message.reachableObjCount))
                            return "reachableObjCount: integer expected";
                    return null;
                };

                /**
                 * Creates a TypeCount message from a plain object. Also converts values to their respective internal types.
                 * @function fromObject
                 * @memberof perfetto.protos.JavaHeapHistogram.TypeCount
                 * @static
                 * @param {Object.<string,*>} object Plain object
                 * @returns {perfetto.protos.JavaHeapHistogram.TypeCount} TypeCount
                 */
                TypeCount.fromObject = function fromObject(object) {
                    if (object instanceof $root.perfetto.protos.JavaHeapHistogram.TypeCount)
                        return object;
                    var message = new $root.perfetto.protos.JavaHeapHistogram.TypeCount();
                    if (object.typeName != null)
                        message.typeName = String(object.typeName);
                    if (object.category != null)
                        message.category = String(object.category);
                    if (object.objCount != null)
                        message.objCount = object.objCount >>> 0;
                    if (object.reachableObjCount != null)
                        message.reachableObjCount = object.reachableObjCount >>> 0;
                    return message;
                };

                /**
                 * Creates a plain object from a TypeCount message. Also converts values to other types if specified.
                 * @function toObject
                 * @memberof perfetto.protos.JavaHeapHistogram.TypeCount
                 * @static
                 * @param {perfetto.protos.JavaHeapHistogram.TypeCount} message TypeCount
                 * @param {$protobuf.IConversionOptions} [options] Conversion options
                 * @returns {Object.<string,*>} Plain object
                 */
                TypeCount.toObject = function toObject(message, options) {
                    if (!options)
                        options = {};
                    var object = {};
                    if (options.defaults) {
                        object.typeName = "";
                        object.objCount = 0;
                        object.reachableObjCount = 0;
                        object.category = "";
                    }
                    if (message.typeName != null && message.hasOwnProperty("typeName"))
                        object.typeName = message.typeName;
                    if (message.objCount != null && message.hasOwnProperty("objCount"))
                        object.objCount = message.objCount;
                    if (message.reachableObjCount != null && message.hasOwnProperty("reachableObjCount"))
                        object.reachableObjCount = message.reachableObjCount;
                    if (message.category != null && message.hasOwnProperty("category"))
                        object.category = message.category;
                    return object;
                };

                /**
                 * Converts this TypeCount to JSON.
                 * @function toJSON
                 * @memberof perfetto.protos.JavaHeapHistogram.TypeCount
                 * @instance
                 * @returns {Object.<string,*>} JSON object
                 */
                TypeCount.prototype.toJSON = function toJSON() {
                    return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
                };

                return TypeCount;
            })();

            JavaHeapHistogram.Sample = (function() {

                /**
                 * Properties of a Sample.
                 * @memberof perfetto.protos.JavaHeapHistogram
                 * @interface ISample
                 * @property {number|null} [ts] Sample ts
                 * @property {Array.<perfetto.protos.JavaHeapHistogram.ITypeCount>|null} [typeCount] Sample typeCount
                 */

                /**
                 * Constructs a new Sample.
                 * @memberof perfetto.protos.JavaHeapHistogram
                 * @classdesc Represents a Sample.
                 * @implements ISample
                 * @constructor
                 * @param {perfetto.protos.JavaHeapHistogram.ISample=} [properties] Properties to set
                 */
                function Sample(properties) {
                    this.typeCount = [];
                    if (properties)
                        for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                            if (properties[keys[i]] != null)
                                this[keys[i]] = properties[keys[i]];
                }

                /**
                 * Sample ts.
                 * @member {number} ts
                 * @memberof perfetto.protos.JavaHeapHistogram.Sample
                 * @instance
                 */
                Sample.prototype.ts = $util.Long ? $util.Long.fromBits(0,0,false) : 0;

                /**
                 * Sample typeCount.
                 * @member {Array.<perfetto.protos.JavaHeapHistogram.ITypeCount>} typeCount
                 * @memberof perfetto.protos.JavaHeapHistogram.Sample
                 * @instance
                 */
                Sample.prototype.typeCount = $util.emptyArray;

                /**
                 * Creates a new Sample instance using the specified properties.
                 * @function create
                 * @memberof perfetto.protos.JavaHeapHistogram.Sample
                 * @static
                 * @param {perfetto.protos.JavaHeapHistogram.ISample=} [properties] Properties to set
                 * @returns {perfetto.protos.JavaHeapHistogram.Sample} Sample instance
                 */
                Sample.create = function create(properties) {
                    return new Sample(properties);
                };

                /**
                 * Encodes the specified Sample message. Does not implicitly {@link perfetto.protos.JavaHeapHistogram.Sample.verify|verify} messages.
                 * @function encode
                 * @memberof perfetto.protos.JavaHeapHistogram.Sample
                 * @static
                 * @param {perfetto.protos.JavaHeapHistogram.ISample} message Sample message or plain object to encode
                 * @param {$protobuf.Writer} [writer] Writer to encode to
                 * @returns {$protobuf.Writer} Writer
                 */
                Sample.encode = function encode(message, writer) {
                    if (!writer)
                        writer = $Writer.create();
                    if (message.ts != null && Object.hasOwnProperty.call(message, "ts"))
                        writer.uint32(/* id 1, wireType 0 =*/8).int64(message.ts);
                    if (message.typeCount != null && message.typeCount.length)
                        for (var i = 0; i < message.typeCount.length; ++i)
                            $root.perfetto.protos.JavaHeapHistogram.TypeCount.encode(message.typeCount[i], writer.uint32(/* id 2, wireType 2 =*/18).fork()).ldelim();
                    return writer;
                };

                /**
                 * Encodes the specified Sample message, length delimited. Does not implicitly {@link perfetto.protos.JavaHeapHistogram.Sample.verify|verify} messages.
                 * @function encodeDelimited
                 * @memberof perfetto.protos.JavaHeapHistogram.Sample
                 * @static
                 * @param {perfetto.protos.JavaHeapHistogram.ISample} message Sample message or plain object to encode
                 * @param {$protobuf.Writer} [writer] Writer to encode to
                 * @returns {$protobuf.Writer} Writer
                 */
                Sample.encodeDelimited = function encodeDelimited(message, writer) {
                    return this.encode(message, writer).ldelim();
                };

                /**
                 * Decodes a Sample message from the specified reader or buffer.
                 * @function decode
                 * @memberof perfetto.protos.JavaHeapHistogram.Sample
                 * @static
                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                 * @param {number} [length] Message length if known beforehand
                 * @returns {perfetto.protos.JavaHeapHistogram.Sample} Sample
                 * @throws {Error} If the payload is not a reader or valid buffer
                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
                 */
                Sample.decode = function decode(reader, length) {
                    if (!(reader instanceof $Reader))
                        reader = $Reader.create(reader);
                    var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.JavaHeapHistogram.Sample();
                    while (reader.pos < end) {
                        var tag = reader.uint32();
                        switch (tag >>> 3) {
                        case 1:
                            message.ts = reader.int64();
                            break;
                        case 2:
                            if (!(message.typeCount && message.typeCount.length))
                                message.typeCount = [];
                            message.typeCount.push($root.perfetto.protos.JavaHeapHistogram.TypeCount.decode(reader, reader.uint32()));
                            break;
                        default:
                            reader.skipType(tag & 7);
                            break;
                        }
                    }
                    return message;
                };

                /**
                 * Decodes a Sample message from the specified reader or buffer, length delimited.
                 * @function decodeDelimited
                 * @memberof perfetto.protos.JavaHeapHistogram.Sample
                 * @static
                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                 * @returns {perfetto.protos.JavaHeapHistogram.Sample} Sample
                 * @throws {Error} If the payload is not a reader or valid buffer
                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
                 */
                Sample.decodeDelimited = function decodeDelimited(reader) {
                    if (!(reader instanceof $Reader))
                        reader = new $Reader(reader);
                    return this.decode(reader, reader.uint32());
                };

                /**
                 * Verifies a Sample message.
                 * @function verify
                 * @memberof perfetto.protos.JavaHeapHistogram.Sample
                 * @static
                 * @param {Object.<string,*>} message Plain object to verify
                 * @returns {string|null} `null` if valid, otherwise the reason why it is not
                 */
                Sample.verify = function verify(message) {
                    if (typeof message !== "object" || message === null)
                        return "object expected";
                    if (message.ts != null && message.hasOwnProperty("ts"))
                        if (!$util.isInteger(message.ts) && !(message.ts && $util.isInteger(message.ts.low) && $util.isInteger(message.ts.high)))
                            return "ts: integer|Long expected";
                    if (message.typeCount != null && message.hasOwnProperty("typeCount")) {
                        if (!Array.isArray(message.typeCount))
                            return "typeCount: array expected";
                        for (var i = 0; i < message.typeCount.length; ++i) {
                            var error = $root.perfetto.protos.JavaHeapHistogram.TypeCount.verify(message.typeCount[i]);
                            if (error)
                                return "typeCount." + error;
                        }
                    }
                    return null;
                };

                /**
                 * Creates a Sample message from a plain object. Also converts values to their respective internal types.
                 * @function fromObject
                 * @memberof perfetto.protos.JavaHeapHistogram.Sample
                 * @static
                 * @param {Object.<string,*>} object Plain object
                 * @returns {perfetto.protos.JavaHeapHistogram.Sample} Sample
                 */
                Sample.fromObject = function fromObject(object) {
                    if (object instanceof $root.perfetto.protos.JavaHeapHistogram.Sample)
                        return object;
                    var message = new $root.perfetto.protos.JavaHeapHistogram.Sample();
                    if (object.ts != null)
                        if ($util.Long)
                            (message.ts = $util.Long.fromValue(object.ts)).unsigned = false;
                        else if (typeof object.ts === "string")
                            message.ts = parseInt(object.ts, 10);
                        else if (typeof object.ts === "number")
                            message.ts = object.ts;
                        else if (typeof object.ts === "object")
                            message.ts = new $util.LongBits(object.ts.low >>> 0, object.ts.high >>> 0).toNumber();
                    if (object.typeCount) {
                        if (!Array.isArray(object.typeCount))
                            throw TypeError(".perfetto.protos.JavaHeapHistogram.Sample.typeCount: array expected");
                        message.typeCount = [];
                        for (var i = 0; i < object.typeCount.length; ++i) {
                            if (typeof object.typeCount[i] !== "object")
                                throw TypeError(".perfetto.protos.JavaHeapHistogram.Sample.typeCount: object expected");
                            message.typeCount[i] = $root.perfetto.protos.JavaHeapHistogram.TypeCount.fromObject(object.typeCount[i]);
                        }
                    }
                    return message;
                };

                /**
                 * Creates a plain object from a Sample message. Also converts values to other types if specified.
                 * @function toObject
                 * @memberof perfetto.protos.JavaHeapHistogram.Sample
                 * @static
                 * @param {perfetto.protos.JavaHeapHistogram.Sample} message Sample
                 * @param {$protobuf.IConversionOptions} [options] Conversion options
                 * @returns {Object.<string,*>} Plain object
                 */
                Sample.toObject = function toObject(message, options) {
                    if (!options)
                        options = {};
                    var object = {};
                    if (options.arrays || options.defaults)
                        object.typeCount = [];
                    if (options.defaults)
                        if ($util.Long) {
                            var long = new $util.Long(0, 0, false);
                            object.ts = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
                        } else
                            object.ts = options.longs === String ? "0" : 0;
                    if (message.ts != null && message.hasOwnProperty("ts"))
                        if (typeof message.ts === "number")
                            object.ts = options.longs === String ? String(message.ts) : message.ts;
                        else
                            object.ts = options.longs === String ? $util.Long.prototype.toString.call(message.ts) : options.longs === Number ? new $util.LongBits(message.ts.low >>> 0, message.ts.high >>> 0).toNumber() : message.ts;
                    if (message.typeCount && message.typeCount.length) {
                        object.typeCount = [];
                        for (var j = 0; j < message.typeCount.length; ++j)
                            object.typeCount[j] = $root.perfetto.protos.JavaHeapHistogram.TypeCount.toObject(message.typeCount[j], options);
                    }
                    return object;
                };

                /**
                 * Converts this Sample to JSON.
                 * @function toJSON
                 * @memberof perfetto.protos.JavaHeapHistogram.Sample
                 * @instance
                 * @returns {Object.<string,*>} JSON object
                 */
                Sample.prototype.toJSON = function toJSON() {
                    return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
                };

                return Sample;
            })();

            JavaHeapHistogram.InstanceStats = (function() {

                /**
                 * Properties of an InstanceStats.
                 * @memberof perfetto.protos.JavaHeapHistogram
                 * @interface IInstanceStats
                 * @property {number|null} [upid] InstanceStats upid
                 * @property {perfetto.protos.IAndroidProcessMetadata|null} [process] InstanceStats process
                 * @property {Array.<perfetto.protos.JavaHeapHistogram.ISample>|null} [samples] InstanceStats samples
                 */

                /**
                 * Constructs a new InstanceStats.
                 * @memberof perfetto.protos.JavaHeapHistogram
                 * @classdesc Represents an InstanceStats.
                 * @implements IInstanceStats
                 * @constructor
                 * @param {perfetto.protos.JavaHeapHistogram.IInstanceStats=} [properties] Properties to set
                 */
                function InstanceStats(properties) {
                    this.samples = [];
                    if (properties)
                        for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                            if (properties[keys[i]] != null)
                                this[keys[i]] = properties[keys[i]];
                }

                /**
                 * InstanceStats upid.
                 * @member {number} upid
                 * @memberof perfetto.protos.JavaHeapHistogram.InstanceStats
                 * @instance
                 */
                InstanceStats.prototype.upid = 0;

                /**
                 * InstanceStats process.
                 * @member {perfetto.protos.IAndroidProcessMetadata|null|undefined} process
                 * @memberof perfetto.protos.JavaHeapHistogram.InstanceStats
                 * @instance
                 */
                InstanceStats.prototype.process = null;

                /**
                 * InstanceStats samples.
                 * @member {Array.<perfetto.protos.JavaHeapHistogram.ISample>} samples
                 * @memberof perfetto.protos.JavaHeapHistogram.InstanceStats
                 * @instance
                 */
                InstanceStats.prototype.samples = $util.emptyArray;

                /**
                 * Creates a new InstanceStats instance using the specified properties.
                 * @function create
                 * @memberof perfetto.protos.JavaHeapHistogram.InstanceStats
                 * @static
                 * @param {perfetto.protos.JavaHeapHistogram.IInstanceStats=} [properties] Properties to set
                 * @returns {perfetto.protos.JavaHeapHistogram.InstanceStats} InstanceStats instance
                 */
                InstanceStats.create = function create(properties) {
                    return new InstanceStats(properties);
                };

                /**
                 * Encodes the specified InstanceStats message. Does not implicitly {@link perfetto.protos.JavaHeapHistogram.InstanceStats.verify|verify} messages.
                 * @function encode
                 * @memberof perfetto.protos.JavaHeapHistogram.InstanceStats
                 * @static
                 * @param {perfetto.protos.JavaHeapHistogram.IInstanceStats} message InstanceStats message or plain object to encode
                 * @param {$protobuf.Writer} [writer] Writer to encode to
                 * @returns {$protobuf.Writer} Writer
                 */
                InstanceStats.encode = function encode(message, writer) {
                    if (!writer)
                        writer = $Writer.create();
                    if (message.upid != null && Object.hasOwnProperty.call(message, "upid"))
                        writer.uint32(/* id 1, wireType 0 =*/8).uint32(message.upid);
                    if (message.process != null && Object.hasOwnProperty.call(message, "process"))
                        $root.perfetto.protos.AndroidProcessMetadata.encode(message.process, writer.uint32(/* id 2, wireType 2 =*/18).fork()).ldelim();
                    if (message.samples != null && message.samples.length)
                        for (var i = 0; i < message.samples.length; ++i)
                            $root.perfetto.protos.JavaHeapHistogram.Sample.encode(message.samples[i], writer.uint32(/* id 3, wireType 2 =*/26).fork()).ldelim();
                    return writer;
                };

                /**
                 * Encodes the specified InstanceStats message, length delimited. Does not implicitly {@link perfetto.protos.JavaHeapHistogram.InstanceStats.verify|verify} messages.
                 * @function encodeDelimited
                 * @memberof perfetto.protos.JavaHeapHistogram.InstanceStats
                 * @static
                 * @param {perfetto.protos.JavaHeapHistogram.IInstanceStats} message InstanceStats message or plain object to encode
                 * @param {$protobuf.Writer} [writer] Writer to encode to
                 * @returns {$protobuf.Writer} Writer
                 */
                InstanceStats.encodeDelimited = function encodeDelimited(message, writer) {
                    return this.encode(message, writer).ldelim();
                };

                /**
                 * Decodes an InstanceStats message from the specified reader or buffer.
                 * @function decode
                 * @memberof perfetto.protos.JavaHeapHistogram.InstanceStats
                 * @static
                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                 * @param {number} [length] Message length if known beforehand
                 * @returns {perfetto.protos.JavaHeapHistogram.InstanceStats} InstanceStats
                 * @throws {Error} If the payload is not a reader or valid buffer
                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
                 */
                InstanceStats.decode = function decode(reader, length) {
                    if (!(reader instanceof $Reader))
                        reader = $Reader.create(reader);
                    var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.JavaHeapHistogram.InstanceStats();
                    while (reader.pos < end) {
                        var tag = reader.uint32();
                        switch (tag >>> 3) {
                        case 1:
                            message.upid = reader.uint32();
                            break;
                        case 2:
                            message.process = $root.perfetto.protos.AndroidProcessMetadata.decode(reader, reader.uint32());
                            break;
                        case 3:
                            if (!(message.samples && message.samples.length))
                                message.samples = [];
                            message.samples.push($root.perfetto.protos.JavaHeapHistogram.Sample.decode(reader, reader.uint32()));
                            break;
                        default:
                            reader.skipType(tag & 7);
                            break;
                        }
                    }
                    return message;
                };

                /**
                 * Decodes an InstanceStats message from the specified reader or buffer, length delimited.
                 * @function decodeDelimited
                 * @memberof perfetto.protos.JavaHeapHistogram.InstanceStats
                 * @static
                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                 * @returns {perfetto.protos.JavaHeapHistogram.InstanceStats} InstanceStats
                 * @throws {Error} If the payload is not a reader or valid buffer
                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
                 */
                InstanceStats.decodeDelimited = function decodeDelimited(reader) {
                    if (!(reader instanceof $Reader))
                        reader = new $Reader(reader);
                    return this.decode(reader, reader.uint32());
                };

                /**
                 * Verifies an InstanceStats message.
                 * @function verify
                 * @memberof perfetto.protos.JavaHeapHistogram.InstanceStats
                 * @static
                 * @param {Object.<string,*>} message Plain object to verify
                 * @returns {string|null} `null` if valid, otherwise the reason why it is not
                 */
                InstanceStats.verify = function verify(message) {
                    if (typeof message !== "object" || message === null)
                        return "object expected";
                    if (message.upid != null && message.hasOwnProperty("upid"))
                        if (!$util.isInteger(message.upid))
                            return "upid: integer expected";
                    if (message.process != null && message.hasOwnProperty("process")) {
                        var error = $root.perfetto.protos.AndroidProcessMetadata.verify(message.process);
                        if (error)
                            return "process." + error;
                    }
                    if (message.samples != null && message.hasOwnProperty("samples")) {
                        if (!Array.isArray(message.samples))
                            return "samples: array expected";
                        for (var i = 0; i < message.samples.length; ++i) {
                            var error = $root.perfetto.protos.JavaHeapHistogram.Sample.verify(message.samples[i]);
                            if (error)
                                return "samples." + error;
                        }
                    }
                    return null;
                };

                /**
                 * Creates an InstanceStats message from a plain object. Also converts values to their respective internal types.
                 * @function fromObject
                 * @memberof perfetto.protos.JavaHeapHistogram.InstanceStats
                 * @static
                 * @param {Object.<string,*>} object Plain object
                 * @returns {perfetto.protos.JavaHeapHistogram.InstanceStats} InstanceStats
                 */
                InstanceStats.fromObject = function fromObject(object) {
                    if (object instanceof $root.perfetto.protos.JavaHeapHistogram.InstanceStats)
                        return object;
                    var message = new $root.perfetto.protos.JavaHeapHistogram.InstanceStats();
                    if (object.upid != null)
                        message.upid = object.upid >>> 0;
                    if (object.process != null) {
                        if (typeof object.process !== "object")
                            throw TypeError(".perfetto.protos.JavaHeapHistogram.InstanceStats.process: object expected");
                        message.process = $root.perfetto.protos.AndroidProcessMetadata.fromObject(object.process);
                    }
                    if (object.samples) {
                        if (!Array.isArray(object.samples))
                            throw TypeError(".perfetto.protos.JavaHeapHistogram.InstanceStats.samples: array expected");
                        message.samples = [];
                        for (var i = 0; i < object.samples.length; ++i) {
                            if (typeof object.samples[i] !== "object")
                                throw TypeError(".perfetto.protos.JavaHeapHistogram.InstanceStats.samples: object expected");
                            message.samples[i] = $root.perfetto.protos.JavaHeapHistogram.Sample.fromObject(object.samples[i]);
                        }
                    }
                    return message;
                };

                /**
                 * Creates a plain object from an InstanceStats message. Also converts values to other types if specified.
                 * @function toObject
                 * @memberof perfetto.protos.JavaHeapHistogram.InstanceStats
                 * @static
                 * @param {perfetto.protos.JavaHeapHistogram.InstanceStats} message InstanceStats
                 * @param {$protobuf.IConversionOptions} [options] Conversion options
                 * @returns {Object.<string,*>} Plain object
                 */
                InstanceStats.toObject = function toObject(message, options) {
                    if (!options)
                        options = {};
                    var object = {};
                    if (options.arrays || options.defaults)
                        object.samples = [];
                    if (options.defaults) {
                        object.upid = 0;
                        object.process = null;
                    }
                    if (message.upid != null && message.hasOwnProperty("upid"))
                        object.upid = message.upid;
                    if (message.process != null && message.hasOwnProperty("process"))
                        object.process = $root.perfetto.protos.AndroidProcessMetadata.toObject(message.process, options);
                    if (message.samples && message.samples.length) {
                        object.samples = [];
                        for (var j = 0; j < message.samples.length; ++j)
                            object.samples[j] = $root.perfetto.protos.JavaHeapHistogram.Sample.toObject(message.samples[j], options);
                    }
                    return object;
                };

                /**
                 * Converts this InstanceStats to JSON.
                 * @function toJSON
                 * @memberof perfetto.protos.JavaHeapHistogram.InstanceStats
                 * @instance
                 * @returns {Object.<string,*>} JSON object
                 */
                InstanceStats.prototype.toJSON = function toJSON() {
                    return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
                };

                return InstanceStats;
            })();

            return JavaHeapHistogram;
        })();

        protos.AndroidProcessMetadata = (function() {

            /**
             * Properties of an AndroidProcessMetadata.
             * @memberof perfetto.protos
             * @interface IAndroidProcessMetadata
             * @property {string|null} [name] AndroidProcessMetadata name
             * @property {number|null} [uid] AndroidProcessMetadata uid
             * @property {perfetto.protos.AndroidProcessMetadata.IPackage|null} ["package"] AndroidProcessMetadata package
             * @property {Array.<perfetto.protos.AndroidProcessMetadata.IPackage>|null} [packagesForUid] AndroidProcessMetadata packagesForUid
             */

            /**
             * Constructs a new AndroidProcessMetadata.
             * @memberof perfetto.protos
             * @classdesc Represents an AndroidProcessMetadata.
             * @implements IAndroidProcessMetadata
             * @constructor
             * @param {perfetto.protos.IAndroidProcessMetadata=} [properties] Properties to set
             */
            function AndroidProcessMetadata(properties) {
                this.packagesForUid = [];
                if (properties)
                    for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                        if (properties[keys[i]] != null)
                            this[keys[i]] = properties[keys[i]];
            }

            /**
             * AndroidProcessMetadata name.
             * @member {string} name
             * @memberof perfetto.protos.AndroidProcessMetadata
             * @instance
             */
            AndroidProcessMetadata.prototype.name = "";

            /**
             * AndroidProcessMetadata uid.
             * @member {number} uid
             * @memberof perfetto.protos.AndroidProcessMetadata
             * @instance
             */
            AndroidProcessMetadata.prototype.uid = $util.Long ? $util.Long.fromBits(0,0,false) : 0;

            /**
             * AndroidProcessMetadata package.
             * @member {perfetto.protos.AndroidProcessMetadata.IPackage|null|undefined} package
             * @memberof perfetto.protos.AndroidProcessMetadata
             * @instance
             */
            AndroidProcessMetadata.prototype["package"] = null;

            /**
             * AndroidProcessMetadata packagesForUid.
             * @member {Array.<perfetto.protos.AndroidProcessMetadata.IPackage>} packagesForUid
             * @memberof perfetto.protos.AndroidProcessMetadata
             * @instance
             */
            AndroidProcessMetadata.prototype.packagesForUid = $util.emptyArray;

            /**
             * Creates a new AndroidProcessMetadata instance using the specified properties.
             * @function create
             * @memberof perfetto.protos.AndroidProcessMetadata
             * @static
             * @param {perfetto.protos.IAndroidProcessMetadata=} [properties] Properties to set
             * @returns {perfetto.protos.AndroidProcessMetadata} AndroidProcessMetadata instance
             */
            AndroidProcessMetadata.create = function create(properties) {
                return new AndroidProcessMetadata(properties);
            };

            /**
             * Encodes the specified AndroidProcessMetadata message. Does not implicitly {@link perfetto.protos.AndroidProcessMetadata.verify|verify} messages.
             * @function encode
             * @memberof perfetto.protos.AndroidProcessMetadata
             * @static
             * @param {perfetto.protos.IAndroidProcessMetadata} message AndroidProcessMetadata message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            AndroidProcessMetadata.encode = function encode(message, writer) {
                if (!writer)
                    writer = $Writer.create();
                if (message.name != null && Object.hasOwnProperty.call(message, "name"))
                    writer.uint32(/* id 1, wireType 2 =*/10).string(message.name);
                if (message.uid != null && Object.hasOwnProperty.call(message, "uid"))
                    writer.uint32(/* id 2, wireType 0 =*/16).int64(message.uid);
                if (message["package"] != null && Object.hasOwnProperty.call(message, "package"))
                    $root.perfetto.protos.AndroidProcessMetadata.Package.encode(message["package"], writer.uint32(/* id 7, wireType 2 =*/58).fork()).ldelim();
                if (message.packagesForUid != null && message.packagesForUid.length)
                    for (var i = 0; i < message.packagesForUid.length; ++i)
                        $root.perfetto.protos.AndroidProcessMetadata.Package.encode(message.packagesForUid[i], writer.uint32(/* id 8, wireType 2 =*/66).fork()).ldelim();
                return writer;
            };

            /**
             * Encodes the specified AndroidProcessMetadata message, length delimited. Does not implicitly {@link perfetto.protos.AndroidProcessMetadata.verify|verify} messages.
             * @function encodeDelimited
             * @memberof perfetto.protos.AndroidProcessMetadata
             * @static
             * @param {perfetto.protos.IAndroidProcessMetadata} message AndroidProcessMetadata message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            AndroidProcessMetadata.encodeDelimited = function encodeDelimited(message, writer) {
                return this.encode(message, writer).ldelim();
            };

            /**
             * Decodes an AndroidProcessMetadata message from the specified reader or buffer.
             * @function decode
             * @memberof perfetto.protos.AndroidProcessMetadata
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @param {number} [length] Message length if known beforehand
             * @returns {perfetto.protos.AndroidProcessMetadata} AndroidProcessMetadata
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            AndroidProcessMetadata.decode = function decode(reader, length) {
                if (!(reader instanceof $Reader))
                    reader = $Reader.create(reader);
                var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.AndroidProcessMetadata();
                while (reader.pos < end) {
                    var tag = reader.uint32();
                    switch (tag >>> 3) {
                    case 1:
                        message.name = reader.string();
                        break;
                    case 2:
                        message.uid = reader.int64();
                        break;
                    case 7:
                        message["package"] = $root.perfetto.protos.AndroidProcessMetadata.Package.decode(reader, reader.uint32());
                        break;
                    case 8:
                        if (!(message.packagesForUid && message.packagesForUid.length))
                            message.packagesForUid = [];
                        message.packagesForUid.push($root.perfetto.protos.AndroidProcessMetadata.Package.decode(reader, reader.uint32()));
                        break;
                    default:
                        reader.skipType(tag & 7);
                        break;
                    }
                }
                return message;
            };

            /**
             * Decodes an AndroidProcessMetadata message from the specified reader or buffer, length delimited.
             * @function decodeDelimited
             * @memberof perfetto.protos.AndroidProcessMetadata
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @returns {perfetto.protos.AndroidProcessMetadata} AndroidProcessMetadata
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            AndroidProcessMetadata.decodeDelimited = function decodeDelimited(reader) {
                if (!(reader instanceof $Reader))
                    reader = new $Reader(reader);
                return this.decode(reader, reader.uint32());
            };

            /**
             * Verifies an AndroidProcessMetadata message.
             * @function verify
             * @memberof perfetto.protos.AndroidProcessMetadata
             * @static
             * @param {Object.<string,*>} message Plain object to verify
             * @returns {string|null} `null` if valid, otherwise the reason why it is not
             */
            AndroidProcessMetadata.verify = function verify(message) {
                if (typeof message !== "object" || message === null)
                    return "object expected";
                if (message.name != null && message.hasOwnProperty("name"))
                    if (!$util.isString(message.name))
                        return "name: string expected";
                if (message.uid != null && message.hasOwnProperty("uid"))
                    if (!$util.isInteger(message.uid) && !(message.uid && $util.isInteger(message.uid.low) && $util.isInteger(message.uid.high)))
                        return "uid: integer|Long expected";
                if (message["package"] != null && message.hasOwnProperty("package")) {
                    var error = $root.perfetto.protos.AndroidProcessMetadata.Package.verify(message["package"]);
                    if (error)
                        return "package." + error;
                }
                if (message.packagesForUid != null && message.hasOwnProperty("packagesForUid")) {
                    if (!Array.isArray(message.packagesForUid))
                        return "packagesForUid: array expected";
                    for (var i = 0; i < message.packagesForUid.length; ++i) {
                        var error = $root.perfetto.protos.AndroidProcessMetadata.Package.verify(message.packagesForUid[i]);
                        if (error)
                            return "packagesForUid." + error;
                    }
                }
                return null;
            };

            /**
             * Creates an AndroidProcessMetadata message from a plain object. Also converts values to their respective internal types.
             * @function fromObject
             * @memberof perfetto.protos.AndroidProcessMetadata
             * @static
             * @param {Object.<string,*>} object Plain object
             * @returns {perfetto.protos.AndroidProcessMetadata} AndroidProcessMetadata
             */
            AndroidProcessMetadata.fromObject = function fromObject(object) {
                if (object instanceof $root.perfetto.protos.AndroidProcessMetadata)
                    return object;
                var message = new $root.perfetto.protos.AndroidProcessMetadata();
                if (object.name != null)
                    message.name = String(object.name);
                if (object.uid != null)
                    if ($util.Long)
                        (message.uid = $util.Long.fromValue(object.uid)).unsigned = false;
                    else if (typeof object.uid === "string")
                        message.uid = parseInt(object.uid, 10);
                    else if (typeof object.uid === "number")
                        message.uid = object.uid;
                    else if (typeof object.uid === "object")
                        message.uid = new $util.LongBits(object.uid.low >>> 0, object.uid.high >>> 0).toNumber();
                if (object["package"] != null) {
                    if (typeof object["package"] !== "object")
                        throw TypeError(".perfetto.protos.AndroidProcessMetadata.package: object expected");
                    message["package"] = $root.perfetto.protos.AndroidProcessMetadata.Package.fromObject(object["package"]);
                }
                if (object.packagesForUid) {
                    if (!Array.isArray(object.packagesForUid))
                        throw TypeError(".perfetto.protos.AndroidProcessMetadata.packagesForUid: array expected");
                    message.packagesForUid = [];
                    for (var i = 0; i < object.packagesForUid.length; ++i) {
                        if (typeof object.packagesForUid[i] !== "object")
                            throw TypeError(".perfetto.protos.AndroidProcessMetadata.packagesForUid: object expected");
                        message.packagesForUid[i] = $root.perfetto.protos.AndroidProcessMetadata.Package.fromObject(object.packagesForUid[i]);
                    }
                }
                return message;
            };

            /**
             * Creates a plain object from an AndroidProcessMetadata message. Also converts values to other types if specified.
             * @function toObject
             * @memberof perfetto.protos.AndroidProcessMetadata
             * @static
             * @param {perfetto.protos.AndroidProcessMetadata} message AndroidProcessMetadata
             * @param {$protobuf.IConversionOptions} [options] Conversion options
             * @returns {Object.<string,*>} Plain object
             */
            AndroidProcessMetadata.toObject = function toObject(message, options) {
                if (!options)
                    options = {};
                var object = {};
                if (options.arrays || options.defaults)
                    object.packagesForUid = [];
                if (options.defaults) {
                    object.name = "";
                    if ($util.Long) {
                        var long = new $util.Long(0, 0, false);
                        object.uid = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
                    } else
                        object.uid = options.longs === String ? "0" : 0;
                    object["package"] = null;
                }
                if (message.name != null && message.hasOwnProperty("name"))
                    object.name = message.name;
                if (message.uid != null && message.hasOwnProperty("uid"))
                    if (typeof message.uid === "number")
                        object.uid = options.longs === String ? String(message.uid) : message.uid;
                    else
                        object.uid = options.longs === String ? $util.Long.prototype.toString.call(message.uid) : options.longs === Number ? new $util.LongBits(message.uid.low >>> 0, message.uid.high >>> 0).toNumber() : message.uid;
                if (message["package"] != null && message.hasOwnProperty("package"))
                    object["package"] = $root.perfetto.protos.AndroidProcessMetadata.Package.toObject(message["package"], options);
                if (message.packagesForUid && message.packagesForUid.length) {
                    object.packagesForUid = [];
                    for (var j = 0; j < message.packagesForUid.length; ++j)
                        object.packagesForUid[j] = $root.perfetto.protos.AndroidProcessMetadata.Package.toObject(message.packagesForUid[j], options);
                }
                return object;
            };

            /**
             * Converts this AndroidProcessMetadata to JSON.
             * @function toJSON
             * @memberof perfetto.protos.AndroidProcessMetadata
             * @instance
             * @returns {Object.<string,*>} JSON object
             */
            AndroidProcessMetadata.prototype.toJSON = function toJSON() {
                return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
            };

            AndroidProcessMetadata.Package = (function() {

                /**
                 * Properties of a Package.
                 * @memberof perfetto.protos.AndroidProcessMetadata
                 * @interface IPackage
                 * @property {string|null} [packageName] Package packageName
                 * @property {number|null} [apkVersionCode] Package apkVersionCode
                 * @property {boolean|null} [debuggable] Package debuggable
                 */

                /**
                 * Constructs a new Package.
                 * @memberof perfetto.protos.AndroidProcessMetadata
                 * @classdesc Represents a Package.
                 * @implements IPackage
                 * @constructor
                 * @param {perfetto.protos.AndroidProcessMetadata.IPackage=} [properties] Properties to set
                 */
                function Package(properties) {
                    if (properties)
                        for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                            if (properties[keys[i]] != null)
                                this[keys[i]] = properties[keys[i]];
                }

                /**
                 * Package packageName.
                 * @member {string} packageName
                 * @memberof perfetto.protos.AndroidProcessMetadata.Package
                 * @instance
                 */
                Package.prototype.packageName = "";

                /**
                 * Package apkVersionCode.
                 * @member {number} apkVersionCode
                 * @memberof perfetto.protos.AndroidProcessMetadata.Package
                 * @instance
                 */
                Package.prototype.apkVersionCode = $util.Long ? $util.Long.fromBits(0,0,false) : 0;

                /**
                 * Package debuggable.
                 * @member {boolean} debuggable
                 * @memberof perfetto.protos.AndroidProcessMetadata.Package
                 * @instance
                 */
                Package.prototype.debuggable = false;

                /**
                 * Creates a new Package instance using the specified properties.
                 * @function create
                 * @memberof perfetto.protos.AndroidProcessMetadata.Package
                 * @static
                 * @param {perfetto.protos.AndroidProcessMetadata.IPackage=} [properties] Properties to set
                 * @returns {perfetto.protos.AndroidProcessMetadata.Package} Package instance
                 */
                Package.create = function create(properties) {
                    return new Package(properties);
                };

                /**
                 * Encodes the specified Package message. Does not implicitly {@link perfetto.protos.AndroidProcessMetadata.Package.verify|verify} messages.
                 * @function encode
                 * @memberof perfetto.protos.AndroidProcessMetadata.Package
                 * @static
                 * @param {perfetto.protos.AndroidProcessMetadata.IPackage} message Package message or plain object to encode
                 * @param {$protobuf.Writer} [writer] Writer to encode to
                 * @returns {$protobuf.Writer} Writer
                 */
                Package.encode = function encode(message, writer) {
                    if (!writer)
                        writer = $Writer.create();
                    if (message.packageName != null && Object.hasOwnProperty.call(message, "packageName"))
                        writer.uint32(/* id 1, wireType 2 =*/10).string(message.packageName);
                    if (message.apkVersionCode != null && Object.hasOwnProperty.call(message, "apkVersionCode"))
                        writer.uint32(/* id 2, wireType 0 =*/16).int64(message.apkVersionCode);
                    if (message.debuggable != null && Object.hasOwnProperty.call(message, "debuggable"))
                        writer.uint32(/* id 3, wireType 0 =*/24).bool(message.debuggable);
                    return writer;
                };

                /**
                 * Encodes the specified Package message, length delimited. Does not implicitly {@link perfetto.protos.AndroidProcessMetadata.Package.verify|verify} messages.
                 * @function encodeDelimited
                 * @memberof perfetto.protos.AndroidProcessMetadata.Package
                 * @static
                 * @param {perfetto.protos.AndroidProcessMetadata.IPackage} message Package message or plain object to encode
                 * @param {$protobuf.Writer} [writer] Writer to encode to
                 * @returns {$protobuf.Writer} Writer
                 */
                Package.encodeDelimited = function encodeDelimited(message, writer) {
                    return this.encode(message, writer).ldelim();
                };

                /**
                 * Decodes a Package message from the specified reader or buffer.
                 * @function decode
                 * @memberof perfetto.protos.AndroidProcessMetadata.Package
                 * @static
                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                 * @param {number} [length] Message length if known beforehand
                 * @returns {perfetto.protos.AndroidProcessMetadata.Package} Package
                 * @throws {Error} If the payload is not a reader or valid buffer
                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
                 */
                Package.decode = function decode(reader, length) {
                    if (!(reader instanceof $Reader))
                        reader = $Reader.create(reader);
                    var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.AndroidProcessMetadata.Package();
                    while (reader.pos < end) {
                        var tag = reader.uint32();
                        switch (tag >>> 3) {
                        case 1:
                            message.packageName = reader.string();
                            break;
                        case 2:
                            message.apkVersionCode = reader.int64();
                            break;
                        case 3:
                            message.debuggable = reader.bool();
                            break;
                        default:
                            reader.skipType(tag & 7);
                            break;
                        }
                    }
                    return message;
                };

                /**
                 * Decodes a Package message from the specified reader or buffer, length delimited.
                 * @function decodeDelimited
                 * @memberof perfetto.protos.AndroidProcessMetadata.Package
                 * @static
                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                 * @returns {perfetto.protos.AndroidProcessMetadata.Package} Package
                 * @throws {Error} If the payload is not a reader or valid buffer
                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
                 */
                Package.decodeDelimited = function decodeDelimited(reader) {
                    if (!(reader instanceof $Reader))
                        reader = new $Reader(reader);
                    return this.decode(reader, reader.uint32());
                };

                /**
                 * Verifies a Package message.
                 * @function verify
                 * @memberof perfetto.protos.AndroidProcessMetadata.Package
                 * @static
                 * @param {Object.<string,*>} message Plain object to verify
                 * @returns {string|null} `null` if valid, otherwise the reason why it is not
                 */
                Package.verify = function verify(message) {
                    if (typeof message !== "object" || message === null)
                        return "object expected";
                    if (message.packageName != null && message.hasOwnProperty("packageName"))
                        if (!$util.isString(message.packageName))
                            return "packageName: string expected";
                    if (message.apkVersionCode != null && message.hasOwnProperty("apkVersionCode"))
                        if (!$util.isInteger(message.apkVersionCode) && !(message.apkVersionCode && $util.isInteger(message.apkVersionCode.low) && $util.isInteger(message.apkVersionCode.high)))
                            return "apkVersionCode: integer|Long expected";
                    if (message.debuggable != null && message.hasOwnProperty("debuggable"))
                        if (typeof message.debuggable !== "boolean")
                            return "debuggable: boolean expected";
                    return null;
                };

                /**
                 * Creates a Package message from a plain object. Also converts values to their respective internal types.
                 * @function fromObject
                 * @memberof perfetto.protos.AndroidProcessMetadata.Package
                 * @static
                 * @param {Object.<string,*>} object Plain object
                 * @returns {perfetto.protos.AndroidProcessMetadata.Package} Package
                 */
                Package.fromObject = function fromObject(object) {
                    if (object instanceof $root.perfetto.protos.AndroidProcessMetadata.Package)
                        return object;
                    var message = new $root.perfetto.protos.AndroidProcessMetadata.Package();
                    if (object.packageName != null)
                        message.packageName = String(object.packageName);
                    if (object.apkVersionCode != null)
                        if ($util.Long)
                            (message.apkVersionCode = $util.Long.fromValue(object.apkVersionCode)).unsigned = false;
                        else if (typeof object.apkVersionCode === "string")
                            message.apkVersionCode = parseInt(object.apkVersionCode, 10);
                        else if (typeof object.apkVersionCode === "number")
                            message.apkVersionCode = object.apkVersionCode;
                        else if (typeof object.apkVersionCode === "object")
                            message.apkVersionCode = new $util.LongBits(object.apkVersionCode.low >>> 0, object.apkVersionCode.high >>> 0).toNumber();
                    if (object.debuggable != null)
                        message.debuggable = Boolean(object.debuggable);
                    return message;
                };

                /**
                 * Creates a plain object from a Package message. Also converts values to other types if specified.
                 * @function toObject
                 * @memberof perfetto.protos.AndroidProcessMetadata.Package
                 * @static
                 * @param {perfetto.protos.AndroidProcessMetadata.Package} message Package
                 * @param {$protobuf.IConversionOptions} [options] Conversion options
                 * @returns {Object.<string,*>} Plain object
                 */
                Package.toObject = function toObject(message, options) {
                    if (!options)
                        options = {};
                    var object = {};
                    if (options.defaults) {
                        object.packageName = "";
                        if ($util.Long) {
                            var long = new $util.Long(0, 0, false);
                            object.apkVersionCode = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
                        } else
                            object.apkVersionCode = options.longs === String ? "0" : 0;
                        object.debuggable = false;
                    }
                    if (message.packageName != null && message.hasOwnProperty("packageName"))
                        object.packageName = message.packageName;
                    if (message.apkVersionCode != null && message.hasOwnProperty("apkVersionCode"))
                        if (typeof message.apkVersionCode === "number")
                            object.apkVersionCode = options.longs === String ? String(message.apkVersionCode) : message.apkVersionCode;
                        else
                            object.apkVersionCode = options.longs === String ? $util.Long.prototype.toString.call(message.apkVersionCode) : options.longs === Number ? new $util.LongBits(message.apkVersionCode.low >>> 0, message.apkVersionCode.high >>> 0).toNumber() : message.apkVersionCode;
                    if (message.debuggable != null && message.hasOwnProperty("debuggable"))
                        object.debuggable = message.debuggable;
                    return object;
                };

                /**
                 * Converts this Package to JSON.
                 * @function toJSON
                 * @memberof perfetto.protos.AndroidProcessMetadata.Package
                 * @instance
                 * @returns {Object.<string,*>} JSON object
                 */
                Package.prototype.toJSON = function toJSON() {
                    return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
                };

                return Package;
            })();

            return AndroidProcessMetadata;
        })();

        protos.JavaHeapStats = (function() {

            /**
             * Properties of a JavaHeapStats.
             * @memberof perfetto.protos
             * @interface IJavaHeapStats
             * @property {Array.<perfetto.protos.JavaHeapStats.IInstanceStats>|null} [instanceStats] JavaHeapStats instanceStats
             */

            /**
             * Constructs a new JavaHeapStats.
             * @memberof perfetto.protos
             * @classdesc Represents a JavaHeapStats.
             * @implements IJavaHeapStats
             * @constructor
             * @param {perfetto.protos.IJavaHeapStats=} [properties] Properties to set
             */
            function JavaHeapStats(properties) {
                this.instanceStats = [];
                if (properties)
                    for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                        if (properties[keys[i]] != null)
                            this[keys[i]] = properties[keys[i]];
            }

            /**
             * JavaHeapStats instanceStats.
             * @member {Array.<perfetto.protos.JavaHeapStats.IInstanceStats>} instanceStats
             * @memberof perfetto.protos.JavaHeapStats
             * @instance
             */
            JavaHeapStats.prototype.instanceStats = $util.emptyArray;

            /**
             * Creates a new JavaHeapStats instance using the specified properties.
             * @function create
             * @memberof perfetto.protos.JavaHeapStats
             * @static
             * @param {perfetto.protos.IJavaHeapStats=} [properties] Properties to set
             * @returns {perfetto.protos.JavaHeapStats} JavaHeapStats instance
             */
            JavaHeapStats.create = function create(properties) {
                return new JavaHeapStats(properties);
            };

            /**
             * Encodes the specified JavaHeapStats message. Does not implicitly {@link perfetto.protos.JavaHeapStats.verify|verify} messages.
             * @function encode
             * @memberof perfetto.protos.JavaHeapStats
             * @static
             * @param {perfetto.protos.IJavaHeapStats} message JavaHeapStats message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            JavaHeapStats.encode = function encode(message, writer) {
                if (!writer)
                    writer = $Writer.create();
                if (message.instanceStats != null && message.instanceStats.length)
                    for (var i = 0; i < message.instanceStats.length; ++i)
                        $root.perfetto.protos.JavaHeapStats.InstanceStats.encode(message.instanceStats[i], writer.uint32(/* id 1, wireType 2 =*/10).fork()).ldelim();
                return writer;
            };

            /**
             * Encodes the specified JavaHeapStats message, length delimited. Does not implicitly {@link perfetto.protos.JavaHeapStats.verify|verify} messages.
             * @function encodeDelimited
             * @memberof perfetto.protos.JavaHeapStats
             * @static
             * @param {perfetto.protos.IJavaHeapStats} message JavaHeapStats message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            JavaHeapStats.encodeDelimited = function encodeDelimited(message, writer) {
                return this.encode(message, writer).ldelim();
            };

            /**
             * Decodes a JavaHeapStats message from the specified reader or buffer.
             * @function decode
             * @memberof perfetto.protos.JavaHeapStats
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @param {number} [length] Message length if known beforehand
             * @returns {perfetto.protos.JavaHeapStats} JavaHeapStats
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            JavaHeapStats.decode = function decode(reader, length) {
                if (!(reader instanceof $Reader))
                    reader = $Reader.create(reader);
                var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.JavaHeapStats();
                while (reader.pos < end) {
                    var tag = reader.uint32();
                    switch (tag >>> 3) {
                    case 1:
                        if (!(message.instanceStats && message.instanceStats.length))
                            message.instanceStats = [];
                        message.instanceStats.push($root.perfetto.protos.JavaHeapStats.InstanceStats.decode(reader, reader.uint32()));
                        break;
                    default:
                        reader.skipType(tag & 7);
                        break;
                    }
                }
                return message;
            };

            /**
             * Decodes a JavaHeapStats message from the specified reader or buffer, length delimited.
             * @function decodeDelimited
             * @memberof perfetto.protos.JavaHeapStats
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @returns {perfetto.protos.JavaHeapStats} JavaHeapStats
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            JavaHeapStats.decodeDelimited = function decodeDelimited(reader) {
                if (!(reader instanceof $Reader))
                    reader = new $Reader(reader);
                return this.decode(reader, reader.uint32());
            };

            /**
             * Verifies a JavaHeapStats message.
             * @function verify
             * @memberof perfetto.protos.JavaHeapStats
             * @static
             * @param {Object.<string,*>} message Plain object to verify
             * @returns {string|null} `null` if valid, otherwise the reason why it is not
             */
            JavaHeapStats.verify = function verify(message) {
                if (typeof message !== "object" || message === null)
                    return "object expected";
                if (message.instanceStats != null && message.hasOwnProperty("instanceStats")) {
                    if (!Array.isArray(message.instanceStats))
                        return "instanceStats: array expected";
                    for (var i = 0; i < message.instanceStats.length; ++i) {
                        var error = $root.perfetto.protos.JavaHeapStats.InstanceStats.verify(message.instanceStats[i]);
                        if (error)
                            return "instanceStats." + error;
                    }
                }
                return null;
            };

            /**
             * Creates a JavaHeapStats message from a plain object. Also converts values to their respective internal types.
             * @function fromObject
             * @memberof perfetto.protos.JavaHeapStats
             * @static
             * @param {Object.<string,*>} object Plain object
             * @returns {perfetto.protos.JavaHeapStats} JavaHeapStats
             */
            JavaHeapStats.fromObject = function fromObject(object) {
                if (object instanceof $root.perfetto.protos.JavaHeapStats)
                    return object;
                var message = new $root.perfetto.protos.JavaHeapStats();
                if (object.instanceStats) {
                    if (!Array.isArray(object.instanceStats))
                        throw TypeError(".perfetto.protos.JavaHeapStats.instanceStats: array expected");
                    message.instanceStats = [];
                    for (var i = 0; i < object.instanceStats.length; ++i) {
                        if (typeof object.instanceStats[i] !== "object")
                            throw TypeError(".perfetto.protos.JavaHeapStats.instanceStats: object expected");
                        message.instanceStats[i] = $root.perfetto.protos.JavaHeapStats.InstanceStats.fromObject(object.instanceStats[i]);
                    }
                }
                return message;
            };

            /**
             * Creates a plain object from a JavaHeapStats message. Also converts values to other types if specified.
             * @function toObject
             * @memberof perfetto.protos.JavaHeapStats
             * @static
             * @param {perfetto.protos.JavaHeapStats} message JavaHeapStats
             * @param {$protobuf.IConversionOptions} [options] Conversion options
             * @returns {Object.<string,*>} Plain object
             */
            JavaHeapStats.toObject = function toObject(message, options) {
                if (!options)
                    options = {};
                var object = {};
                if (options.arrays || options.defaults)
                    object.instanceStats = [];
                if (message.instanceStats && message.instanceStats.length) {
                    object.instanceStats = [];
                    for (var j = 0; j < message.instanceStats.length; ++j)
                        object.instanceStats[j] = $root.perfetto.protos.JavaHeapStats.InstanceStats.toObject(message.instanceStats[j], options);
                }
                return object;
            };

            /**
             * Converts this JavaHeapStats to JSON.
             * @function toJSON
             * @memberof perfetto.protos.JavaHeapStats
             * @instance
             * @returns {Object.<string,*>} JSON object
             */
            JavaHeapStats.prototype.toJSON = function toJSON() {
                return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
            };

            JavaHeapStats.HeapRoots = (function() {

                /**
                 * Properties of a HeapRoots.
                 * @memberof perfetto.protos.JavaHeapStats
                 * @interface IHeapRoots
                 * @property {string|null} [rootType] HeapRoots rootType
                 * @property {string|null} [typeName] HeapRoots typeName
                 * @property {number|null} [objCount] HeapRoots objCount
                 */

                /**
                 * Constructs a new HeapRoots.
                 * @memberof perfetto.protos.JavaHeapStats
                 * @classdesc Represents a HeapRoots.
                 * @implements IHeapRoots
                 * @constructor
                 * @param {perfetto.protos.JavaHeapStats.IHeapRoots=} [properties] Properties to set
                 */
                function HeapRoots(properties) {
                    if (properties)
                        for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                            if (properties[keys[i]] != null)
                                this[keys[i]] = properties[keys[i]];
                }

                /**
                 * HeapRoots rootType.
                 * @member {string} rootType
                 * @memberof perfetto.protos.JavaHeapStats.HeapRoots
                 * @instance
                 */
                HeapRoots.prototype.rootType = "";

                /**
                 * HeapRoots typeName.
                 * @member {string} typeName
                 * @memberof perfetto.protos.JavaHeapStats.HeapRoots
                 * @instance
                 */
                HeapRoots.prototype.typeName = "";

                /**
                 * HeapRoots objCount.
                 * @member {number} objCount
                 * @memberof perfetto.protos.JavaHeapStats.HeapRoots
                 * @instance
                 */
                HeapRoots.prototype.objCount = $util.Long ? $util.Long.fromBits(0,0,false) : 0;

                /**
                 * Creates a new HeapRoots instance using the specified properties.
                 * @function create
                 * @memberof perfetto.protos.JavaHeapStats.HeapRoots
                 * @static
                 * @param {perfetto.protos.JavaHeapStats.IHeapRoots=} [properties] Properties to set
                 * @returns {perfetto.protos.JavaHeapStats.HeapRoots} HeapRoots instance
                 */
                HeapRoots.create = function create(properties) {
                    return new HeapRoots(properties);
                };

                /**
                 * Encodes the specified HeapRoots message. Does not implicitly {@link perfetto.protos.JavaHeapStats.HeapRoots.verify|verify} messages.
                 * @function encode
                 * @memberof perfetto.protos.JavaHeapStats.HeapRoots
                 * @static
                 * @param {perfetto.protos.JavaHeapStats.IHeapRoots} message HeapRoots message or plain object to encode
                 * @param {$protobuf.Writer} [writer] Writer to encode to
                 * @returns {$protobuf.Writer} Writer
                 */
                HeapRoots.encode = function encode(message, writer) {
                    if (!writer)
                        writer = $Writer.create();
                    if (message.rootType != null && Object.hasOwnProperty.call(message, "rootType"))
                        writer.uint32(/* id 1, wireType 2 =*/10).string(message.rootType);
                    if (message.typeName != null && Object.hasOwnProperty.call(message, "typeName"))
                        writer.uint32(/* id 2, wireType 2 =*/18).string(message.typeName);
                    if (message.objCount != null && Object.hasOwnProperty.call(message, "objCount"))
                        writer.uint32(/* id 3, wireType 0 =*/24).int64(message.objCount);
                    return writer;
                };

                /**
                 * Encodes the specified HeapRoots message, length delimited. Does not implicitly {@link perfetto.protos.JavaHeapStats.HeapRoots.verify|verify} messages.
                 * @function encodeDelimited
                 * @memberof perfetto.protos.JavaHeapStats.HeapRoots
                 * @static
                 * @param {perfetto.protos.JavaHeapStats.IHeapRoots} message HeapRoots message or plain object to encode
                 * @param {$protobuf.Writer} [writer] Writer to encode to
                 * @returns {$protobuf.Writer} Writer
                 */
                HeapRoots.encodeDelimited = function encodeDelimited(message, writer) {
                    return this.encode(message, writer).ldelim();
                };

                /**
                 * Decodes a HeapRoots message from the specified reader or buffer.
                 * @function decode
                 * @memberof perfetto.protos.JavaHeapStats.HeapRoots
                 * @static
                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                 * @param {number} [length] Message length if known beforehand
                 * @returns {perfetto.protos.JavaHeapStats.HeapRoots} HeapRoots
                 * @throws {Error} If the payload is not a reader or valid buffer
                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
                 */
                HeapRoots.decode = function decode(reader, length) {
                    if (!(reader instanceof $Reader))
                        reader = $Reader.create(reader);
                    var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.JavaHeapStats.HeapRoots();
                    while (reader.pos < end) {
                        var tag = reader.uint32();
                        switch (tag >>> 3) {
                        case 1:
                            message.rootType = reader.string();
                            break;
                        case 2:
                            message.typeName = reader.string();
                            break;
                        case 3:
                            message.objCount = reader.int64();
                            break;
                        default:
                            reader.skipType(tag & 7);
                            break;
                        }
                    }
                    return message;
                };

                /**
                 * Decodes a HeapRoots message from the specified reader or buffer, length delimited.
                 * @function decodeDelimited
                 * @memberof perfetto.protos.JavaHeapStats.HeapRoots
                 * @static
                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                 * @returns {perfetto.protos.JavaHeapStats.HeapRoots} HeapRoots
                 * @throws {Error} If the payload is not a reader or valid buffer
                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
                 */
                HeapRoots.decodeDelimited = function decodeDelimited(reader) {
                    if (!(reader instanceof $Reader))
                        reader = new $Reader(reader);
                    return this.decode(reader, reader.uint32());
                };

                /**
                 * Verifies a HeapRoots message.
                 * @function verify
                 * @memberof perfetto.protos.JavaHeapStats.HeapRoots
                 * @static
                 * @param {Object.<string,*>} message Plain object to verify
                 * @returns {string|null} `null` if valid, otherwise the reason why it is not
                 */
                HeapRoots.verify = function verify(message) {
                    if (typeof message !== "object" || message === null)
                        return "object expected";
                    if (message.rootType != null && message.hasOwnProperty("rootType"))
                        if (!$util.isString(message.rootType))
                            return "rootType: string expected";
                    if (message.typeName != null && message.hasOwnProperty("typeName"))
                        if (!$util.isString(message.typeName))
                            return "typeName: string expected";
                    if (message.objCount != null && message.hasOwnProperty("objCount"))
                        if (!$util.isInteger(message.objCount) && !(message.objCount && $util.isInteger(message.objCount.low) && $util.isInteger(message.objCount.high)))
                            return "objCount: integer|Long expected";
                    return null;
                };

                /**
                 * Creates a HeapRoots message from a plain object. Also converts values to their respective internal types.
                 * @function fromObject
                 * @memberof perfetto.protos.JavaHeapStats.HeapRoots
                 * @static
                 * @param {Object.<string,*>} object Plain object
                 * @returns {perfetto.protos.JavaHeapStats.HeapRoots} HeapRoots
                 */
                HeapRoots.fromObject = function fromObject(object) {
                    if (object instanceof $root.perfetto.protos.JavaHeapStats.HeapRoots)
                        return object;
                    var message = new $root.perfetto.protos.JavaHeapStats.HeapRoots();
                    if (object.rootType != null)
                        message.rootType = String(object.rootType);
                    if (object.typeName != null)
                        message.typeName = String(object.typeName);
                    if (object.objCount != null)
                        if ($util.Long)
                            (message.objCount = $util.Long.fromValue(object.objCount)).unsigned = false;
                        else if (typeof object.objCount === "string")
                            message.objCount = parseInt(object.objCount, 10);
                        else if (typeof object.objCount === "number")
                            message.objCount = object.objCount;
                        else if (typeof object.objCount === "object")
                            message.objCount = new $util.LongBits(object.objCount.low >>> 0, object.objCount.high >>> 0).toNumber();
                    return message;
                };

                /**
                 * Creates a plain object from a HeapRoots message. Also converts values to other types if specified.
                 * @function toObject
                 * @memberof perfetto.protos.JavaHeapStats.HeapRoots
                 * @static
                 * @param {perfetto.protos.JavaHeapStats.HeapRoots} message HeapRoots
                 * @param {$protobuf.IConversionOptions} [options] Conversion options
                 * @returns {Object.<string,*>} Plain object
                 */
                HeapRoots.toObject = function toObject(message, options) {
                    if (!options)
                        options = {};
                    var object = {};
                    if (options.defaults) {
                        object.rootType = "";
                        object.typeName = "";
                        if ($util.Long) {
                            var long = new $util.Long(0, 0, false);
                            object.objCount = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
                        } else
                            object.objCount = options.longs === String ? "0" : 0;
                    }
                    if (message.rootType != null && message.hasOwnProperty("rootType"))
                        object.rootType = message.rootType;
                    if (message.typeName != null && message.hasOwnProperty("typeName"))
                        object.typeName = message.typeName;
                    if (message.objCount != null && message.hasOwnProperty("objCount"))
                        if (typeof message.objCount === "number")
                            object.objCount = options.longs === String ? String(message.objCount) : message.objCount;
                        else
                            object.objCount = options.longs === String ? $util.Long.prototype.toString.call(message.objCount) : options.longs === Number ? new $util.LongBits(message.objCount.low >>> 0, message.objCount.high >>> 0).toNumber() : message.objCount;
                    return object;
                };

                /**
                 * Converts this HeapRoots to JSON.
                 * @function toJSON
                 * @memberof perfetto.protos.JavaHeapStats.HeapRoots
                 * @instance
                 * @returns {Object.<string,*>} JSON object
                 */
                HeapRoots.prototype.toJSON = function toJSON() {
                    return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
                };

                return HeapRoots;
            })();

            JavaHeapStats.Sample = (function() {

                /**
                 * Properties of a Sample.
                 * @memberof perfetto.protos.JavaHeapStats
                 * @interface ISample
                 * @property {number|null} [ts] Sample ts
                 * @property {number|null} [heapSize] Sample heapSize
                 * @property {number|null} [objCount] Sample objCount
                 * @property {number|null} [reachableHeapSize] Sample reachableHeapSize
                 * @property {number|null} [reachableObjCount] Sample reachableObjCount
                 * @property {number|null} [anonRssAndSwapSize] Sample anonRssAndSwapSize
                 * @property {Array.<perfetto.protos.JavaHeapStats.IHeapRoots>|null} [roots] Sample roots
                 */

                /**
                 * Constructs a new Sample.
                 * @memberof perfetto.protos.JavaHeapStats
                 * @classdesc Represents a Sample.
                 * @implements ISample
                 * @constructor
                 * @param {perfetto.protos.JavaHeapStats.ISample=} [properties] Properties to set
                 */
                function Sample(properties) {
                    this.roots = [];
                    if (properties)
                        for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                            if (properties[keys[i]] != null)
                                this[keys[i]] = properties[keys[i]];
                }

                /**
                 * Sample ts.
                 * @member {number} ts
                 * @memberof perfetto.protos.JavaHeapStats.Sample
                 * @instance
                 */
                Sample.prototype.ts = $util.Long ? $util.Long.fromBits(0,0,false) : 0;

                /**
                 * Sample heapSize.
                 * @member {number} heapSize
                 * @memberof perfetto.protos.JavaHeapStats.Sample
                 * @instance
                 */
                Sample.prototype.heapSize = $util.Long ? $util.Long.fromBits(0,0,false) : 0;

                /**
                 * Sample objCount.
                 * @member {number} objCount
                 * @memberof perfetto.protos.JavaHeapStats.Sample
                 * @instance
                 */
                Sample.prototype.objCount = $util.Long ? $util.Long.fromBits(0,0,false) : 0;

                /**
                 * Sample reachableHeapSize.
                 * @member {number} reachableHeapSize
                 * @memberof perfetto.protos.JavaHeapStats.Sample
                 * @instance
                 */
                Sample.prototype.reachableHeapSize = $util.Long ? $util.Long.fromBits(0,0,false) : 0;

                /**
                 * Sample reachableObjCount.
                 * @member {number} reachableObjCount
                 * @memberof perfetto.protos.JavaHeapStats.Sample
                 * @instance
                 */
                Sample.prototype.reachableObjCount = $util.Long ? $util.Long.fromBits(0,0,false) : 0;

                /**
                 * Sample anonRssAndSwapSize.
                 * @member {number} anonRssAndSwapSize
                 * @memberof perfetto.protos.JavaHeapStats.Sample
                 * @instance
                 */
                Sample.prototype.anonRssAndSwapSize = $util.Long ? $util.Long.fromBits(0,0,false) : 0;

                /**
                 * Sample roots.
                 * @member {Array.<perfetto.protos.JavaHeapStats.IHeapRoots>} roots
                 * @memberof perfetto.protos.JavaHeapStats.Sample
                 * @instance
                 */
                Sample.prototype.roots = $util.emptyArray;

                /**
                 * Creates a new Sample instance using the specified properties.
                 * @function create
                 * @memberof perfetto.protos.JavaHeapStats.Sample
                 * @static
                 * @param {perfetto.protos.JavaHeapStats.ISample=} [properties] Properties to set
                 * @returns {perfetto.protos.JavaHeapStats.Sample} Sample instance
                 */
                Sample.create = function create(properties) {
                    return new Sample(properties);
                };

                /**
                 * Encodes the specified Sample message. Does not implicitly {@link perfetto.protos.JavaHeapStats.Sample.verify|verify} messages.
                 * @function encode
                 * @memberof perfetto.protos.JavaHeapStats.Sample
                 * @static
                 * @param {perfetto.protos.JavaHeapStats.ISample} message Sample message or plain object to encode
                 * @param {$protobuf.Writer} [writer] Writer to encode to
                 * @returns {$protobuf.Writer} Writer
                 */
                Sample.encode = function encode(message, writer) {
                    if (!writer)
                        writer = $Writer.create();
                    if (message.ts != null && Object.hasOwnProperty.call(message, "ts"))
                        writer.uint32(/* id 1, wireType 0 =*/8).int64(message.ts);
                    if (message.heapSize != null && Object.hasOwnProperty.call(message, "heapSize"))
                        writer.uint32(/* id 2, wireType 0 =*/16).int64(message.heapSize);
                    if (message.reachableHeapSize != null && Object.hasOwnProperty.call(message, "reachableHeapSize"))
                        writer.uint32(/* id 3, wireType 0 =*/24).int64(message.reachableHeapSize);
                    if (message.objCount != null && Object.hasOwnProperty.call(message, "objCount"))
                        writer.uint32(/* id 4, wireType 0 =*/32).int64(message.objCount);
                    if (message.reachableObjCount != null && Object.hasOwnProperty.call(message, "reachableObjCount"))
                        writer.uint32(/* id 5, wireType 0 =*/40).int64(message.reachableObjCount);
                    if (message.anonRssAndSwapSize != null && Object.hasOwnProperty.call(message, "anonRssAndSwapSize"))
                        writer.uint32(/* id 6, wireType 0 =*/48).int64(message.anonRssAndSwapSize);
                    if (message.roots != null && message.roots.length)
                        for (var i = 0; i < message.roots.length; ++i)
                            $root.perfetto.protos.JavaHeapStats.HeapRoots.encode(message.roots[i], writer.uint32(/* id 7, wireType 2 =*/58).fork()).ldelim();
                    return writer;
                };

                /**
                 * Encodes the specified Sample message, length delimited. Does not implicitly {@link perfetto.protos.JavaHeapStats.Sample.verify|verify} messages.
                 * @function encodeDelimited
                 * @memberof perfetto.protos.JavaHeapStats.Sample
                 * @static
                 * @param {perfetto.protos.JavaHeapStats.ISample} message Sample message or plain object to encode
                 * @param {$protobuf.Writer} [writer] Writer to encode to
                 * @returns {$protobuf.Writer} Writer
                 */
                Sample.encodeDelimited = function encodeDelimited(message, writer) {
                    return this.encode(message, writer).ldelim();
                };

                /**
                 * Decodes a Sample message from the specified reader or buffer.
                 * @function decode
                 * @memberof perfetto.protos.JavaHeapStats.Sample
                 * @static
                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                 * @param {number} [length] Message length if known beforehand
                 * @returns {perfetto.protos.JavaHeapStats.Sample} Sample
                 * @throws {Error} If the payload is not a reader or valid buffer
                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
                 */
                Sample.decode = function decode(reader, length) {
                    if (!(reader instanceof $Reader))
                        reader = $Reader.create(reader);
                    var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.JavaHeapStats.Sample();
                    while (reader.pos < end) {
                        var tag = reader.uint32();
                        switch (tag >>> 3) {
                        case 1:
                            message.ts = reader.int64();
                            break;
                        case 2:
                            message.heapSize = reader.int64();
                            break;
                        case 4:
                            message.objCount = reader.int64();
                            break;
                        case 3:
                            message.reachableHeapSize = reader.int64();
                            break;
                        case 5:
                            message.reachableObjCount = reader.int64();
                            break;
                        case 6:
                            message.anonRssAndSwapSize = reader.int64();
                            break;
                        case 7:
                            if (!(message.roots && message.roots.length))
                                message.roots = [];
                            message.roots.push($root.perfetto.protos.JavaHeapStats.HeapRoots.decode(reader, reader.uint32()));
                            break;
                        default:
                            reader.skipType(tag & 7);
                            break;
                        }
                    }
                    return message;
                };

                /**
                 * Decodes a Sample message from the specified reader or buffer, length delimited.
                 * @function decodeDelimited
                 * @memberof perfetto.protos.JavaHeapStats.Sample
                 * @static
                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                 * @returns {perfetto.protos.JavaHeapStats.Sample} Sample
                 * @throws {Error} If the payload is not a reader or valid buffer
                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
                 */
                Sample.decodeDelimited = function decodeDelimited(reader) {
                    if (!(reader instanceof $Reader))
                        reader = new $Reader(reader);
                    return this.decode(reader, reader.uint32());
                };

                /**
                 * Verifies a Sample message.
                 * @function verify
                 * @memberof perfetto.protos.JavaHeapStats.Sample
                 * @static
                 * @param {Object.<string,*>} message Plain object to verify
                 * @returns {string|null} `null` if valid, otherwise the reason why it is not
                 */
                Sample.verify = function verify(message) {
                    if (typeof message !== "object" || message === null)
                        return "object expected";
                    if (message.ts != null && message.hasOwnProperty("ts"))
                        if (!$util.isInteger(message.ts) && !(message.ts && $util.isInteger(message.ts.low) && $util.isInteger(message.ts.high)))
                            return "ts: integer|Long expected";
                    if (message.heapSize != null && message.hasOwnProperty("heapSize"))
                        if (!$util.isInteger(message.heapSize) && !(message.heapSize && $util.isInteger(message.heapSize.low) && $util.isInteger(message.heapSize.high)))
                            return "heapSize: integer|Long expected";
                    if (message.objCount != null && message.hasOwnProperty("objCount"))
                        if (!$util.isInteger(message.objCount) && !(message.objCount && $util.isInteger(message.objCount.low) && $util.isInteger(message.objCount.high)))
                            return "objCount: integer|Long expected";
                    if (message.reachableHeapSize != null && message.hasOwnProperty("reachableHeapSize"))
                        if (!$util.isInteger(message.reachableHeapSize) && !(message.reachableHeapSize && $util.isInteger(message.reachableHeapSize.low) && $util.isInteger(message.reachableHeapSize.high)))
                            return "reachableHeapSize: integer|Long expected";
                    if (message.reachableObjCount != null && message.hasOwnProperty("reachableObjCount"))
                        if (!$util.isInteger(message.reachableObjCount) && !(message.reachableObjCount && $util.isInteger(message.reachableObjCount.low) && $util.isInteger(message.reachableObjCount.high)))
                            return "reachableObjCount: integer|Long expected";
                    if (message.anonRssAndSwapSize != null && message.hasOwnProperty("anonRssAndSwapSize"))
                        if (!$util.isInteger(message.anonRssAndSwapSize) && !(message.anonRssAndSwapSize && $util.isInteger(message.anonRssAndSwapSize.low) && $util.isInteger(message.anonRssAndSwapSize.high)))
                            return "anonRssAndSwapSize: integer|Long expected";
                    if (message.roots != null && message.hasOwnProperty("roots")) {
                        if (!Array.isArray(message.roots))
                            return "roots: array expected";
                        for (var i = 0; i < message.roots.length; ++i) {
                            var error = $root.perfetto.protos.JavaHeapStats.HeapRoots.verify(message.roots[i]);
                            if (error)
                                return "roots." + error;
                        }
                    }
                    return null;
                };

                /**
                 * Creates a Sample message from a plain object. Also converts values to their respective internal types.
                 * @function fromObject
                 * @memberof perfetto.protos.JavaHeapStats.Sample
                 * @static
                 * @param {Object.<string,*>} object Plain object
                 * @returns {perfetto.protos.JavaHeapStats.Sample} Sample
                 */
                Sample.fromObject = function fromObject(object) {
                    if (object instanceof $root.perfetto.protos.JavaHeapStats.Sample)
                        return object;
                    var message = new $root.perfetto.protos.JavaHeapStats.Sample();
                    if (object.ts != null)
                        if ($util.Long)
                            (message.ts = $util.Long.fromValue(object.ts)).unsigned = false;
                        else if (typeof object.ts === "string")
                            message.ts = parseInt(object.ts, 10);
                        else if (typeof object.ts === "number")
                            message.ts = object.ts;
                        else if (typeof object.ts === "object")
                            message.ts = new $util.LongBits(object.ts.low >>> 0, object.ts.high >>> 0).toNumber();
                    if (object.heapSize != null)
                        if ($util.Long)
                            (message.heapSize = $util.Long.fromValue(object.heapSize)).unsigned = false;
                        else if (typeof object.heapSize === "string")
                            message.heapSize = parseInt(object.heapSize, 10);
                        else if (typeof object.heapSize === "number")
                            message.heapSize = object.heapSize;
                        else if (typeof object.heapSize === "object")
                            message.heapSize = new $util.LongBits(object.heapSize.low >>> 0, object.heapSize.high >>> 0).toNumber();
                    if (object.objCount != null)
                        if ($util.Long)
                            (message.objCount = $util.Long.fromValue(object.objCount)).unsigned = false;
                        else if (typeof object.objCount === "string")
                            message.objCount = parseInt(object.objCount, 10);
                        else if (typeof object.objCount === "number")
                            message.objCount = object.objCount;
                        else if (typeof object.objCount === "object")
                            message.objCount = new $util.LongBits(object.objCount.low >>> 0, object.objCount.high >>> 0).toNumber();
                    if (object.reachableHeapSize != null)
                        if ($util.Long)
                            (message.reachableHeapSize = $util.Long.fromValue(object.reachableHeapSize)).unsigned = false;
                        else if (typeof object.reachableHeapSize === "string")
                            message.reachableHeapSize = parseInt(object.reachableHeapSize, 10);
                        else if (typeof object.reachableHeapSize === "number")
                            message.reachableHeapSize = object.reachableHeapSize;
                        else if (typeof object.reachableHeapSize === "object")
                            message.reachableHeapSize = new $util.LongBits(object.reachableHeapSize.low >>> 0, object.reachableHeapSize.high >>> 0).toNumber();
                    if (object.reachableObjCount != null)
                        if ($util.Long)
                            (message.reachableObjCount = $util.Long.fromValue(object.reachableObjCount)).unsigned = false;
                        else if (typeof object.reachableObjCount === "string")
                            message.reachableObjCount = parseInt(object.reachableObjCount, 10);
                        else if (typeof object.reachableObjCount === "number")
                            message.reachableObjCount = object.reachableObjCount;
                        else if (typeof object.reachableObjCount === "object")
                            message.reachableObjCount = new $util.LongBits(object.reachableObjCount.low >>> 0, object.reachableObjCount.high >>> 0).toNumber();
                    if (object.anonRssAndSwapSize != null)
                        if ($util.Long)
                            (message.anonRssAndSwapSize = $util.Long.fromValue(object.anonRssAndSwapSize)).unsigned = false;
                        else if (typeof object.anonRssAndSwapSize === "string")
                            message.anonRssAndSwapSize = parseInt(object.anonRssAndSwapSize, 10);
                        else if (typeof object.anonRssAndSwapSize === "number")
                            message.anonRssAndSwapSize = object.anonRssAndSwapSize;
                        else if (typeof object.anonRssAndSwapSize === "object")
                            message.anonRssAndSwapSize = new $util.LongBits(object.anonRssAndSwapSize.low >>> 0, object.anonRssAndSwapSize.high >>> 0).toNumber();
                    if (object.roots) {
                        if (!Array.isArray(object.roots))
                            throw TypeError(".perfetto.protos.JavaHeapStats.Sample.roots: array expected");
                        message.roots = [];
                        for (var i = 0; i < object.roots.length; ++i) {
                            if (typeof object.roots[i] !== "object")
                                throw TypeError(".perfetto.protos.JavaHeapStats.Sample.roots: object expected");
                            message.roots[i] = $root.perfetto.protos.JavaHeapStats.HeapRoots.fromObject(object.roots[i]);
                        }
                    }
                    return message;
                };

                /**
                 * Creates a plain object from a Sample message. Also converts values to other types if specified.
                 * @function toObject
                 * @memberof perfetto.protos.JavaHeapStats.Sample
                 * @static
                 * @param {perfetto.protos.JavaHeapStats.Sample} message Sample
                 * @param {$protobuf.IConversionOptions} [options] Conversion options
                 * @returns {Object.<string,*>} Plain object
                 */
                Sample.toObject = function toObject(message, options) {
                    if (!options)
                        options = {};
                    var object = {};
                    if (options.arrays || options.defaults)
                        object.roots = [];
                    if (options.defaults) {
                        if ($util.Long) {
                            var long = new $util.Long(0, 0, false);
                            object.ts = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
                        } else
                            object.ts = options.longs === String ? "0" : 0;
                        if ($util.Long) {
                            var long = new $util.Long(0, 0, false);
                            object.heapSize = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
                        } else
                            object.heapSize = options.longs === String ? "0" : 0;
                        if ($util.Long) {
                            var long = new $util.Long(0, 0, false);
                            object.reachableHeapSize = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
                        } else
                            object.reachableHeapSize = options.longs === String ? "0" : 0;
                        if ($util.Long) {
                            var long = new $util.Long(0, 0, false);
                            object.objCount = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
                        } else
                            object.objCount = options.longs === String ? "0" : 0;
                        if ($util.Long) {
                            var long = new $util.Long(0, 0, false);
                            object.reachableObjCount = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
                        } else
                            object.reachableObjCount = options.longs === String ? "0" : 0;
                        if ($util.Long) {
                            var long = new $util.Long(0, 0, false);
                            object.anonRssAndSwapSize = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
                        } else
                            object.anonRssAndSwapSize = options.longs === String ? "0" : 0;
                    }
                    if (message.ts != null && message.hasOwnProperty("ts"))
                        if (typeof message.ts === "number")
                            object.ts = options.longs === String ? String(message.ts) : message.ts;
                        else
                            object.ts = options.longs === String ? $util.Long.prototype.toString.call(message.ts) : options.longs === Number ? new $util.LongBits(message.ts.low >>> 0, message.ts.high >>> 0).toNumber() : message.ts;
                    if (message.heapSize != null && message.hasOwnProperty("heapSize"))
                        if (typeof message.heapSize === "number")
                            object.heapSize = options.longs === String ? String(message.heapSize) : message.heapSize;
                        else
                            object.heapSize = options.longs === String ? $util.Long.prototype.toString.call(message.heapSize) : options.longs === Number ? new $util.LongBits(message.heapSize.low >>> 0, message.heapSize.high >>> 0).toNumber() : message.heapSize;
                    if (message.reachableHeapSize != null && message.hasOwnProperty("reachableHeapSize"))
                        if (typeof message.reachableHeapSize === "number")
                            object.reachableHeapSize = options.longs === String ? String(message.reachableHeapSize) : message.reachableHeapSize;
                        else
                            object.reachableHeapSize = options.longs === String ? $util.Long.prototype.toString.call(message.reachableHeapSize) : options.longs === Number ? new $util.LongBits(message.reachableHeapSize.low >>> 0, message.reachableHeapSize.high >>> 0).toNumber() : message.reachableHeapSize;
                    if (message.objCount != null && message.hasOwnProperty("objCount"))
                        if (typeof message.objCount === "number")
                            object.objCount = options.longs === String ? String(message.objCount) : message.objCount;
                        else
                            object.objCount = options.longs === String ? $util.Long.prototype.toString.call(message.objCount) : options.longs === Number ? new $util.LongBits(message.objCount.low >>> 0, message.objCount.high >>> 0).toNumber() : message.objCount;
                    if (message.reachableObjCount != null && message.hasOwnProperty("reachableObjCount"))
                        if (typeof message.reachableObjCount === "number")
                            object.reachableObjCount = options.longs === String ? String(message.reachableObjCount) : message.reachableObjCount;
                        else
                            object.reachableObjCount = options.longs === String ? $util.Long.prototype.toString.call(message.reachableObjCount) : options.longs === Number ? new $util.LongBits(message.reachableObjCount.low >>> 0, message.reachableObjCount.high >>> 0).toNumber() : message.reachableObjCount;
                    if (message.anonRssAndSwapSize != null && message.hasOwnProperty("anonRssAndSwapSize"))
                        if (typeof message.anonRssAndSwapSize === "number")
                            object.anonRssAndSwapSize = options.longs === String ? String(message.anonRssAndSwapSize) : message.anonRssAndSwapSize;
                        else
                            object.anonRssAndSwapSize = options.longs === String ? $util.Long.prototype.toString.call(message.anonRssAndSwapSize) : options.longs === Number ? new $util.LongBits(message.anonRssAndSwapSize.low >>> 0, message.anonRssAndSwapSize.high >>> 0).toNumber() : message.anonRssAndSwapSize;
                    if (message.roots && message.roots.length) {
                        object.roots = [];
                        for (var j = 0; j < message.roots.length; ++j)
                            object.roots[j] = $root.perfetto.protos.JavaHeapStats.HeapRoots.toObject(message.roots[j], options);
                    }
                    return object;
                };

                /**
                 * Converts this Sample to JSON.
                 * @function toJSON
                 * @memberof perfetto.protos.JavaHeapStats.Sample
                 * @instance
                 * @returns {Object.<string,*>} JSON object
                 */
                Sample.prototype.toJSON = function toJSON() {
                    return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
                };

                return Sample;
            })();

            JavaHeapStats.InstanceStats = (function() {

                /**
                 * Properties of an InstanceStats.
                 * @memberof perfetto.protos.JavaHeapStats
                 * @interface IInstanceStats
                 * @property {number|null} [upid] InstanceStats upid
                 * @property {perfetto.protos.IAndroidProcessMetadata|null} [process] InstanceStats process
                 * @property {Array.<perfetto.protos.JavaHeapStats.ISample>|null} [samples] InstanceStats samples
                 */

                /**
                 * Constructs a new InstanceStats.
                 * @memberof perfetto.protos.JavaHeapStats
                 * @classdesc Represents an InstanceStats.
                 * @implements IInstanceStats
                 * @constructor
                 * @param {perfetto.protos.JavaHeapStats.IInstanceStats=} [properties] Properties to set
                 */
                function InstanceStats(properties) {
                    this.samples = [];
                    if (properties)
                        for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                            if (properties[keys[i]] != null)
                                this[keys[i]] = properties[keys[i]];
                }

                /**
                 * InstanceStats upid.
                 * @member {number} upid
                 * @memberof perfetto.protos.JavaHeapStats.InstanceStats
                 * @instance
                 */
                InstanceStats.prototype.upid = 0;

                /**
                 * InstanceStats process.
                 * @member {perfetto.protos.IAndroidProcessMetadata|null|undefined} process
                 * @memberof perfetto.protos.JavaHeapStats.InstanceStats
                 * @instance
                 */
                InstanceStats.prototype.process = null;

                /**
                 * InstanceStats samples.
                 * @member {Array.<perfetto.protos.JavaHeapStats.ISample>} samples
                 * @memberof perfetto.protos.JavaHeapStats.InstanceStats
                 * @instance
                 */
                InstanceStats.prototype.samples = $util.emptyArray;

                /**
                 * Creates a new InstanceStats instance using the specified properties.
                 * @function create
                 * @memberof perfetto.protos.JavaHeapStats.InstanceStats
                 * @static
                 * @param {perfetto.protos.JavaHeapStats.IInstanceStats=} [properties] Properties to set
                 * @returns {perfetto.protos.JavaHeapStats.InstanceStats} InstanceStats instance
                 */
                InstanceStats.create = function create(properties) {
                    return new InstanceStats(properties);
                };

                /**
                 * Encodes the specified InstanceStats message. Does not implicitly {@link perfetto.protos.JavaHeapStats.InstanceStats.verify|verify} messages.
                 * @function encode
                 * @memberof perfetto.protos.JavaHeapStats.InstanceStats
                 * @static
                 * @param {perfetto.protos.JavaHeapStats.IInstanceStats} message InstanceStats message or plain object to encode
                 * @param {$protobuf.Writer} [writer] Writer to encode to
                 * @returns {$protobuf.Writer} Writer
                 */
                InstanceStats.encode = function encode(message, writer) {
                    if (!writer)
                        writer = $Writer.create();
                    if (message.upid != null && Object.hasOwnProperty.call(message, "upid"))
                        writer.uint32(/* id 1, wireType 0 =*/8).uint32(message.upid);
                    if (message.process != null && Object.hasOwnProperty.call(message, "process"))
                        $root.perfetto.protos.AndroidProcessMetadata.encode(message.process, writer.uint32(/* id 2, wireType 2 =*/18).fork()).ldelim();
                    if (message.samples != null && message.samples.length)
                        for (var i = 0; i < message.samples.length; ++i)
                            $root.perfetto.protos.JavaHeapStats.Sample.encode(message.samples[i], writer.uint32(/* id 3, wireType 2 =*/26).fork()).ldelim();
                    return writer;
                };

                /**
                 * Encodes the specified InstanceStats message, length delimited. Does not implicitly {@link perfetto.protos.JavaHeapStats.InstanceStats.verify|verify} messages.
                 * @function encodeDelimited
                 * @memberof perfetto.protos.JavaHeapStats.InstanceStats
                 * @static
                 * @param {perfetto.protos.JavaHeapStats.IInstanceStats} message InstanceStats message or plain object to encode
                 * @param {$protobuf.Writer} [writer] Writer to encode to
                 * @returns {$protobuf.Writer} Writer
                 */
                InstanceStats.encodeDelimited = function encodeDelimited(message, writer) {
                    return this.encode(message, writer).ldelim();
                };

                /**
                 * Decodes an InstanceStats message from the specified reader or buffer.
                 * @function decode
                 * @memberof perfetto.protos.JavaHeapStats.InstanceStats
                 * @static
                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                 * @param {number} [length] Message length if known beforehand
                 * @returns {perfetto.protos.JavaHeapStats.InstanceStats} InstanceStats
                 * @throws {Error} If the payload is not a reader or valid buffer
                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
                 */
                InstanceStats.decode = function decode(reader, length) {
                    if (!(reader instanceof $Reader))
                        reader = $Reader.create(reader);
                    var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.JavaHeapStats.InstanceStats();
                    while (reader.pos < end) {
                        var tag = reader.uint32();
                        switch (tag >>> 3) {
                        case 1:
                            message.upid = reader.uint32();
                            break;
                        case 2:
                            message.process = $root.perfetto.protos.AndroidProcessMetadata.decode(reader, reader.uint32());
                            break;
                        case 3:
                            if (!(message.samples && message.samples.length))
                                message.samples = [];
                            message.samples.push($root.perfetto.protos.JavaHeapStats.Sample.decode(reader, reader.uint32()));
                            break;
                        default:
                            reader.skipType(tag & 7);
                            break;
                        }
                    }
                    return message;
                };

                /**
                 * Decodes an InstanceStats message from the specified reader or buffer, length delimited.
                 * @function decodeDelimited
                 * @memberof perfetto.protos.JavaHeapStats.InstanceStats
                 * @static
                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                 * @returns {perfetto.protos.JavaHeapStats.InstanceStats} InstanceStats
                 * @throws {Error} If the payload is not a reader or valid buffer
                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
                 */
                InstanceStats.decodeDelimited = function decodeDelimited(reader) {
                    if (!(reader instanceof $Reader))
                        reader = new $Reader(reader);
                    return this.decode(reader, reader.uint32());
                };

                /**
                 * Verifies an InstanceStats message.
                 * @function verify
                 * @memberof perfetto.protos.JavaHeapStats.InstanceStats
                 * @static
                 * @param {Object.<string,*>} message Plain object to verify
                 * @returns {string|null} `null` if valid, otherwise the reason why it is not
                 */
                InstanceStats.verify = function verify(message) {
                    if (typeof message !== "object" || message === null)
                        return "object expected";
                    if (message.upid != null && message.hasOwnProperty("upid"))
                        if (!$util.isInteger(message.upid))
                            return "upid: integer expected";
                    if (message.process != null && message.hasOwnProperty("process")) {
                        var error = $root.perfetto.protos.AndroidProcessMetadata.verify(message.process);
                        if (error)
                            return "process." + error;
                    }
                    if (message.samples != null && message.hasOwnProperty("samples")) {
                        if (!Array.isArray(message.samples))
                            return "samples: array expected";
                        for (var i = 0; i < message.samples.length; ++i) {
                            var error = $root.perfetto.protos.JavaHeapStats.Sample.verify(message.samples[i]);
                            if (error)
                                return "samples." + error;
                        }
                    }
                    return null;
                };

                /**
                 * Creates an InstanceStats message from a plain object. Also converts values to their respective internal types.
                 * @function fromObject
                 * @memberof perfetto.protos.JavaHeapStats.InstanceStats
                 * @static
                 * @param {Object.<string,*>} object Plain object
                 * @returns {perfetto.protos.JavaHeapStats.InstanceStats} InstanceStats
                 */
                InstanceStats.fromObject = function fromObject(object) {
                    if (object instanceof $root.perfetto.protos.JavaHeapStats.InstanceStats)
                        return object;
                    var message = new $root.perfetto.protos.JavaHeapStats.InstanceStats();
                    if (object.upid != null)
                        message.upid = object.upid >>> 0;
                    if (object.process != null) {
                        if (typeof object.process !== "object")
                            throw TypeError(".perfetto.protos.JavaHeapStats.InstanceStats.process: object expected");
                        message.process = $root.perfetto.protos.AndroidProcessMetadata.fromObject(object.process);
                    }
                    if (object.samples) {
                        if (!Array.isArray(object.samples))
                            throw TypeError(".perfetto.protos.JavaHeapStats.InstanceStats.samples: array expected");
                        message.samples = [];
                        for (var i = 0; i < object.samples.length; ++i) {
                            if (typeof object.samples[i] !== "object")
                                throw TypeError(".perfetto.protos.JavaHeapStats.InstanceStats.samples: object expected");
                            message.samples[i] = $root.perfetto.protos.JavaHeapStats.Sample.fromObject(object.samples[i]);
                        }
                    }
                    return message;
                };

                /**
                 * Creates a plain object from an InstanceStats message. Also converts values to other types if specified.
                 * @function toObject
                 * @memberof perfetto.protos.JavaHeapStats.InstanceStats
                 * @static
                 * @param {perfetto.protos.JavaHeapStats.InstanceStats} message InstanceStats
                 * @param {$protobuf.IConversionOptions} [options] Conversion options
                 * @returns {Object.<string,*>} Plain object
                 */
                InstanceStats.toObject = function toObject(message, options) {
                    if (!options)
                        options = {};
                    var object = {};
                    if (options.arrays || options.defaults)
                        object.samples = [];
                    if (options.defaults) {
                        object.upid = 0;
                        object.process = null;
                    }
                    if (message.upid != null && message.hasOwnProperty("upid"))
                        object.upid = message.upid;
                    if (message.process != null && message.hasOwnProperty("process"))
                        object.process = $root.perfetto.protos.AndroidProcessMetadata.toObject(message.process, options);
                    if (message.samples && message.samples.length) {
                        object.samples = [];
                        for (var j = 0; j < message.samples.length; ++j)
                            object.samples[j] = $root.perfetto.protos.JavaHeapStats.Sample.toObject(message.samples[j], options);
                    }
                    return object;
                };

                /**
                 * Converts this InstanceStats to JSON.
                 * @function toJSON
                 * @memberof perfetto.protos.JavaHeapStats.InstanceStats
                 * @instance
                 * @returns {Object.<string,*>} JSON object
                 */
                InstanceStats.prototype.toJSON = function toJSON() {
                    return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
                };

                return InstanceStats;
            })();

            return JavaHeapStats;
        })();

        protos.AndroidLmkMetric = (function() {

            /**
             * Properties of an AndroidLmkMetric.
             * @memberof perfetto.protos
             * @interface IAndroidLmkMetric
             * @property {number|null} [totalCount] AndroidLmkMetric totalCount
             * @property {Array.<perfetto.protos.AndroidLmkMetric.IByOomScore>|null} [byOomScore] AndroidLmkMetric byOomScore
             * @property {number|null} [oomVictimCount] AndroidLmkMetric oomVictimCount
             */

            /**
             * Constructs a new AndroidLmkMetric.
             * @memberof perfetto.protos
             * @classdesc Represents an AndroidLmkMetric.
             * @implements IAndroidLmkMetric
             * @constructor
             * @param {perfetto.protos.IAndroidLmkMetric=} [properties] Properties to set
             */
            function AndroidLmkMetric(properties) {
                this.byOomScore = [];
                if (properties)
                    for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                        if (properties[keys[i]] != null)
                            this[keys[i]] = properties[keys[i]];
            }

            /**
             * AndroidLmkMetric totalCount.
             * @member {number} totalCount
             * @memberof perfetto.protos.AndroidLmkMetric
             * @instance
             */
            AndroidLmkMetric.prototype.totalCount = 0;

            /**
             * AndroidLmkMetric byOomScore.
             * @member {Array.<perfetto.protos.AndroidLmkMetric.IByOomScore>} byOomScore
             * @memberof perfetto.protos.AndroidLmkMetric
             * @instance
             */
            AndroidLmkMetric.prototype.byOomScore = $util.emptyArray;

            /**
             * AndroidLmkMetric oomVictimCount.
             * @member {number} oomVictimCount
             * @memberof perfetto.protos.AndroidLmkMetric
             * @instance
             */
            AndroidLmkMetric.prototype.oomVictimCount = 0;

            /**
             * Creates a new AndroidLmkMetric instance using the specified properties.
             * @function create
             * @memberof perfetto.protos.AndroidLmkMetric
             * @static
             * @param {perfetto.protos.IAndroidLmkMetric=} [properties] Properties to set
             * @returns {perfetto.protos.AndroidLmkMetric} AndroidLmkMetric instance
             */
            AndroidLmkMetric.create = function create(properties) {
                return new AndroidLmkMetric(properties);
            };

            /**
             * Encodes the specified AndroidLmkMetric message. Does not implicitly {@link perfetto.protos.AndroidLmkMetric.verify|verify} messages.
             * @function encode
             * @memberof perfetto.protos.AndroidLmkMetric
             * @static
             * @param {perfetto.protos.IAndroidLmkMetric} message AndroidLmkMetric message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            AndroidLmkMetric.encode = function encode(message, writer) {
                if (!writer)
                    writer = $Writer.create();
                if (message.totalCount != null && Object.hasOwnProperty.call(message, "totalCount"))
                    writer.uint32(/* id 1, wireType 0 =*/8).int32(message.totalCount);
                if (message.byOomScore != null && message.byOomScore.length)
                    for (var i = 0; i < message.byOomScore.length; ++i)
                        $root.perfetto.protos.AndroidLmkMetric.ByOomScore.encode(message.byOomScore[i], writer.uint32(/* id 2, wireType 2 =*/18).fork()).ldelim();
                if (message.oomVictimCount != null && Object.hasOwnProperty.call(message, "oomVictimCount"))
                    writer.uint32(/* id 3, wireType 0 =*/24).int32(message.oomVictimCount);
                return writer;
            };

            /**
             * Encodes the specified AndroidLmkMetric message, length delimited. Does not implicitly {@link perfetto.protos.AndroidLmkMetric.verify|verify} messages.
             * @function encodeDelimited
             * @memberof perfetto.protos.AndroidLmkMetric
             * @static
             * @param {perfetto.protos.IAndroidLmkMetric} message AndroidLmkMetric message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            AndroidLmkMetric.encodeDelimited = function encodeDelimited(message, writer) {
                return this.encode(message, writer).ldelim();
            };

            /**
             * Decodes an AndroidLmkMetric message from the specified reader or buffer.
             * @function decode
             * @memberof perfetto.protos.AndroidLmkMetric
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @param {number} [length] Message length if known beforehand
             * @returns {perfetto.protos.AndroidLmkMetric} AndroidLmkMetric
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            AndroidLmkMetric.decode = function decode(reader, length) {
                if (!(reader instanceof $Reader))
                    reader = $Reader.create(reader);
                var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.AndroidLmkMetric();
                while (reader.pos < end) {
                    var tag = reader.uint32();
                    switch (tag >>> 3) {
                    case 1:
                        message.totalCount = reader.int32();
                        break;
                    case 2:
                        if (!(message.byOomScore && message.byOomScore.length))
                            message.byOomScore = [];
                        message.byOomScore.push($root.perfetto.protos.AndroidLmkMetric.ByOomScore.decode(reader, reader.uint32()));
                        break;
                    case 3:
                        message.oomVictimCount = reader.int32();
                        break;
                    default:
                        reader.skipType(tag & 7);
                        break;
                    }
                }
                return message;
            };

            /**
             * Decodes an AndroidLmkMetric message from the specified reader or buffer, length delimited.
             * @function decodeDelimited
             * @memberof perfetto.protos.AndroidLmkMetric
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @returns {perfetto.protos.AndroidLmkMetric} AndroidLmkMetric
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            AndroidLmkMetric.decodeDelimited = function decodeDelimited(reader) {
                if (!(reader instanceof $Reader))
                    reader = new $Reader(reader);
                return this.decode(reader, reader.uint32());
            };

            /**
             * Verifies an AndroidLmkMetric message.
             * @function verify
             * @memberof perfetto.protos.AndroidLmkMetric
             * @static
             * @param {Object.<string,*>} message Plain object to verify
             * @returns {string|null} `null` if valid, otherwise the reason why it is not
             */
            AndroidLmkMetric.verify = function verify(message) {
                if (typeof message !== "object" || message === null)
                    return "object expected";
                if (message.totalCount != null && message.hasOwnProperty("totalCount"))
                    if (!$util.isInteger(message.totalCount))
                        return "totalCount: integer expected";
                if (message.byOomScore != null && message.hasOwnProperty("byOomScore")) {
                    if (!Array.isArray(message.byOomScore))
                        return "byOomScore: array expected";
                    for (var i = 0; i < message.byOomScore.length; ++i) {
                        var error = $root.perfetto.protos.AndroidLmkMetric.ByOomScore.verify(message.byOomScore[i]);
                        if (error)
                            return "byOomScore." + error;
                    }
                }
                if (message.oomVictimCount != null && message.hasOwnProperty("oomVictimCount"))
                    if (!$util.isInteger(message.oomVictimCount))
                        return "oomVictimCount: integer expected";
                return null;
            };

            /**
             * Creates an AndroidLmkMetric message from a plain object. Also converts values to their respective internal types.
             * @function fromObject
             * @memberof perfetto.protos.AndroidLmkMetric
             * @static
             * @param {Object.<string,*>} object Plain object
             * @returns {perfetto.protos.AndroidLmkMetric} AndroidLmkMetric
             */
            AndroidLmkMetric.fromObject = function fromObject(object) {
                if (object instanceof $root.perfetto.protos.AndroidLmkMetric)
                    return object;
                var message = new $root.perfetto.protos.AndroidLmkMetric();
                if (object.totalCount != null)
                    message.totalCount = object.totalCount | 0;
                if (object.byOomScore) {
                    if (!Array.isArray(object.byOomScore))
                        throw TypeError(".perfetto.protos.AndroidLmkMetric.byOomScore: array expected");
                    message.byOomScore = [];
                    for (var i = 0; i < object.byOomScore.length; ++i) {
                        if (typeof object.byOomScore[i] !== "object")
                            throw TypeError(".perfetto.protos.AndroidLmkMetric.byOomScore: object expected");
                        message.byOomScore[i] = $root.perfetto.protos.AndroidLmkMetric.ByOomScore.fromObject(object.byOomScore[i]);
                    }
                }
                if (object.oomVictimCount != null)
                    message.oomVictimCount = object.oomVictimCount | 0;
                return message;
            };

            /**
             * Creates a plain object from an AndroidLmkMetric message. Also converts values to other types if specified.
             * @function toObject
             * @memberof perfetto.protos.AndroidLmkMetric
             * @static
             * @param {perfetto.protos.AndroidLmkMetric} message AndroidLmkMetric
             * @param {$protobuf.IConversionOptions} [options] Conversion options
             * @returns {Object.<string,*>} Plain object
             */
            AndroidLmkMetric.toObject = function toObject(message, options) {
                if (!options)
                    options = {};
                var object = {};
                if (options.arrays || options.defaults)
                    object.byOomScore = [];
                if (options.defaults) {
                    object.totalCount = 0;
                    object.oomVictimCount = 0;
                }
                if (message.totalCount != null && message.hasOwnProperty("totalCount"))
                    object.totalCount = message.totalCount;
                if (message.byOomScore && message.byOomScore.length) {
                    object.byOomScore = [];
                    for (var j = 0; j < message.byOomScore.length; ++j)
                        object.byOomScore[j] = $root.perfetto.protos.AndroidLmkMetric.ByOomScore.toObject(message.byOomScore[j], options);
                }
                if (message.oomVictimCount != null && message.hasOwnProperty("oomVictimCount"))
                    object.oomVictimCount = message.oomVictimCount;
                return object;
            };

            /**
             * Converts this AndroidLmkMetric to JSON.
             * @function toJSON
             * @memberof perfetto.protos.AndroidLmkMetric
             * @instance
             * @returns {Object.<string,*>} JSON object
             */
            AndroidLmkMetric.prototype.toJSON = function toJSON() {
                return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
            };

            AndroidLmkMetric.ByOomScore = (function() {

                /**
                 * Properties of a ByOomScore.
                 * @memberof perfetto.protos.AndroidLmkMetric
                 * @interface IByOomScore
                 * @property {number|null} [oomScoreAdj] ByOomScore oomScoreAdj
                 * @property {number|null} [count] ByOomScore count
                 */

                /**
                 * Constructs a new ByOomScore.
                 * @memberof perfetto.protos.AndroidLmkMetric
                 * @classdesc Represents a ByOomScore.
                 * @implements IByOomScore
                 * @constructor
                 * @param {perfetto.protos.AndroidLmkMetric.IByOomScore=} [properties] Properties to set
                 */
                function ByOomScore(properties) {
                    if (properties)
                        for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                            if (properties[keys[i]] != null)
                                this[keys[i]] = properties[keys[i]];
                }

                /**
                 * ByOomScore oomScoreAdj.
                 * @member {number} oomScoreAdj
                 * @memberof perfetto.protos.AndroidLmkMetric.ByOomScore
                 * @instance
                 */
                ByOomScore.prototype.oomScoreAdj = 0;

                /**
                 * ByOomScore count.
                 * @member {number} count
                 * @memberof perfetto.protos.AndroidLmkMetric.ByOomScore
                 * @instance
                 */
                ByOomScore.prototype.count = 0;

                /**
                 * Creates a new ByOomScore instance using the specified properties.
                 * @function create
                 * @memberof perfetto.protos.AndroidLmkMetric.ByOomScore
                 * @static
                 * @param {perfetto.protos.AndroidLmkMetric.IByOomScore=} [properties] Properties to set
                 * @returns {perfetto.protos.AndroidLmkMetric.ByOomScore} ByOomScore instance
                 */
                ByOomScore.create = function create(properties) {
                    return new ByOomScore(properties);
                };

                /**
                 * Encodes the specified ByOomScore message. Does not implicitly {@link perfetto.protos.AndroidLmkMetric.ByOomScore.verify|verify} messages.
                 * @function encode
                 * @memberof perfetto.protos.AndroidLmkMetric.ByOomScore
                 * @static
                 * @param {perfetto.protos.AndroidLmkMetric.IByOomScore} message ByOomScore message or plain object to encode
                 * @param {$protobuf.Writer} [writer] Writer to encode to
                 * @returns {$protobuf.Writer} Writer
                 */
                ByOomScore.encode = function encode(message, writer) {
                    if (!writer)
                        writer = $Writer.create();
                    if (message.oomScoreAdj != null && Object.hasOwnProperty.call(message, "oomScoreAdj"))
                        writer.uint32(/* id 1, wireType 0 =*/8).int32(message.oomScoreAdj);
                    if (message.count != null && Object.hasOwnProperty.call(message, "count"))
                        writer.uint32(/* id 2, wireType 0 =*/16).int32(message.count);
                    return writer;
                };

                /**
                 * Encodes the specified ByOomScore message, length delimited. Does not implicitly {@link perfetto.protos.AndroidLmkMetric.ByOomScore.verify|verify} messages.
                 * @function encodeDelimited
                 * @memberof perfetto.protos.AndroidLmkMetric.ByOomScore
                 * @static
                 * @param {perfetto.protos.AndroidLmkMetric.IByOomScore} message ByOomScore message or plain object to encode
                 * @param {$protobuf.Writer} [writer] Writer to encode to
                 * @returns {$protobuf.Writer} Writer
                 */
                ByOomScore.encodeDelimited = function encodeDelimited(message, writer) {
                    return this.encode(message, writer).ldelim();
                };

                /**
                 * Decodes a ByOomScore message from the specified reader or buffer.
                 * @function decode
                 * @memberof perfetto.protos.AndroidLmkMetric.ByOomScore
                 * @static
                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                 * @param {number} [length] Message length if known beforehand
                 * @returns {perfetto.protos.AndroidLmkMetric.ByOomScore} ByOomScore
                 * @throws {Error} If the payload is not a reader or valid buffer
                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
                 */
                ByOomScore.decode = function decode(reader, length) {
                    if (!(reader instanceof $Reader))
                        reader = $Reader.create(reader);
                    var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.AndroidLmkMetric.ByOomScore();
                    while (reader.pos < end) {
                        var tag = reader.uint32();
                        switch (tag >>> 3) {
                        case 1:
                            message.oomScoreAdj = reader.int32();
                            break;
                        case 2:
                            message.count = reader.int32();
                            break;
                        default:
                            reader.skipType(tag & 7);
                            break;
                        }
                    }
                    return message;
                };

                /**
                 * Decodes a ByOomScore message from the specified reader or buffer, length delimited.
                 * @function decodeDelimited
                 * @memberof perfetto.protos.AndroidLmkMetric.ByOomScore
                 * @static
                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                 * @returns {perfetto.protos.AndroidLmkMetric.ByOomScore} ByOomScore
                 * @throws {Error} If the payload is not a reader or valid buffer
                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
                 */
                ByOomScore.decodeDelimited = function decodeDelimited(reader) {
                    if (!(reader instanceof $Reader))
                        reader = new $Reader(reader);
                    return this.decode(reader, reader.uint32());
                };

                /**
                 * Verifies a ByOomScore message.
                 * @function verify
                 * @memberof perfetto.protos.AndroidLmkMetric.ByOomScore
                 * @static
                 * @param {Object.<string,*>} message Plain object to verify
                 * @returns {string|null} `null` if valid, otherwise the reason why it is not
                 */
                ByOomScore.verify = function verify(message) {
                    if (typeof message !== "object" || message === null)
                        return "object expected";
                    if (message.oomScoreAdj != null && message.hasOwnProperty("oomScoreAdj"))
                        if (!$util.isInteger(message.oomScoreAdj))
                            return "oomScoreAdj: integer expected";
                    if (message.count != null && message.hasOwnProperty("count"))
                        if (!$util.isInteger(message.count))
                            return "count: integer expected";
                    return null;
                };

                /**
                 * Creates a ByOomScore message from a plain object. Also converts values to their respective internal types.
                 * @function fromObject
                 * @memberof perfetto.protos.AndroidLmkMetric.ByOomScore
                 * @static
                 * @param {Object.<string,*>} object Plain object
                 * @returns {perfetto.protos.AndroidLmkMetric.ByOomScore} ByOomScore
                 */
                ByOomScore.fromObject = function fromObject(object) {
                    if (object instanceof $root.perfetto.protos.AndroidLmkMetric.ByOomScore)
                        return object;
                    var message = new $root.perfetto.protos.AndroidLmkMetric.ByOomScore();
                    if (object.oomScoreAdj != null)
                        message.oomScoreAdj = object.oomScoreAdj | 0;
                    if (object.count != null)
                        message.count = object.count | 0;
                    return message;
                };

                /**
                 * Creates a plain object from a ByOomScore message. Also converts values to other types if specified.
                 * @function toObject
                 * @memberof perfetto.protos.AndroidLmkMetric.ByOomScore
                 * @static
                 * @param {perfetto.protos.AndroidLmkMetric.ByOomScore} message ByOomScore
                 * @param {$protobuf.IConversionOptions} [options] Conversion options
                 * @returns {Object.<string,*>} Plain object
                 */
                ByOomScore.toObject = function toObject(message, options) {
                    if (!options)
                        options = {};
                    var object = {};
                    if (options.defaults) {
                        object.oomScoreAdj = 0;
                        object.count = 0;
                    }
                    if (message.oomScoreAdj != null && message.hasOwnProperty("oomScoreAdj"))
                        object.oomScoreAdj = message.oomScoreAdj;
                    if (message.count != null && message.hasOwnProperty("count"))
                        object.count = message.count;
                    return object;
                };

                /**
                 * Converts this ByOomScore to JSON.
                 * @function toJSON
                 * @memberof perfetto.protos.AndroidLmkMetric.ByOomScore
                 * @instance
                 * @returns {Object.<string,*>} JSON object
                 */
                ByOomScore.prototype.toJSON = function toJSON() {
                    return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
                };

                return ByOomScore;
            })();

            return AndroidLmkMetric;
        })();

        protos.AndroidLmkReasonMetric = (function() {

            /**
             * Properties of an AndroidLmkReasonMetric.
             * @memberof perfetto.protos
             * @interface IAndroidLmkReasonMetric
             * @property {Array.<perfetto.protos.AndroidLmkReasonMetric.ILmk>|null} [lmks] AndroidLmkReasonMetric lmks
             */

            /**
             * Constructs a new AndroidLmkReasonMetric.
             * @memberof perfetto.protos
             * @classdesc Represents an AndroidLmkReasonMetric.
             * @implements IAndroidLmkReasonMetric
             * @constructor
             * @param {perfetto.protos.IAndroidLmkReasonMetric=} [properties] Properties to set
             */
            function AndroidLmkReasonMetric(properties) {
                this.lmks = [];
                if (properties)
                    for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                        if (properties[keys[i]] != null)
                            this[keys[i]] = properties[keys[i]];
            }

            /**
             * AndroidLmkReasonMetric lmks.
             * @member {Array.<perfetto.protos.AndroidLmkReasonMetric.ILmk>} lmks
             * @memberof perfetto.protos.AndroidLmkReasonMetric
             * @instance
             */
            AndroidLmkReasonMetric.prototype.lmks = $util.emptyArray;

            /**
             * Creates a new AndroidLmkReasonMetric instance using the specified properties.
             * @function create
             * @memberof perfetto.protos.AndroidLmkReasonMetric
             * @static
             * @param {perfetto.protos.IAndroidLmkReasonMetric=} [properties] Properties to set
             * @returns {perfetto.protos.AndroidLmkReasonMetric} AndroidLmkReasonMetric instance
             */
            AndroidLmkReasonMetric.create = function create(properties) {
                return new AndroidLmkReasonMetric(properties);
            };

            /**
             * Encodes the specified AndroidLmkReasonMetric message. Does not implicitly {@link perfetto.protos.AndroidLmkReasonMetric.verify|verify} messages.
             * @function encode
             * @memberof perfetto.protos.AndroidLmkReasonMetric
             * @static
             * @param {perfetto.protos.IAndroidLmkReasonMetric} message AndroidLmkReasonMetric message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            AndroidLmkReasonMetric.encode = function encode(message, writer) {
                if (!writer)
                    writer = $Writer.create();
                if (message.lmks != null && message.lmks.length)
                    for (var i = 0; i < message.lmks.length; ++i)
                        $root.perfetto.protos.AndroidLmkReasonMetric.Lmk.encode(message.lmks[i], writer.uint32(/* id 1, wireType 2 =*/10).fork()).ldelim();
                return writer;
            };

            /**
             * Encodes the specified AndroidLmkReasonMetric message, length delimited. Does not implicitly {@link perfetto.protos.AndroidLmkReasonMetric.verify|verify} messages.
             * @function encodeDelimited
             * @memberof perfetto.protos.AndroidLmkReasonMetric
             * @static
             * @param {perfetto.protos.IAndroidLmkReasonMetric} message AndroidLmkReasonMetric message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            AndroidLmkReasonMetric.encodeDelimited = function encodeDelimited(message, writer) {
                return this.encode(message, writer).ldelim();
            };

            /**
             * Decodes an AndroidLmkReasonMetric message from the specified reader or buffer.
             * @function decode
             * @memberof perfetto.protos.AndroidLmkReasonMetric
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @param {number} [length] Message length if known beforehand
             * @returns {perfetto.protos.AndroidLmkReasonMetric} AndroidLmkReasonMetric
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            AndroidLmkReasonMetric.decode = function decode(reader, length) {
                if (!(reader instanceof $Reader))
                    reader = $Reader.create(reader);
                var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.AndroidLmkReasonMetric();
                while (reader.pos < end) {
                    var tag = reader.uint32();
                    switch (tag >>> 3) {
                    case 1:
                        if (!(message.lmks && message.lmks.length))
                            message.lmks = [];
                        message.lmks.push($root.perfetto.protos.AndroidLmkReasonMetric.Lmk.decode(reader, reader.uint32()));
                        break;
                    default:
                        reader.skipType(tag & 7);
                        break;
                    }
                }
                return message;
            };

            /**
             * Decodes an AndroidLmkReasonMetric message from the specified reader or buffer, length delimited.
             * @function decodeDelimited
             * @memberof perfetto.protos.AndroidLmkReasonMetric
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @returns {perfetto.protos.AndroidLmkReasonMetric} AndroidLmkReasonMetric
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            AndroidLmkReasonMetric.decodeDelimited = function decodeDelimited(reader) {
                if (!(reader instanceof $Reader))
                    reader = new $Reader(reader);
                return this.decode(reader, reader.uint32());
            };

            /**
             * Verifies an AndroidLmkReasonMetric message.
             * @function verify
             * @memberof perfetto.protos.AndroidLmkReasonMetric
             * @static
             * @param {Object.<string,*>} message Plain object to verify
             * @returns {string|null} `null` if valid, otherwise the reason why it is not
             */
            AndroidLmkReasonMetric.verify = function verify(message) {
                if (typeof message !== "object" || message === null)
                    return "object expected";
                if (message.lmks != null && message.hasOwnProperty("lmks")) {
                    if (!Array.isArray(message.lmks))
                        return "lmks: array expected";
                    for (var i = 0; i < message.lmks.length; ++i) {
                        var error = $root.perfetto.protos.AndroidLmkReasonMetric.Lmk.verify(message.lmks[i]);
                        if (error)
                            return "lmks." + error;
                    }
                }
                return null;
            };

            /**
             * Creates an AndroidLmkReasonMetric message from a plain object. Also converts values to their respective internal types.
             * @function fromObject
             * @memberof perfetto.protos.AndroidLmkReasonMetric
             * @static
             * @param {Object.<string,*>} object Plain object
             * @returns {perfetto.protos.AndroidLmkReasonMetric} AndroidLmkReasonMetric
             */
            AndroidLmkReasonMetric.fromObject = function fromObject(object) {
                if (object instanceof $root.perfetto.protos.AndroidLmkReasonMetric)
                    return object;
                var message = new $root.perfetto.protos.AndroidLmkReasonMetric();
                if (object.lmks) {
                    if (!Array.isArray(object.lmks))
                        throw TypeError(".perfetto.protos.AndroidLmkReasonMetric.lmks: array expected");
                    message.lmks = [];
                    for (var i = 0; i < object.lmks.length; ++i) {
                        if (typeof object.lmks[i] !== "object")
                            throw TypeError(".perfetto.protos.AndroidLmkReasonMetric.lmks: object expected");
                        message.lmks[i] = $root.perfetto.protos.AndroidLmkReasonMetric.Lmk.fromObject(object.lmks[i]);
                    }
                }
                return message;
            };

            /**
             * Creates a plain object from an AndroidLmkReasonMetric message. Also converts values to other types if specified.
             * @function toObject
             * @memberof perfetto.protos.AndroidLmkReasonMetric
             * @static
             * @param {perfetto.protos.AndroidLmkReasonMetric} message AndroidLmkReasonMetric
             * @param {$protobuf.IConversionOptions} [options] Conversion options
             * @returns {Object.<string,*>} Plain object
             */
            AndroidLmkReasonMetric.toObject = function toObject(message, options) {
                if (!options)
                    options = {};
                var object = {};
                if (options.arrays || options.defaults)
                    object.lmks = [];
                if (message.lmks && message.lmks.length) {
                    object.lmks = [];
                    for (var j = 0; j < message.lmks.length; ++j)
                        object.lmks[j] = $root.perfetto.protos.AndroidLmkReasonMetric.Lmk.toObject(message.lmks[j], options);
                }
                return object;
            };

            /**
             * Converts this AndroidLmkReasonMetric to JSON.
             * @function toJSON
             * @memberof perfetto.protos.AndroidLmkReasonMetric
             * @instance
             * @returns {Object.<string,*>} JSON object
             */
            AndroidLmkReasonMetric.prototype.toJSON = function toJSON() {
                return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
            };

            AndroidLmkReasonMetric.Process = (function() {

                /**
                 * Properties of a Process.
                 * @memberof perfetto.protos.AndroidLmkReasonMetric
                 * @interface IProcess
                 * @property {perfetto.protos.IAndroidProcessMetadata|null} [process] Process process
                 * @property {number|null} [oomScoreAdj] Process oomScoreAdj
                 * @property {number|null} [size] Process size
                 * @property {number|null} [fileRssBytes] Process fileRssBytes
                 * @property {number|null} [anonRssBytes] Process anonRssBytes
                 * @property {number|null} [shmemRssBytes] Process shmemRssBytes
                 * @property {number|null} [swapBytes] Process swapBytes
                 */

                /**
                 * Constructs a new Process.
                 * @memberof perfetto.protos.AndroidLmkReasonMetric
                 * @classdesc Represents a Process.
                 * @implements IProcess
                 * @constructor
                 * @param {perfetto.protos.AndroidLmkReasonMetric.IProcess=} [properties] Properties to set
                 */
                function Process(properties) {
                    if (properties)
                        for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                            if (properties[keys[i]] != null)
                                this[keys[i]] = properties[keys[i]];
                }

                /**
                 * Process process.
                 * @member {perfetto.protos.IAndroidProcessMetadata|null|undefined} process
                 * @memberof perfetto.protos.AndroidLmkReasonMetric.Process
                 * @instance
                 */
                Process.prototype.process = null;

                /**
                 * Process oomScoreAdj.
                 * @member {number} oomScoreAdj
                 * @memberof perfetto.protos.AndroidLmkReasonMetric.Process
                 * @instance
                 */
                Process.prototype.oomScoreAdj = 0;

                /**
                 * Process size.
                 * @member {number} size
                 * @memberof perfetto.protos.AndroidLmkReasonMetric.Process
                 * @instance
                 */
                Process.prototype.size = $util.Long ? $util.Long.fromBits(0,0,false) : 0;

                /**
                 * Process fileRssBytes.
                 * @member {number} fileRssBytes
                 * @memberof perfetto.protos.AndroidLmkReasonMetric.Process
                 * @instance
                 */
                Process.prototype.fileRssBytes = $util.Long ? $util.Long.fromBits(0,0,false) : 0;

                /**
                 * Process anonRssBytes.
                 * @member {number} anonRssBytes
                 * @memberof perfetto.protos.AndroidLmkReasonMetric.Process
                 * @instance
                 */
                Process.prototype.anonRssBytes = $util.Long ? $util.Long.fromBits(0,0,false) : 0;

                /**
                 * Process shmemRssBytes.
                 * @member {number} shmemRssBytes
                 * @memberof perfetto.protos.AndroidLmkReasonMetric.Process
                 * @instance
                 */
                Process.prototype.shmemRssBytes = $util.Long ? $util.Long.fromBits(0,0,false) : 0;

                /**
                 * Process swapBytes.
                 * @member {number} swapBytes
                 * @memberof perfetto.protos.AndroidLmkReasonMetric.Process
                 * @instance
                 */
                Process.prototype.swapBytes = $util.Long ? $util.Long.fromBits(0,0,false) : 0;

                /**
                 * Creates a new Process instance using the specified properties.
                 * @function create
                 * @memberof perfetto.protos.AndroidLmkReasonMetric.Process
                 * @static
                 * @param {perfetto.protos.AndroidLmkReasonMetric.IProcess=} [properties] Properties to set
                 * @returns {perfetto.protos.AndroidLmkReasonMetric.Process} Process instance
                 */
                Process.create = function create(properties) {
                    return new Process(properties);
                };

                /**
                 * Encodes the specified Process message. Does not implicitly {@link perfetto.protos.AndroidLmkReasonMetric.Process.verify|verify} messages.
                 * @function encode
                 * @memberof perfetto.protos.AndroidLmkReasonMetric.Process
                 * @static
                 * @param {perfetto.protos.AndroidLmkReasonMetric.IProcess} message Process message or plain object to encode
                 * @param {$protobuf.Writer} [writer] Writer to encode to
                 * @returns {$protobuf.Writer} Writer
                 */
                Process.encode = function encode(message, writer) {
                    if (!writer)
                        writer = $Writer.create();
                    if (message.process != null && Object.hasOwnProperty.call(message, "process"))
                        $root.perfetto.protos.AndroidProcessMetadata.encode(message.process, writer.uint32(/* id 1, wireType 2 =*/10).fork()).ldelim();
                    if (message.oomScoreAdj != null && Object.hasOwnProperty.call(message, "oomScoreAdj"))
                        writer.uint32(/* id 2, wireType 0 =*/16).int32(message.oomScoreAdj);
                    if (message.size != null && Object.hasOwnProperty.call(message, "size"))
                        writer.uint32(/* id 3, wireType 0 =*/24).int64(message.size);
                    if (message.fileRssBytes != null && Object.hasOwnProperty.call(message, "fileRssBytes"))
                        writer.uint32(/* id 4, wireType 0 =*/32).int64(message.fileRssBytes);
                    if (message.anonRssBytes != null && Object.hasOwnProperty.call(message, "anonRssBytes"))
                        writer.uint32(/* id 5, wireType 0 =*/40).int64(message.anonRssBytes);
                    if (message.shmemRssBytes != null && Object.hasOwnProperty.call(message, "shmemRssBytes"))
                        writer.uint32(/* id 6, wireType 0 =*/48).int64(message.shmemRssBytes);
                    if (message.swapBytes != null && Object.hasOwnProperty.call(message, "swapBytes"))
                        writer.uint32(/* id 7, wireType 0 =*/56).int64(message.swapBytes);
                    return writer;
                };

                /**
                 * Encodes the specified Process message, length delimited. Does not implicitly {@link perfetto.protos.AndroidLmkReasonMetric.Process.verify|verify} messages.
                 * @function encodeDelimited
                 * @memberof perfetto.protos.AndroidLmkReasonMetric.Process
                 * @static
                 * @param {perfetto.protos.AndroidLmkReasonMetric.IProcess} message Process message or plain object to encode
                 * @param {$protobuf.Writer} [writer] Writer to encode to
                 * @returns {$protobuf.Writer} Writer
                 */
                Process.encodeDelimited = function encodeDelimited(message, writer) {
                    return this.encode(message, writer).ldelim();
                };

                /**
                 * Decodes a Process message from the specified reader or buffer.
                 * @function decode
                 * @memberof perfetto.protos.AndroidLmkReasonMetric.Process
                 * @static
                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                 * @param {number} [length] Message length if known beforehand
                 * @returns {perfetto.protos.AndroidLmkReasonMetric.Process} Process
                 * @throws {Error} If the payload is not a reader or valid buffer
                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
                 */
                Process.decode = function decode(reader, length) {
                    if (!(reader instanceof $Reader))
                        reader = $Reader.create(reader);
                    var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.AndroidLmkReasonMetric.Process();
                    while (reader.pos < end) {
                        var tag = reader.uint32();
                        switch (tag >>> 3) {
                        case 1:
                            message.process = $root.perfetto.protos.AndroidProcessMetadata.decode(reader, reader.uint32());
                            break;
                        case 2:
                            message.oomScoreAdj = reader.int32();
                            break;
                        case 3:
                            message.size = reader.int64();
                            break;
                        case 4:
                            message.fileRssBytes = reader.int64();
                            break;
                        case 5:
                            message.anonRssBytes = reader.int64();
                            break;
                        case 6:
                            message.shmemRssBytes = reader.int64();
                            break;
                        case 7:
                            message.swapBytes = reader.int64();
                            break;
                        default:
                            reader.skipType(tag & 7);
                            break;
                        }
                    }
                    return message;
                };

                /**
                 * Decodes a Process message from the specified reader or buffer, length delimited.
                 * @function decodeDelimited
                 * @memberof perfetto.protos.AndroidLmkReasonMetric.Process
                 * @static
                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                 * @returns {perfetto.protos.AndroidLmkReasonMetric.Process} Process
                 * @throws {Error} If the payload is not a reader or valid buffer
                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
                 */
                Process.decodeDelimited = function decodeDelimited(reader) {
                    if (!(reader instanceof $Reader))
                        reader = new $Reader(reader);
                    return this.decode(reader, reader.uint32());
                };

                /**
                 * Verifies a Process message.
                 * @function verify
                 * @memberof perfetto.protos.AndroidLmkReasonMetric.Process
                 * @static
                 * @param {Object.<string,*>} message Plain object to verify
                 * @returns {string|null} `null` if valid, otherwise the reason why it is not
                 */
                Process.verify = function verify(message) {
                    if (typeof message !== "object" || message === null)
                        return "object expected";
                    if (message.process != null && message.hasOwnProperty("process")) {
                        var error = $root.perfetto.protos.AndroidProcessMetadata.verify(message.process);
                        if (error)
                            return "process." + error;
                    }
                    if (message.oomScoreAdj != null && message.hasOwnProperty("oomScoreAdj"))
                        if (!$util.isInteger(message.oomScoreAdj))
                            return "oomScoreAdj: integer expected";
                    if (message.size != null && message.hasOwnProperty("size"))
                        if (!$util.isInteger(message.size) && !(message.size && $util.isInteger(message.size.low) && $util.isInteger(message.size.high)))
                            return "size: integer|Long expected";
                    if (message.fileRssBytes != null && message.hasOwnProperty("fileRssBytes"))
                        if (!$util.isInteger(message.fileRssBytes) && !(message.fileRssBytes && $util.isInteger(message.fileRssBytes.low) && $util.isInteger(message.fileRssBytes.high)))
                            return "fileRssBytes: integer|Long expected";
                    if (message.anonRssBytes != null && message.hasOwnProperty("anonRssBytes"))
                        if (!$util.isInteger(message.anonRssBytes) && !(message.anonRssBytes && $util.isInteger(message.anonRssBytes.low) && $util.isInteger(message.anonRssBytes.high)))
                            return "anonRssBytes: integer|Long expected";
                    if (message.shmemRssBytes != null && message.hasOwnProperty("shmemRssBytes"))
                        if (!$util.isInteger(message.shmemRssBytes) && !(message.shmemRssBytes && $util.isInteger(message.shmemRssBytes.low) && $util.isInteger(message.shmemRssBytes.high)))
                            return "shmemRssBytes: integer|Long expected";
                    if (message.swapBytes != null && message.hasOwnProperty("swapBytes"))
                        if (!$util.isInteger(message.swapBytes) && !(message.swapBytes && $util.isInteger(message.swapBytes.low) && $util.isInteger(message.swapBytes.high)))
                            return "swapBytes: integer|Long expected";
                    return null;
                };

                /**
                 * Creates a Process message from a plain object. Also converts values to their respective internal types.
                 * @function fromObject
                 * @memberof perfetto.protos.AndroidLmkReasonMetric.Process
                 * @static
                 * @param {Object.<string,*>} object Plain object
                 * @returns {perfetto.protos.AndroidLmkReasonMetric.Process} Process
                 */
                Process.fromObject = function fromObject(object) {
                    if (object instanceof $root.perfetto.protos.AndroidLmkReasonMetric.Process)
                        return object;
                    var message = new $root.perfetto.protos.AndroidLmkReasonMetric.Process();
                    if (object.process != null) {
                        if (typeof object.process !== "object")
                            throw TypeError(".perfetto.protos.AndroidLmkReasonMetric.Process.process: object expected");
                        message.process = $root.perfetto.protos.AndroidProcessMetadata.fromObject(object.process);
                    }
                    if (object.oomScoreAdj != null)
                        message.oomScoreAdj = object.oomScoreAdj | 0;
                    if (object.size != null)
                        if ($util.Long)
                            (message.size = $util.Long.fromValue(object.size)).unsigned = false;
                        else if (typeof object.size === "string")
                            message.size = parseInt(object.size, 10);
                        else if (typeof object.size === "number")
                            message.size = object.size;
                        else if (typeof object.size === "object")
                            message.size = new $util.LongBits(object.size.low >>> 0, object.size.high >>> 0).toNumber();
                    if (object.fileRssBytes != null)
                        if ($util.Long)
                            (message.fileRssBytes = $util.Long.fromValue(object.fileRssBytes)).unsigned = false;
                        else if (typeof object.fileRssBytes === "string")
                            message.fileRssBytes = parseInt(object.fileRssBytes, 10);
                        else if (typeof object.fileRssBytes === "number")
                            message.fileRssBytes = object.fileRssBytes;
                        else if (typeof object.fileRssBytes === "object")
                            message.fileRssBytes = new $util.LongBits(object.fileRssBytes.low >>> 0, object.fileRssBytes.high >>> 0).toNumber();
                    if (object.anonRssBytes != null)
                        if ($util.Long)
                            (message.anonRssBytes = $util.Long.fromValue(object.anonRssBytes)).unsigned = false;
                        else if (typeof object.anonRssBytes === "string")
                            message.anonRssBytes = parseInt(object.anonRssBytes, 10);
                        else if (typeof object.anonRssBytes === "number")
                            message.anonRssBytes = object.anonRssBytes;
                        else if (typeof object.anonRssBytes === "object")
                            message.anonRssBytes = new $util.LongBits(object.anonRssBytes.low >>> 0, object.anonRssBytes.high >>> 0).toNumber();
                    if (object.shmemRssBytes != null)
                        if ($util.Long)
                            (message.shmemRssBytes = $util.Long.fromValue(object.shmemRssBytes)).unsigned = false;
                        else if (typeof object.shmemRssBytes === "string")
                            message.shmemRssBytes = parseInt(object.shmemRssBytes, 10);
                        else if (typeof object.shmemRssBytes === "number")
                            message.shmemRssBytes = object.shmemRssBytes;
                        else if (typeof object.shmemRssBytes === "object")
                            message.shmemRssBytes = new $util.LongBits(object.shmemRssBytes.low >>> 0, object.shmemRssBytes.high >>> 0).toNumber();
                    if (object.swapBytes != null)
                        if ($util.Long)
                            (message.swapBytes = $util.Long.fromValue(object.swapBytes)).unsigned = false;
                        else if (typeof object.swapBytes === "string")
                            message.swapBytes = parseInt(object.swapBytes, 10);
                        else if (typeof object.swapBytes === "number")
                            message.swapBytes = object.swapBytes;
                        else if (typeof object.swapBytes === "object")
                            message.swapBytes = new $util.LongBits(object.swapBytes.low >>> 0, object.swapBytes.high >>> 0).toNumber();
                    return message;
                };

                /**
                 * Creates a plain object from a Process message. Also converts values to other types if specified.
                 * @function toObject
                 * @memberof perfetto.protos.AndroidLmkReasonMetric.Process
                 * @static
                 * @param {perfetto.protos.AndroidLmkReasonMetric.Process} message Process
                 * @param {$protobuf.IConversionOptions} [options] Conversion options
                 * @returns {Object.<string,*>} Plain object
                 */
                Process.toObject = function toObject(message, options) {
                    if (!options)
                        options = {};
                    var object = {};
                    if (options.defaults) {
                        object.process = null;
                        object.oomScoreAdj = 0;
                        if ($util.Long) {
                            var long = new $util.Long(0, 0, false);
                            object.size = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
                        } else
                            object.size = options.longs === String ? "0" : 0;
                        if ($util.Long) {
                            var long = new $util.Long(0, 0, false);
                            object.fileRssBytes = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
                        } else
                            object.fileRssBytes = options.longs === String ? "0" : 0;
                        if ($util.Long) {
                            var long = new $util.Long(0, 0, false);
                            object.anonRssBytes = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
                        } else
                            object.anonRssBytes = options.longs === String ? "0" : 0;
                        if ($util.Long) {
                            var long = new $util.Long(0, 0, false);
                            object.shmemRssBytes = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
                        } else
                            object.shmemRssBytes = options.longs === String ? "0" : 0;
                        if ($util.Long) {
                            var long = new $util.Long(0, 0, false);
                            object.swapBytes = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
                        } else
                            object.swapBytes = options.longs === String ? "0" : 0;
                    }
                    if (message.process != null && message.hasOwnProperty("process"))
                        object.process = $root.perfetto.protos.AndroidProcessMetadata.toObject(message.process, options);
                    if (message.oomScoreAdj != null && message.hasOwnProperty("oomScoreAdj"))
                        object.oomScoreAdj = message.oomScoreAdj;
                    if (message.size != null && message.hasOwnProperty("size"))
                        if (typeof message.size === "number")
                            object.size = options.longs === String ? String(message.size) : message.size;
                        else
                            object.size = options.longs === String ? $util.Long.prototype.toString.call(message.size) : options.longs === Number ? new $util.LongBits(message.size.low >>> 0, message.size.high >>> 0).toNumber() : message.size;
                    if (message.fileRssBytes != null && message.hasOwnProperty("fileRssBytes"))
                        if (typeof message.fileRssBytes === "number")
                            object.fileRssBytes = options.longs === String ? String(message.fileRssBytes) : message.fileRssBytes;
                        else
                            object.fileRssBytes = options.longs === String ? $util.Long.prototype.toString.call(message.fileRssBytes) : options.longs === Number ? new $util.LongBits(message.fileRssBytes.low >>> 0, message.fileRssBytes.high >>> 0).toNumber() : message.fileRssBytes;
                    if (message.anonRssBytes != null && message.hasOwnProperty("anonRssBytes"))
                        if (typeof message.anonRssBytes === "number")
                            object.anonRssBytes = options.longs === String ? String(message.anonRssBytes) : message.anonRssBytes;
                        else
                            object.anonRssBytes = options.longs === String ? $util.Long.prototype.toString.call(message.anonRssBytes) : options.longs === Number ? new $util.LongBits(message.anonRssBytes.low >>> 0, message.anonRssBytes.high >>> 0).toNumber() : message.anonRssBytes;
                    if (message.shmemRssBytes != null && message.hasOwnProperty("shmemRssBytes"))
                        if (typeof message.shmemRssBytes === "number")
                            object.shmemRssBytes = options.longs === String ? String(message.shmemRssBytes) : message.shmemRssBytes;
                        else
                            object.shmemRssBytes = options.longs === String ? $util.Long.prototype.toString.call(message.shmemRssBytes) : options.longs === Number ? new $util.LongBits(message.shmemRssBytes.low >>> 0, message.shmemRssBytes.high >>> 0).toNumber() : message.shmemRssBytes;
                    if (message.swapBytes != null && message.hasOwnProperty("swapBytes"))
                        if (typeof message.swapBytes === "number")
                            object.swapBytes = options.longs === String ? String(message.swapBytes) : message.swapBytes;
                        else
                            object.swapBytes = options.longs === String ? $util.Long.prototype.toString.call(message.swapBytes) : options.longs === Number ? new $util.LongBits(message.swapBytes.low >>> 0, message.swapBytes.high >>> 0).toNumber() : message.swapBytes;
                    return object;
                };

                /**
                 * Converts this Process to JSON.
                 * @function toJSON
                 * @memberof perfetto.protos.AndroidLmkReasonMetric.Process
                 * @instance
                 * @returns {Object.<string,*>} JSON object
                 */
                Process.prototype.toJSON = function toJSON() {
                    return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
                };

                return Process;
            })();

            AndroidLmkReasonMetric.Lmk = (function() {

                /**
                 * Properties of a Lmk.
                 * @memberof perfetto.protos.AndroidLmkReasonMetric
                 * @interface ILmk
                 * @property {number|null} [oomScoreAdj] Lmk oomScoreAdj
                 * @property {number|null} [ionHeapsBytes] Lmk ionHeapsBytes
                 * @property {number|null} [systemIonHeapSize] Lmk systemIonHeapSize
                 * @property {Array.<perfetto.protos.AndroidLmkReasonMetric.IProcess>|null} [processes] Lmk processes
                 */

                /**
                 * Constructs a new Lmk.
                 * @memberof perfetto.protos.AndroidLmkReasonMetric
                 * @classdesc Represents a Lmk.
                 * @implements ILmk
                 * @constructor
                 * @param {perfetto.protos.AndroidLmkReasonMetric.ILmk=} [properties] Properties to set
                 */
                function Lmk(properties) {
                    this.processes = [];
                    if (properties)
                        for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                            if (properties[keys[i]] != null)
                                this[keys[i]] = properties[keys[i]];
                }

                /**
                 * Lmk oomScoreAdj.
                 * @member {number} oomScoreAdj
                 * @memberof perfetto.protos.AndroidLmkReasonMetric.Lmk
                 * @instance
                 */
                Lmk.prototype.oomScoreAdj = 0;

                /**
                 * Lmk ionHeapsBytes.
                 * @member {number} ionHeapsBytes
                 * @memberof perfetto.protos.AndroidLmkReasonMetric.Lmk
                 * @instance
                 */
                Lmk.prototype.ionHeapsBytes = $util.Long ? $util.Long.fromBits(0,0,false) : 0;

                /**
                 * Lmk systemIonHeapSize.
                 * @member {number} systemIonHeapSize
                 * @memberof perfetto.protos.AndroidLmkReasonMetric.Lmk
                 * @instance
                 */
                Lmk.prototype.systemIonHeapSize = $util.Long ? $util.Long.fromBits(0,0,false) : 0;

                /**
                 * Lmk processes.
                 * @member {Array.<perfetto.protos.AndroidLmkReasonMetric.IProcess>} processes
                 * @memberof perfetto.protos.AndroidLmkReasonMetric.Lmk
                 * @instance
                 */
                Lmk.prototype.processes = $util.emptyArray;

                /**
                 * Creates a new Lmk instance using the specified properties.
                 * @function create
                 * @memberof perfetto.protos.AndroidLmkReasonMetric.Lmk
                 * @static
                 * @param {perfetto.protos.AndroidLmkReasonMetric.ILmk=} [properties] Properties to set
                 * @returns {perfetto.protos.AndroidLmkReasonMetric.Lmk} Lmk instance
                 */
                Lmk.create = function create(properties) {
                    return new Lmk(properties);
                };

                /**
                 * Encodes the specified Lmk message. Does not implicitly {@link perfetto.protos.AndroidLmkReasonMetric.Lmk.verify|verify} messages.
                 * @function encode
                 * @memberof perfetto.protos.AndroidLmkReasonMetric.Lmk
                 * @static
                 * @param {perfetto.protos.AndroidLmkReasonMetric.ILmk} message Lmk message or plain object to encode
                 * @param {$protobuf.Writer} [writer] Writer to encode to
                 * @returns {$protobuf.Writer} Writer
                 */
                Lmk.encode = function encode(message, writer) {
                    if (!writer)
                        writer = $Writer.create();
                    if (message.oomScoreAdj != null && Object.hasOwnProperty.call(message, "oomScoreAdj"))
                        writer.uint32(/* id 1, wireType 0 =*/8).int32(message.oomScoreAdj);
                    if (message.systemIonHeapSize != null && Object.hasOwnProperty.call(message, "systemIonHeapSize"))
                        writer.uint32(/* id 2, wireType 0 =*/16).int64(message.systemIonHeapSize);
                    if (message.processes != null && message.processes.length)
                        for (var i = 0; i < message.processes.length; ++i)
                            $root.perfetto.protos.AndroidLmkReasonMetric.Process.encode(message.processes[i], writer.uint32(/* id 3, wireType 2 =*/26).fork()).ldelim();
                    if (message.ionHeapsBytes != null && Object.hasOwnProperty.call(message, "ionHeapsBytes"))
                        writer.uint32(/* id 4, wireType 0 =*/32).int64(message.ionHeapsBytes);
                    return writer;
                };

                /**
                 * Encodes the specified Lmk message, length delimited. Does not implicitly {@link perfetto.protos.AndroidLmkReasonMetric.Lmk.verify|verify} messages.
                 * @function encodeDelimited
                 * @memberof perfetto.protos.AndroidLmkReasonMetric.Lmk
                 * @static
                 * @param {perfetto.protos.AndroidLmkReasonMetric.ILmk} message Lmk message or plain object to encode
                 * @param {$protobuf.Writer} [writer] Writer to encode to
                 * @returns {$protobuf.Writer} Writer
                 */
                Lmk.encodeDelimited = function encodeDelimited(message, writer) {
                    return this.encode(message, writer).ldelim();
                };

                /**
                 * Decodes a Lmk message from the specified reader or buffer.
                 * @function decode
                 * @memberof perfetto.protos.AndroidLmkReasonMetric.Lmk
                 * @static
                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                 * @param {number} [length] Message length if known beforehand
                 * @returns {perfetto.protos.AndroidLmkReasonMetric.Lmk} Lmk
                 * @throws {Error} If the payload is not a reader or valid buffer
                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
                 */
                Lmk.decode = function decode(reader, length) {
                    if (!(reader instanceof $Reader))
                        reader = $Reader.create(reader);
                    var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.AndroidLmkReasonMetric.Lmk();
                    while (reader.pos < end) {
                        var tag = reader.uint32();
                        switch (tag >>> 3) {
                        case 1:
                            message.oomScoreAdj = reader.int32();
                            break;
                        case 4:
                            message.ionHeapsBytes = reader.int64();
                            break;
                        case 2:
                            message.systemIonHeapSize = reader.int64();
                            break;
                        case 3:
                            if (!(message.processes && message.processes.length))
                                message.processes = [];
                            message.processes.push($root.perfetto.protos.AndroidLmkReasonMetric.Process.decode(reader, reader.uint32()));
                            break;
                        default:
                            reader.skipType(tag & 7);
                            break;
                        }
                    }
                    return message;
                };

                /**
                 * Decodes a Lmk message from the specified reader or buffer, length delimited.
                 * @function decodeDelimited
                 * @memberof perfetto.protos.AndroidLmkReasonMetric.Lmk
                 * @static
                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                 * @returns {perfetto.protos.AndroidLmkReasonMetric.Lmk} Lmk
                 * @throws {Error} If the payload is not a reader or valid buffer
                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
                 */
                Lmk.decodeDelimited = function decodeDelimited(reader) {
                    if (!(reader instanceof $Reader))
                        reader = new $Reader(reader);
                    return this.decode(reader, reader.uint32());
                };

                /**
                 * Verifies a Lmk message.
                 * @function verify
                 * @memberof perfetto.protos.AndroidLmkReasonMetric.Lmk
                 * @static
                 * @param {Object.<string,*>} message Plain object to verify
                 * @returns {string|null} `null` if valid, otherwise the reason why it is not
                 */
                Lmk.verify = function verify(message) {
                    if (typeof message !== "object" || message === null)
                        return "object expected";
                    if (message.oomScoreAdj != null && message.hasOwnProperty("oomScoreAdj"))
                        if (!$util.isInteger(message.oomScoreAdj))
                            return "oomScoreAdj: integer expected";
                    if (message.ionHeapsBytes != null && message.hasOwnProperty("ionHeapsBytes"))
                        if (!$util.isInteger(message.ionHeapsBytes) && !(message.ionHeapsBytes && $util.isInteger(message.ionHeapsBytes.low) && $util.isInteger(message.ionHeapsBytes.high)))
                            return "ionHeapsBytes: integer|Long expected";
                    if (message.systemIonHeapSize != null && message.hasOwnProperty("systemIonHeapSize"))
                        if (!$util.isInteger(message.systemIonHeapSize) && !(message.systemIonHeapSize && $util.isInteger(message.systemIonHeapSize.low) && $util.isInteger(message.systemIonHeapSize.high)))
                            return "systemIonHeapSize: integer|Long expected";
                    if (message.processes != null && message.hasOwnProperty("processes")) {
                        if (!Array.isArray(message.processes))
                            return "processes: array expected";
                        for (var i = 0; i < message.processes.length; ++i) {
                            var error = $root.perfetto.protos.AndroidLmkReasonMetric.Process.verify(message.processes[i]);
                            if (error)
                                return "processes." + error;
                        }
                    }
                    return null;
                };

                /**
                 * Creates a Lmk message from a plain object. Also converts values to their respective internal types.
                 * @function fromObject
                 * @memberof perfetto.protos.AndroidLmkReasonMetric.Lmk
                 * @static
                 * @param {Object.<string,*>} object Plain object
                 * @returns {perfetto.protos.AndroidLmkReasonMetric.Lmk} Lmk
                 */
                Lmk.fromObject = function fromObject(object) {
                    if (object instanceof $root.perfetto.protos.AndroidLmkReasonMetric.Lmk)
                        return object;
                    var message = new $root.perfetto.protos.AndroidLmkReasonMetric.Lmk();
                    if (object.oomScoreAdj != null)
                        message.oomScoreAdj = object.oomScoreAdj | 0;
                    if (object.ionHeapsBytes != null)
                        if ($util.Long)
                            (message.ionHeapsBytes = $util.Long.fromValue(object.ionHeapsBytes)).unsigned = false;
                        else if (typeof object.ionHeapsBytes === "string")
                            message.ionHeapsBytes = parseInt(object.ionHeapsBytes, 10);
                        else if (typeof object.ionHeapsBytes === "number")
                            message.ionHeapsBytes = object.ionHeapsBytes;
                        else if (typeof object.ionHeapsBytes === "object")
                            message.ionHeapsBytes = new $util.LongBits(object.ionHeapsBytes.low >>> 0, object.ionHeapsBytes.high >>> 0).toNumber();
                    if (object.systemIonHeapSize != null)
                        if ($util.Long)
                            (message.systemIonHeapSize = $util.Long.fromValue(object.systemIonHeapSize)).unsigned = false;
                        else if (typeof object.systemIonHeapSize === "string")
                            message.systemIonHeapSize = parseInt(object.systemIonHeapSize, 10);
                        else if (typeof object.systemIonHeapSize === "number")
                            message.systemIonHeapSize = object.systemIonHeapSize;
                        else if (typeof object.systemIonHeapSize === "object")
                            message.systemIonHeapSize = new $util.LongBits(object.systemIonHeapSize.low >>> 0, object.systemIonHeapSize.high >>> 0).toNumber();
                    if (object.processes) {
                        if (!Array.isArray(object.processes))
                            throw TypeError(".perfetto.protos.AndroidLmkReasonMetric.Lmk.processes: array expected");
                        message.processes = [];
                        for (var i = 0; i < object.processes.length; ++i) {
                            if (typeof object.processes[i] !== "object")
                                throw TypeError(".perfetto.protos.AndroidLmkReasonMetric.Lmk.processes: object expected");
                            message.processes[i] = $root.perfetto.protos.AndroidLmkReasonMetric.Process.fromObject(object.processes[i]);
                        }
                    }
                    return message;
                };

                /**
                 * Creates a plain object from a Lmk message. Also converts values to other types if specified.
                 * @function toObject
                 * @memberof perfetto.protos.AndroidLmkReasonMetric.Lmk
                 * @static
                 * @param {perfetto.protos.AndroidLmkReasonMetric.Lmk} message Lmk
                 * @param {$protobuf.IConversionOptions} [options] Conversion options
                 * @returns {Object.<string,*>} Plain object
                 */
                Lmk.toObject = function toObject(message, options) {
                    if (!options)
                        options = {};
                    var object = {};
                    if (options.arrays || options.defaults)
                        object.processes = [];
                    if (options.defaults) {
                        object.oomScoreAdj = 0;
                        if ($util.Long) {
                            var long = new $util.Long(0, 0, false);
                            object.systemIonHeapSize = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
                        } else
                            object.systemIonHeapSize = options.longs === String ? "0" : 0;
                        if ($util.Long) {
                            var long = new $util.Long(0, 0, false);
                            object.ionHeapsBytes = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
                        } else
                            object.ionHeapsBytes = options.longs === String ? "0" : 0;
                    }
                    if (message.oomScoreAdj != null && message.hasOwnProperty("oomScoreAdj"))
                        object.oomScoreAdj = message.oomScoreAdj;
                    if (message.systemIonHeapSize != null && message.hasOwnProperty("systemIonHeapSize"))
                        if (typeof message.systemIonHeapSize === "number")
                            object.systemIonHeapSize = options.longs === String ? String(message.systemIonHeapSize) : message.systemIonHeapSize;
                        else
                            object.systemIonHeapSize = options.longs === String ? $util.Long.prototype.toString.call(message.systemIonHeapSize) : options.longs === Number ? new $util.LongBits(message.systemIonHeapSize.low >>> 0, message.systemIonHeapSize.high >>> 0).toNumber() : message.systemIonHeapSize;
                    if (message.processes && message.processes.length) {
                        object.processes = [];
                        for (var j = 0; j < message.processes.length; ++j)
                            object.processes[j] = $root.perfetto.protos.AndroidLmkReasonMetric.Process.toObject(message.processes[j], options);
                    }
                    if (message.ionHeapsBytes != null && message.hasOwnProperty("ionHeapsBytes"))
                        if (typeof message.ionHeapsBytes === "number")
                            object.ionHeapsBytes = options.longs === String ? String(message.ionHeapsBytes) : message.ionHeapsBytes;
                        else
                            object.ionHeapsBytes = options.longs === String ? $util.Long.prototype.toString.call(message.ionHeapsBytes) : options.longs === Number ? new $util.LongBits(message.ionHeapsBytes.low >>> 0, message.ionHeapsBytes.high >>> 0).toNumber() : message.ionHeapsBytes;
                    return object;
                };

                /**
                 * Converts this Lmk to JSON.
                 * @function toJSON
                 * @memberof perfetto.protos.AndroidLmkReasonMetric.Lmk
                 * @instance
                 * @returns {Object.<string,*>} JSON object
                 */
                Lmk.prototype.toJSON = function toJSON() {
                    return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
                };

                return Lmk;
            })();

            return AndroidLmkReasonMetric;
        })();

        protos.AndroidMemoryMetric = (function() {

            /**
             * Properties of an AndroidMemoryMetric.
             * @memberof perfetto.protos
             * @interface IAndroidMemoryMetric
             * @property {Array.<perfetto.protos.AndroidMemoryMetric.IProcessMetrics>|null} [processMetrics] AndroidMemoryMetric processMetrics
             */

            /**
             * Constructs a new AndroidMemoryMetric.
             * @memberof perfetto.protos
             * @classdesc Represents an AndroidMemoryMetric.
             * @implements IAndroidMemoryMetric
             * @constructor
             * @param {perfetto.protos.IAndroidMemoryMetric=} [properties] Properties to set
             */
            function AndroidMemoryMetric(properties) {
                this.processMetrics = [];
                if (properties)
                    for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                        if (properties[keys[i]] != null)
                            this[keys[i]] = properties[keys[i]];
            }

            /**
             * AndroidMemoryMetric processMetrics.
             * @member {Array.<perfetto.protos.AndroidMemoryMetric.IProcessMetrics>} processMetrics
             * @memberof perfetto.protos.AndroidMemoryMetric
             * @instance
             */
            AndroidMemoryMetric.prototype.processMetrics = $util.emptyArray;

            /**
             * Creates a new AndroidMemoryMetric instance using the specified properties.
             * @function create
             * @memberof perfetto.protos.AndroidMemoryMetric
             * @static
             * @param {perfetto.protos.IAndroidMemoryMetric=} [properties] Properties to set
             * @returns {perfetto.protos.AndroidMemoryMetric} AndroidMemoryMetric instance
             */
            AndroidMemoryMetric.create = function create(properties) {
                return new AndroidMemoryMetric(properties);
            };

            /**
             * Encodes the specified AndroidMemoryMetric message. Does not implicitly {@link perfetto.protos.AndroidMemoryMetric.verify|verify} messages.
             * @function encode
             * @memberof perfetto.protos.AndroidMemoryMetric
             * @static
             * @param {perfetto.protos.IAndroidMemoryMetric} message AndroidMemoryMetric message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            AndroidMemoryMetric.encode = function encode(message, writer) {
                if (!writer)
                    writer = $Writer.create();
                if (message.processMetrics != null && message.processMetrics.length)
                    for (var i = 0; i < message.processMetrics.length; ++i)
                        $root.perfetto.protos.AndroidMemoryMetric.ProcessMetrics.encode(message.processMetrics[i], writer.uint32(/* id 1, wireType 2 =*/10).fork()).ldelim();
                return writer;
            };

            /**
             * Encodes the specified AndroidMemoryMetric message, length delimited. Does not implicitly {@link perfetto.protos.AndroidMemoryMetric.verify|verify} messages.
             * @function encodeDelimited
             * @memberof perfetto.protos.AndroidMemoryMetric
             * @static
             * @param {perfetto.protos.IAndroidMemoryMetric} message AndroidMemoryMetric message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            AndroidMemoryMetric.encodeDelimited = function encodeDelimited(message, writer) {
                return this.encode(message, writer).ldelim();
            };

            /**
             * Decodes an AndroidMemoryMetric message from the specified reader or buffer.
             * @function decode
             * @memberof perfetto.protos.AndroidMemoryMetric
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @param {number} [length] Message length if known beforehand
             * @returns {perfetto.protos.AndroidMemoryMetric} AndroidMemoryMetric
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            AndroidMemoryMetric.decode = function decode(reader, length) {
                if (!(reader instanceof $Reader))
                    reader = $Reader.create(reader);
                var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.AndroidMemoryMetric();
                while (reader.pos < end) {
                    var tag = reader.uint32();
                    switch (tag >>> 3) {
                    case 1:
                        if (!(message.processMetrics && message.processMetrics.length))
                            message.processMetrics = [];
                        message.processMetrics.push($root.perfetto.protos.AndroidMemoryMetric.ProcessMetrics.decode(reader, reader.uint32()));
                        break;
                    default:
                        reader.skipType(tag & 7);
                        break;
                    }
                }
                return message;
            };

            /**
             * Decodes an AndroidMemoryMetric message from the specified reader or buffer, length delimited.
             * @function decodeDelimited
             * @memberof perfetto.protos.AndroidMemoryMetric
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @returns {perfetto.protos.AndroidMemoryMetric} AndroidMemoryMetric
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            AndroidMemoryMetric.decodeDelimited = function decodeDelimited(reader) {
                if (!(reader instanceof $Reader))
                    reader = new $Reader(reader);
                return this.decode(reader, reader.uint32());
            };

            /**
             * Verifies an AndroidMemoryMetric message.
             * @function verify
             * @memberof perfetto.protos.AndroidMemoryMetric
             * @static
             * @param {Object.<string,*>} message Plain object to verify
             * @returns {string|null} `null` if valid, otherwise the reason why it is not
             */
            AndroidMemoryMetric.verify = function verify(message) {
                if (typeof message !== "object" || message === null)
                    return "object expected";
                if (message.processMetrics != null && message.hasOwnProperty("processMetrics")) {
                    if (!Array.isArray(message.processMetrics))
                        return "processMetrics: array expected";
                    for (var i = 0; i < message.processMetrics.length; ++i) {
                        var error = $root.perfetto.protos.AndroidMemoryMetric.ProcessMetrics.verify(message.processMetrics[i]);
                        if (error)
                            return "processMetrics." + error;
                    }
                }
                return null;
            };

            /**
             * Creates an AndroidMemoryMetric message from a plain object. Also converts values to their respective internal types.
             * @function fromObject
             * @memberof perfetto.protos.AndroidMemoryMetric
             * @static
             * @param {Object.<string,*>} object Plain object
             * @returns {perfetto.protos.AndroidMemoryMetric} AndroidMemoryMetric
             */
            AndroidMemoryMetric.fromObject = function fromObject(object) {
                if (object instanceof $root.perfetto.protos.AndroidMemoryMetric)
                    return object;
                var message = new $root.perfetto.protos.AndroidMemoryMetric();
                if (object.processMetrics) {
                    if (!Array.isArray(object.processMetrics))
                        throw TypeError(".perfetto.protos.AndroidMemoryMetric.processMetrics: array expected");
                    message.processMetrics = [];
                    for (var i = 0; i < object.processMetrics.length; ++i) {
                        if (typeof object.processMetrics[i] !== "object")
                            throw TypeError(".perfetto.protos.AndroidMemoryMetric.processMetrics: object expected");
                        message.processMetrics[i] = $root.perfetto.protos.AndroidMemoryMetric.ProcessMetrics.fromObject(object.processMetrics[i]);
                    }
                }
                return message;
            };

            /**
             * Creates a plain object from an AndroidMemoryMetric message. Also converts values to other types if specified.
             * @function toObject
             * @memberof perfetto.protos.AndroidMemoryMetric
             * @static
             * @param {perfetto.protos.AndroidMemoryMetric} message AndroidMemoryMetric
             * @param {$protobuf.IConversionOptions} [options] Conversion options
             * @returns {Object.<string,*>} Plain object
             */
            AndroidMemoryMetric.toObject = function toObject(message, options) {
                if (!options)
                    options = {};
                var object = {};
                if (options.arrays || options.defaults)
                    object.processMetrics = [];
                if (message.processMetrics && message.processMetrics.length) {
                    object.processMetrics = [];
                    for (var j = 0; j < message.processMetrics.length; ++j)
                        object.processMetrics[j] = $root.perfetto.protos.AndroidMemoryMetric.ProcessMetrics.toObject(message.processMetrics[j], options);
                }
                return object;
            };

            /**
             * Converts this AndroidMemoryMetric to JSON.
             * @function toJSON
             * @memberof perfetto.protos.AndroidMemoryMetric
             * @instance
             * @returns {Object.<string,*>} JSON object
             */
            AndroidMemoryMetric.prototype.toJSON = function toJSON() {
                return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
            };

            AndroidMemoryMetric.ProcessMetrics = (function() {

                /**
                 * Properties of a ProcessMetrics.
                 * @memberof perfetto.protos.AndroidMemoryMetric
                 * @interface IProcessMetrics
                 * @property {string|null} [processName] ProcessMetrics processName
                 * @property {perfetto.protos.AndroidMemoryMetric.IProcessMemoryCounters|null} [totalCounters] ProcessMetrics totalCounters
                 * @property {Array.<perfetto.protos.AndroidMemoryMetric.IPriorityBreakdown>|null} [priorityBreakdown] ProcessMetrics priorityBreakdown
                 */

                /**
                 * Constructs a new ProcessMetrics.
                 * @memberof perfetto.protos.AndroidMemoryMetric
                 * @classdesc Represents a ProcessMetrics.
                 * @implements IProcessMetrics
                 * @constructor
                 * @param {perfetto.protos.AndroidMemoryMetric.IProcessMetrics=} [properties] Properties to set
                 */
                function ProcessMetrics(properties) {
                    this.priorityBreakdown = [];
                    if (properties)
                        for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                            if (properties[keys[i]] != null)
                                this[keys[i]] = properties[keys[i]];
                }

                /**
                 * ProcessMetrics processName.
                 * @member {string} processName
                 * @memberof perfetto.protos.AndroidMemoryMetric.ProcessMetrics
                 * @instance
                 */
                ProcessMetrics.prototype.processName = "";

                /**
                 * ProcessMetrics totalCounters.
                 * @member {perfetto.protos.AndroidMemoryMetric.IProcessMemoryCounters|null|undefined} totalCounters
                 * @memberof perfetto.protos.AndroidMemoryMetric.ProcessMetrics
                 * @instance
                 */
                ProcessMetrics.prototype.totalCounters = null;

                /**
                 * ProcessMetrics priorityBreakdown.
                 * @member {Array.<perfetto.protos.AndroidMemoryMetric.IPriorityBreakdown>} priorityBreakdown
                 * @memberof perfetto.protos.AndroidMemoryMetric.ProcessMetrics
                 * @instance
                 */
                ProcessMetrics.prototype.priorityBreakdown = $util.emptyArray;

                /**
                 * Creates a new ProcessMetrics instance using the specified properties.
                 * @function create
                 * @memberof perfetto.protos.AndroidMemoryMetric.ProcessMetrics
                 * @static
                 * @param {perfetto.protos.AndroidMemoryMetric.IProcessMetrics=} [properties] Properties to set
                 * @returns {perfetto.protos.AndroidMemoryMetric.ProcessMetrics} ProcessMetrics instance
                 */
                ProcessMetrics.create = function create(properties) {
                    return new ProcessMetrics(properties);
                };

                /**
                 * Encodes the specified ProcessMetrics message. Does not implicitly {@link perfetto.protos.AndroidMemoryMetric.ProcessMetrics.verify|verify} messages.
                 * @function encode
                 * @memberof perfetto.protos.AndroidMemoryMetric.ProcessMetrics
                 * @static
                 * @param {perfetto.protos.AndroidMemoryMetric.IProcessMetrics} message ProcessMetrics message or plain object to encode
                 * @param {$protobuf.Writer} [writer] Writer to encode to
                 * @returns {$protobuf.Writer} Writer
                 */
                ProcessMetrics.encode = function encode(message, writer) {
                    if (!writer)
                        writer = $Writer.create();
                    if (message.processName != null && Object.hasOwnProperty.call(message, "processName"))
                        writer.uint32(/* id 1, wireType 2 =*/10).string(message.processName);
                    if (message.totalCounters != null && Object.hasOwnProperty.call(message, "totalCounters"))
                        $root.perfetto.protos.AndroidMemoryMetric.ProcessMemoryCounters.encode(message.totalCounters, writer.uint32(/* id 2, wireType 2 =*/18).fork()).ldelim();
                    if (message.priorityBreakdown != null && message.priorityBreakdown.length)
                        for (var i = 0; i < message.priorityBreakdown.length; ++i)
                            $root.perfetto.protos.AndroidMemoryMetric.PriorityBreakdown.encode(message.priorityBreakdown[i], writer.uint32(/* id 3, wireType 2 =*/26).fork()).ldelim();
                    return writer;
                };

                /**
                 * Encodes the specified ProcessMetrics message, length delimited. Does not implicitly {@link perfetto.protos.AndroidMemoryMetric.ProcessMetrics.verify|verify} messages.
                 * @function encodeDelimited
                 * @memberof perfetto.protos.AndroidMemoryMetric.ProcessMetrics
                 * @static
                 * @param {perfetto.protos.AndroidMemoryMetric.IProcessMetrics} message ProcessMetrics message or plain object to encode
                 * @param {$protobuf.Writer} [writer] Writer to encode to
                 * @returns {$protobuf.Writer} Writer
                 */
                ProcessMetrics.encodeDelimited = function encodeDelimited(message, writer) {
                    return this.encode(message, writer).ldelim();
                };

                /**
                 * Decodes a ProcessMetrics message from the specified reader or buffer.
                 * @function decode
                 * @memberof perfetto.protos.AndroidMemoryMetric.ProcessMetrics
                 * @static
                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                 * @param {number} [length] Message length if known beforehand
                 * @returns {perfetto.protos.AndroidMemoryMetric.ProcessMetrics} ProcessMetrics
                 * @throws {Error} If the payload is not a reader or valid buffer
                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
                 */
                ProcessMetrics.decode = function decode(reader, length) {
                    if (!(reader instanceof $Reader))
                        reader = $Reader.create(reader);
                    var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.AndroidMemoryMetric.ProcessMetrics();
                    while (reader.pos < end) {
                        var tag = reader.uint32();
                        switch (tag >>> 3) {
                        case 1:
                            message.processName = reader.string();
                            break;
                        case 2:
                            message.totalCounters = $root.perfetto.protos.AndroidMemoryMetric.ProcessMemoryCounters.decode(reader, reader.uint32());
                            break;
                        case 3:
                            if (!(message.priorityBreakdown && message.priorityBreakdown.length))
                                message.priorityBreakdown = [];
                            message.priorityBreakdown.push($root.perfetto.protos.AndroidMemoryMetric.PriorityBreakdown.decode(reader, reader.uint32()));
                            break;
                        default:
                            reader.skipType(tag & 7);
                            break;
                        }
                    }
                    return message;
                };

                /**
                 * Decodes a ProcessMetrics message from the specified reader or buffer, length delimited.
                 * @function decodeDelimited
                 * @memberof perfetto.protos.AndroidMemoryMetric.ProcessMetrics
                 * @static
                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                 * @returns {perfetto.protos.AndroidMemoryMetric.ProcessMetrics} ProcessMetrics
                 * @throws {Error} If the payload is not a reader or valid buffer
                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
                 */
                ProcessMetrics.decodeDelimited = function decodeDelimited(reader) {
                    if (!(reader instanceof $Reader))
                        reader = new $Reader(reader);
                    return this.decode(reader, reader.uint32());
                };

                /**
                 * Verifies a ProcessMetrics message.
                 * @function verify
                 * @memberof perfetto.protos.AndroidMemoryMetric.ProcessMetrics
                 * @static
                 * @param {Object.<string,*>} message Plain object to verify
                 * @returns {string|null} `null` if valid, otherwise the reason why it is not
                 */
                ProcessMetrics.verify = function verify(message) {
                    if (typeof message !== "object" || message === null)
                        return "object expected";
                    if (message.processName != null && message.hasOwnProperty("processName"))
                        if (!$util.isString(message.processName))
                            return "processName: string expected";
                    if (message.totalCounters != null && message.hasOwnProperty("totalCounters")) {
                        var error = $root.perfetto.protos.AndroidMemoryMetric.ProcessMemoryCounters.verify(message.totalCounters);
                        if (error)
                            return "totalCounters." + error;
                    }
                    if (message.priorityBreakdown != null && message.hasOwnProperty("priorityBreakdown")) {
                        if (!Array.isArray(message.priorityBreakdown))
                            return "priorityBreakdown: array expected";
                        for (var i = 0; i < message.priorityBreakdown.length; ++i) {
                            var error = $root.perfetto.protos.AndroidMemoryMetric.PriorityBreakdown.verify(message.priorityBreakdown[i]);
                            if (error)
                                return "priorityBreakdown." + error;
                        }
                    }
                    return null;
                };

                /**
                 * Creates a ProcessMetrics message from a plain object. Also converts values to their respective internal types.
                 * @function fromObject
                 * @memberof perfetto.protos.AndroidMemoryMetric.ProcessMetrics
                 * @static
                 * @param {Object.<string,*>} object Plain object
                 * @returns {perfetto.protos.AndroidMemoryMetric.ProcessMetrics} ProcessMetrics
                 */
                ProcessMetrics.fromObject = function fromObject(object) {
                    if (object instanceof $root.perfetto.protos.AndroidMemoryMetric.ProcessMetrics)
                        return object;
                    var message = new $root.perfetto.protos.AndroidMemoryMetric.ProcessMetrics();
                    if (object.processName != null)
                        message.processName = String(object.processName);
                    if (object.totalCounters != null) {
                        if (typeof object.totalCounters !== "object")
                            throw TypeError(".perfetto.protos.AndroidMemoryMetric.ProcessMetrics.totalCounters: object expected");
                        message.totalCounters = $root.perfetto.protos.AndroidMemoryMetric.ProcessMemoryCounters.fromObject(object.totalCounters);
                    }
                    if (object.priorityBreakdown) {
                        if (!Array.isArray(object.priorityBreakdown))
                            throw TypeError(".perfetto.protos.AndroidMemoryMetric.ProcessMetrics.priorityBreakdown: array expected");
                        message.priorityBreakdown = [];
                        for (var i = 0; i < object.priorityBreakdown.length; ++i) {
                            if (typeof object.priorityBreakdown[i] !== "object")
                                throw TypeError(".perfetto.protos.AndroidMemoryMetric.ProcessMetrics.priorityBreakdown: object expected");
                            message.priorityBreakdown[i] = $root.perfetto.protos.AndroidMemoryMetric.PriorityBreakdown.fromObject(object.priorityBreakdown[i]);
                        }
                    }
                    return message;
                };

                /**
                 * Creates a plain object from a ProcessMetrics message. Also converts values to other types if specified.
                 * @function toObject
                 * @memberof perfetto.protos.AndroidMemoryMetric.ProcessMetrics
                 * @static
                 * @param {perfetto.protos.AndroidMemoryMetric.ProcessMetrics} message ProcessMetrics
                 * @param {$protobuf.IConversionOptions} [options] Conversion options
                 * @returns {Object.<string,*>} Plain object
                 */
                ProcessMetrics.toObject = function toObject(message, options) {
                    if (!options)
                        options = {};
                    var object = {};
                    if (options.arrays || options.defaults)
                        object.priorityBreakdown = [];
                    if (options.defaults) {
                        object.processName = "";
                        object.totalCounters = null;
                    }
                    if (message.processName != null && message.hasOwnProperty("processName"))
                        object.processName = message.processName;
                    if (message.totalCounters != null && message.hasOwnProperty("totalCounters"))
                        object.totalCounters = $root.perfetto.protos.AndroidMemoryMetric.ProcessMemoryCounters.toObject(message.totalCounters, options);
                    if (message.priorityBreakdown && message.priorityBreakdown.length) {
                        object.priorityBreakdown = [];
                        for (var j = 0; j < message.priorityBreakdown.length; ++j)
                            object.priorityBreakdown[j] = $root.perfetto.protos.AndroidMemoryMetric.PriorityBreakdown.toObject(message.priorityBreakdown[j], options);
                    }
                    return object;
                };

                /**
                 * Converts this ProcessMetrics to JSON.
                 * @function toJSON
                 * @memberof perfetto.protos.AndroidMemoryMetric.ProcessMetrics
                 * @instance
                 * @returns {Object.<string,*>} JSON object
                 */
                ProcessMetrics.prototype.toJSON = function toJSON() {
                    return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
                };

                return ProcessMetrics;
            })();

            AndroidMemoryMetric.PriorityBreakdown = (function() {

                /**
                 * Properties of a PriorityBreakdown.
                 * @memberof perfetto.protos.AndroidMemoryMetric
                 * @interface IPriorityBreakdown
                 * @property {string|null} [priority] PriorityBreakdown priority
                 * @property {perfetto.protos.AndroidMemoryMetric.IProcessMemoryCounters|null} [counters] PriorityBreakdown counters
                 */

                /**
                 * Constructs a new PriorityBreakdown.
                 * @memberof perfetto.protos.AndroidMemoryMetric
                 * @classdesc Represents a PriorityBreakdown.
                 * @implements IPriorityBreakdown
                 * @constructor
                 * @param {perfetto.protos.AndroidMemoryMetric.IPriorityBreakdown=} [properties] Properties to set
                 */
                function PriorityBreakdown(properties) {
                    if (properties)
                        for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                            if (properties[keys[i]] != null)
                                this[keys[i]] = properties[keys[i]];
                }

                /**
                 * PriorityBreakdown priority.
                 * @member {string} priority
                 * @memberof perfetto.protos.AndroidMemoryMetric.PriorityBreakdown
                 * @instance
                 */
                PriorityBreakdown.prototype.priority = "";

                /**
                 * PriorityBreakdown counters.
                 * @member {perfetto.protos.AndroidMemoryMetric.IProcessMemoryCounters|null|undefined} counters
                 * @memberof perfetto.protos.AndroidMemoryMetric.PriorityBreakdown
                 * @instance
                 */
                PriorityBreakdown.prototype.counters = null;

                /**
                 * Creates a new PriorityBreakdown instance using the specified properties.
                 * @function create
                 * @memberof perfetto.protos.AndroidMemoryMetric.PriorityBreakdown
                 * @static
                 * @param {perfetto.protos.AndroidMemoryMetric.IPriorityBreakdown=} [properties] Properties to set
                 * @returns {perfetto.protos.AndroidMemoryMetric.PriorityBreakdown} PriorityBreakdown instance
                 */
                PriorityBreakdown.create = function create(properties) {
                    return new PriorityBreakdown(properties);
                };

                /**
                 * Encodes the specified PriorityBreakdown message. Does not implicitly {@link perfetto.protos.AndroidMemoryMetric.PriorityBreakdown.verify|verify} messages.
                 * @function encode
                 * @memberof perfetto.protos.AndroidMemoryMetric.PriorityBreakdown
                 * @static
                 * @param {perfetto.protos.AndroidMemoryMetric.IPriorityBreakdown} message PriorityBreakdown message or plain object to encode
                 * @param {$protobuf.Writer} [writer] Writer to encode to
                 * @returns {$protobuf.Writer} Writer
                 */
                PriorityBreakdown.encode = function encode(message, writer) {
                    if (!writer)
                        writer = $Writer.create();
                    if (message.priority != null && Object.hasOwnProperty.call(message, "priority"))
                        writer.uint32(/* id 1, wireType 2 =*/10).string(message.priority);
                    if (message.counters != null && Object.hasOwnProperty.call(message, "counters"))
                        $root.perfetto.protos.AndroidMemoryMetric.ProcessMemoryCounters.encode(message.counters, writer.uint32(/* id 2, wireType 2 =*/18).fork()).ldelim();
                    return writer;
                };

                /**
                 * Encodes the specified PriorityBreakdown message, length delimited. Does not implicitly {@link perfetto.protos.AndroidMemoryMetric.PriorityBreakdown.verify|verify} messages.
                 * @function encodeDelimited
                 * @memberof perfetto.protos.AndroidMemoryMetric.PriorityBreakdown
                 * @static
                 * @param {perfetto.protos.AndroidMemoryMetric.IPriorityBreakdown} message PriorityBreakdown message or plain object to encode
                 * @param {$protobuf.Writer} [writer] Writer to encode to
                 * @returns {$protobuf.Writer} Writer
                 */
                PriorityBreakdown.encodeDelimited = function encodeDelimited(message, writer) {
                    return this.encode(message, writer).ldelim();
                };

                /**
                 * Decodes a PriorityBreakdown message from the specified reader or buffer.
                 * @function decode
                 * @memberof perfetto.protos.AndroidMemoryMetric.PriorityBreakdown
                 * @static
                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                 * @param {number} [length] Message length if known beforehand
                 * @returns {perfetto.protos.AndroidMemoryMetric.PriorityBreakdown} PriorityBreakdown
                 * @throws {Error} If the payload is not a reader or valid buffer
                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
                 */
                PriorityBreakdown.decode = function decode(reader, length) {
                    if (!(reader instanceof $Reader))
                        reader = $Reader.create(reader);
                    var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.AndroidMemoryMetric.PriorityBreakdown();
                    while (reader.pos < end) {
                        var tag = reader.uint32();
                        switch (tag >>> 3) {
                        case 1:
                            message.priority = reader.string();
                            break;
                        case 2:
                            message.counters = $root.perfetto.protos.AndroidMemoryMetric.ProcessMemoryCounters.decode(reader, reader.uint32());
                            break;
                        default:
                            reader.skipType(tag & 7);
                            break;
                        }
                    }
                    return message;
                };

                /**
                 * Decodes a PriorityBreakdown message from the specified reader or buffer, length delimited.
                 * @function decodeDelimited
                 * @memberof perfetto.protos.AndroidMemoryMetric.PriorityBreakdown
                 * @static
                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                 * @returns {perfetto.protos.AndroidMemoryMetric.PriorityBreakdown} PriorityBreakdown
                 * @throws {Error} If the payload is not a reader or valid buffer
                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
                 */
                PriorityBreakdown.decodeDelimited = function decodeDelimited(reader) {
                    if (!(reader instanceof $Reader))
                        reader = new $Reader(reader);
                    return this.decode(reader, reader.uint32());
                };

                /**
                 * Verifies a PriorityBreakdown message.
                 * @function verify
                 * @memberof perfetto.protos.AndroidMemoryMetric.PriorityBreakdown
                 * @static
                 * @param {Object.<string,*>} message Plain object to verify
                 * @returns {string|null} `null` if valid, otherwise the reason why it is not
                 */
                PriorityBreakdown.verify = function verify(message) {
                    if (typeof message !== "object" || message === null)
                        return "object expected";
                    if (message.priority != null && message.hasOwnProperty("priority"))
                        if (!$util.isString(message.priority))
                            return "priority: string expected";
                    if (message.counters != null && message.hasOwnProperty("counters")) {
                        var error = $root.perfetto.protos.AndroidMemoryMetric.ProcessMemoryCounters.verify(message.counters);
                        if (error)
                            return "counters." + error;
                    }
                    return null;
                };

                /**
                 * Creates a PriorityBreakdown message from a plain object. Also converts values to their respective internal types.
                 * @function fromObject
                 * @memberof perfetto.protos.AndroidMemoryMetric.PriorityBreakdown
                 * @static
                 * @param {Object.<string,*>} object Plain object
                 * @returns {perfetto.protos.AndroidMemoryMetric.PriorityBreakdown} PriorityBreakdown
                 */
                PriorityBreakdown.fromObject = function fromObject(object) {
                    if (object instanceof $root.perfetto.protos.AndroidMemoryMetric.PriorityBreakdown)
                        return object;
                    var message = new $root.perfetto.protos.AndroidMemoryMetric.PriorityBreakdown();
                    if (object.priority != null)
                        message.priority = String(object.priority);
                    if (object.counters != null) {
                        if (typeof object.counters !== "object")
                            throw TypeError(".perfetto.protos.AndroidMemoryMetric.PriorityBreakdown.counters: object expected");
                        message.counters = $root.perfetto.protos.AndroidMemoryMetric.ProcessMemoryCounters.fromObject(object.counters);
                    }
                    return message;
                };

                /**
                 * Creates a plain object from a PriorityBreakdown message. Also converts values to other types if specified.
                 * @function toObject
                 * @memberof perfetto.protos.AndroidMemoryMetric.PriorityBreakdown
                 * @static
                 * @param {perfetto.protos.AndroidMemoryMetric.PriorityBreakdown} message PriorityBreakdown
                 * @param {$protobuf.IConversionOptions} [options] Conversion options
                 * @returns {Object.<string,*>} Plain object
                 */
                PriorityBreakdown.toObject = function toObject(message, options) {
                    if (!options)
                        options = {};
                    var object = {};
                    if (options.defaults) {
                        object.priority = "";
                        object.counters = null;
                    }
                    if (message.priority != null && message.hasOwnProperty("priority"))
                        object.priority = message.priority;
                    if (message.counters != null && message.hasOwnProperty("counters"))
                        object.counters = $root.perfetto.protos.AndroidMemoryMetric.ProcessMemoryCounters.toObject(message.counters, options);
                    return object;
                };

                /**
                 * Converts this PriorityBreakdown to JSON.
                 * @function toJSON
                 * @memberof perfetto.protos.AndroidMemoryMetric.PriorityBreakdown
                 * @instance
                 * @returns {Object.<string,*>} JSON object
                 */
                PriorityBreakdown.prototype.toJSON = function toJSON() {
                    return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
                };

                return PriorityBreakdown;
            })();

            AndroidMemoryMetric.ProcessMemoryCounters = (function() {

                /**
                 * Properties of a ProcessMemoryCounters.
                 * @memberof perfetto.protos.AndroidMemoryMetric
                 * @interface IProcessMemoryCounters
                 * @property {perfetto.protos.AndroidMemoryMetric.ICounter|null} [anonRss] ProcessMemoryCounters anonRss
                 * @property {perfetto.protos.AndroidMemoryMetric.ICounter|null} [fileRss] ProcessMemoryCounters fileRss
                 * @property {perfetto.protos.AndroidMemoryMetric.ICounter|null} [swap] ProcessMemoryCounters swap
                 * @property {perfetto.protos.AndroidMemoryMetric.ICounter|null} [anonAndSwap] ProcessMemoryCounters anonAndSwap
                 * @property {perfetto.protos.AndroidMemoryMetric.ICounter|null} [javaHeap] ProcessMemoryCounters javaHeap
                 */

                /**
                 * Constructs a new ProcessMemoryCounters.
                 * @memberof perfetto.protos.AndroidMemoryMetric
                 * @classdesc Represents a ProcessMemoryCounters.
                 * @implements IProcessMemoryCounters
                 * @constructor
                 * @param {perfetto.protos.AndroidMemoryMetric.IProcessMemoryCounters=} [properties] Properties to set
                 */
                function ProcessMemoryCounters(properties) {
                    if (properties)
                        for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                            if (properties[keys[i]] != null)
                                this[keys[i]] = properties[keys[i]];
                }

                /**
                 * ProcessMemoryCounters anonRss.
                 * @member {perfetto.protos.AndroidMemoryMetric.ICounter|null|undefined} anonRss
                 * @memberof perfetto.protos.AndroidMemoryMetric.ProcessMemoryCounters
                 * @instance
                 */
                ProcessMemoryCounters.prototype.anonRss = null;

                /**
                 * ProcessMemoryCounters fileRss.
                 * @member {perfetto.protos.AndroidMemoryMetric.ICounter|null|undefined} fileRss
                 * @memberof perfetto.protos.AndroidMemoryMetric.ProcessMemoryCounters
                 * @instance
                 */
                ProcessMemoryCounters.prototype.fileRss = null;

                /**
                 * ProcessMemoryCounters swap.
                 * @member {perfetto.protos.AndroidMemoryMetric.ICounter|null|undefined} swap
                 * @memberof perfetto.protos.AndroidMemoryMetric.ProcessMemoryCounters
                 * @instance
                 */
                ProcessMemoryCounters.prototype.swap = null;

                /**
                 * ProcessMemoryCounters anonAndSwap.
                 * @member {perfetto.protos.AndroidMemoryMetric.ICounter|null|undefined} anonAndSwap
                 * @memberof perfetto.protos.AndroidMemoryMetric.ProcessMemoryCounters
                 * @instance
                 */
                ProcessMemoryCounters.prototype.anonAndSwap = null;

                /**
                 * ProcessMemoryCounters javaHeap.
                 * @member {perfetto.protos.AndroidMemoryMetric.ICounter|null|undefined} javaHeap
                 * @memberof perfetto.protos.AndroidMemoryMetric.ProcessMemoryCounters
                 * @instance
                 */
                ProcessMemoryCounters.prototype.javaHeap = null;

                /**
                 * Creates a new ProcessMemoryCounters instance using the specified properties.
                 * @function create
                 * @memberof perfetto.protos.AndroidMemoryMetric.ProcessMemoryCounters
                 * @static
                 * @param {perfetto.protos.AndroidMemoryMetric.IProcessMemoryCounters=} [properties] Properties to set
                 * @returns {perfetto.protos.AndroidMemoryMetric.ProcessMemoryCounters} ProcessMemoryCounters instance
                 */
                ProcessMemoryCounters.create = function create(properties) {
                    return new ProcessMemoryCounters(properties);
                };

                /**
                 * Encodes the specified ProcessMemoryCounters message. Does not implicitly {@link perfetto.protos.AndroidMemoryMetric.ProcessMemoryCounters.verify|verify} messages.
                 * @function encode
                 * @memberof perfetto.protos.AndroidMemoryMetric.ProcessMemoryCounters
                 * @static
                 * @param {perfetto.protos.AndroidMemoryMetric.IProcessMemoryCounters} message ProcessMemoryCounters message or plain object to encode
                 * @param {$protobuf.Writer} [writer] Writer to encode to
                 * @returns {$protobuf.Writer} Writer
                 */
                ProcessMemoryCounters.encode = function encode(message, writer) {
                    if (!writer)
                        writer = $Writer.create();
                    if (message.anonRss != null && Object.hasOwnProperty.call(message, "anonRss"))
                        $root.perfetto.protos.AndroidMemoryMetric.Counter.encode(message.anonRss, writer.uint32(/* id 1, wireType 2 =*/10).fork()).ldelim();
                    if (message.fileRss != null && Object.hasOwnProperty.call(message, "fileRss"))
                        $root.perfetto.protos.AndroidMemoryMetric.Counter.encode(message.fileRss, writer.uint32(/* id 2, wireType 2 =*/18).fork()).ldelim();
                    if (message.swap != null && Object.hasOwnProperty.call(message, "swap"))
                        $root.perfetto.protos.AndroidMemoryMetric.Counter.encode(message.swap, writer.uint32(/* id 3, wireType 2 =*/26).fork()).ldelim();
                    if (message.anonAndSwap != null && Object.hasOwnProperty.call(message, "anonAndSwap"))
                        $root.perfetto.protos.AndroidMemoryMetric.Counter.encode(message.anonAndSwap, writer.uint32(/* id 4, wireType 2 =*/34).fork()).ldelim();
                    if (message.javaHeap != null && Object.hasOwnProperty.call(message, "javaHeap"))
                        $root.perfetto.protos.AndroidMemoryMetric.Counter.encode(message.javaHeap, writer.uint32(/* id 5, wireType 2 =*/42).fork()).ldelim();
                    return writer;
                };

                /**
                 * Encodes the specified ProcessMemoryCounters message, length delimited. Does not implicitly {@link perfetto.protos.AndroidMemoryMetric.ProcessMemoryCounters.verify|verify} messages.
                 * @function encodeDelimited
                 * @memberof perfetto.protos.AndroidMemoryMetric.ProcessMemoryCounters
                 * @static
                 * @param {perfetto.protos.AndroidMemoryMetric.IProcessMemoryCounters} message ProcessMemoryCounters message or plain object to encode
                 * @param {$protobuf.Writer} [writer] Writer to encode to
                 * @returns {$protobuf.Writer} Writer
                 */
                ProcessMemoryCounters.encodeDelimited = function encodeDelimited(message, writer) {
                    return this.encode(message, writer).ldelim();
                };

                /**
                 * Decodes a ProcessMemoryCounters message from the specified reader or buffer.
                 * @function decode
                 * @memberof perfetto.protos.AndroidMemoryMetric.ProcessMemoryCounters
                 * @static
                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                 * @param {number} [length] Message length if known beforehand
                 * @returns {perfetto.protos.AndroidMemoryMetric.ProcessMemoryCounters} ProcessMemoryCounters
                 * @throws {Error} If the payload is not a reader or valid buffer
                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
                 */
                ProcessMemoryCounters.decode = function decode(reader, length) {
                    if (!(reader instanceof $Reader))
                        reader = $Reader.create(reader);
                    var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.AndroidMemoryMetric.ProcessMemoryCounters();
                    while (reader.pos < end) {
                        var tag = reader.uint32();
                        switch (tag >>> 3) {
                        case 1:
                            message.anonRss = $root.perfetto.protos.AndroidMemoryMetric.Counter.decode(reader, reader.uint32());
                            break;
                        case 2:
                            message.fileRss = $root.perfetto.protos.AndroidMemoryMetric.Counter.decode(reader, reader.uint32());
                            break;
                        case 3:
                            message.swap = $root.perfetto.protos.AndroidMemoryMetric.Counter.decode(reader, reader.uint32());
                            break;
                        case 4:
                            message.anonAndSwap = $root.perfetto.protos.AndroidMemoryMetric.Counter.decode(reader, reader.uint32());
                            break;
                        case 5:
                            message.javaHeap = $root.perfetto.protos.AndroidMemoryMetric.Counter.decode(reader, reader.uint32());
                            break;
                        default:
                            reader.skipType(tag & 7);
                            break;
                        }
                    }
                    return message;
                };

                /**
                 * Decodes a ProcessMemoryCounters message from the specified reader or buffer, length delimited.
                 * @function decodeDelimited
                 * @memberof perfetto.protos.AndroidMemoryMetric.ProcessMemoryCounters
                 * @static
                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                 * @returns {perfetto.protos.AndroidMemoryMetric.ProcessMemoryCounters} ProcessMemoryCounters
                 * @throws {Error} If the payload is not a reader or valid buffer
                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
                 */
                ProcessMemoryCounters.decodeDelimited = function decodeDelimited(reader) {
                    if (!(reader instanceof $Reader))
                        reader = new $Reader(reader);
                    return this.decode(reader, reader.uint32());
                };

                /**
                 * Verifies a ProcessMemoryCounters message.
                 * @function verify
                 * @memberof perfetto.protos.AndroidMemoryMetric.ProcessMemoryCounters
                 * @static
                 * @param {Object.<string,*>} message Plain object to verify
                 * @returns {string|null} `null` if valid, otherwise the reason why it is not
                 */
                ProcessMemoryCounters.verify = function verify(message) {
                    if (typeof message !== "object" || message === null)
                        return "object expected";
                    if (message.anonRss != null && message.hasOwnProperty("anonRss")) {
                        var error = $root.perfetto.protos.AndroidMemoryMetric.Counter.verify(message.anonRss);
                        if (error)
                            return "anonRss." + error;
                    }
                    if (message.fileRss != null && message.hasOwnProperty("fileRss")) {
                        var error = $root.perfetto.protos.AndroidMemoryMetric.Counter.verify(message.fileRss);
                        if (error)
                            return "fileRss." + error;
                    }
                    if (message.swap != null && message.hasOwnProperty("swap")) {
                        var error = $root.perfetto.protos.AndroidMemoryMetric.Counter.verify(message.swap);
                        if (error)
                            return "swap." + error;
                    }
                    if (message.anonAndSwap != null && message.hasOwnProperty("anonAndSwap")) {
                        var error = $root.perfetto.protos.AndroidMemoryMetric.Counter.verify(message.anonAndSwap);
                        if (error)
                            return "anonAndSwap." + error;
                    }
                    if (message.javaHeap != null && message.hasOwnProperty("javaHeap")) {
                        var error = $root.perfetto.protos.AndroidMemoryMetric.Counter.verify(message.javaHeap);
                        if (error)
                            return "javaHeap." + error;
                    }
                    return null;
                };

                /**
                 * Creates a ProcessMemoryCounters message from a plain object. Also converts values to their respective internal types.
                 * @function fromObject
                 * @memberof perfetto.protos.AndroidMemoryMetric.ProcessMemoryCounters
                 * @static
                 * @param {Object.<string,*>} object Plain object
                 * @returns {perfetto.protos.AndroidMemoryMetric.ProcessMemoryCounters} ProcessMemoryCounters
                 */
                ProcessMemoryCounters.fromObject = function fromObject(object) {
                    if (object instanceof $root.perfetto.protos.AndroidMemoryMetric.ProcessMemoryCounters)
                        return object;
                    var message = new $root.perfetto.protos.AndroidMemoryMetric.ProcessMemoryCounters();
                    if (object.anonRss != null) {
                        if (typeof object.anonRss !== "object")
                            throw TypeError(".perfetto.protos.AndroidMemoryMetric.ProcessMemoryCounters.anonRss: object expected");
                        message.anonRss = $root.perfetto.protos.AndroidMemoryMetric.Counter.fromObject(object.anonRss);
                    }
                    if (object.fileRss != null) {
                        if (typeof object.fileRss !== "object")
                            throw TypeError(".perfetto.protos.AndroidMemoryMetric.ProcessMemoryCounters.fileRss: object expected");
                        message.fileRss = $root.perfetto.protos.AndroidMemoryMetric.Counter.fromObject(object.fileRss);
                    }
                    if (object.swap != null) {
                        if (typeof object.swap !== "object")
                            throw TypeError(".perfetto.protos.AndroidMemoryMetric.ProcessMemoryCounters.swap: object expected");
                        message.swap = $root.perfetto.protos.AndroidMemoryMetric.Counter.fromObject(object.swap);
                    }
                    if (object.anonAndSwap != null) {
                        if (typeof object.anonAndSwap !== "object")
                            throw TypeError(".perfetto.protos.AndroidMemoryMetric.ProcessMemoryCounters.anonAndSwap: object expected");
                        message.anonAndSwap = $root.perfetto.protos.AndroidMemoryMetric.Counter.fromObject(object.anonAndSwap);
                    }
                    if (object.javaHeap != null) {
                        if (typeof object.javaHeap !== "object")
                            throw TypeError(".perfetto.protos.AndroidMemoryMetric.ProcessMemoryCounters.javaHeap: object expected");
                        message.javaHeap = $root.perfetto.protos.AndroidMemoryMetric.Counter.fromObject(object.javaHeap);
                    }
                    return message;
                };

                /**
                 * Creates a plain object from a ProcessMemoryCounters message. Also converts values to other types if specified.
                 * @function toObject
                 * @memberof perfetto.protos.AndroidMemoryMetric.ProcessMemoryCounters
                 * @static
                 * @param {perfetto.protos.AndroidMemoryMetric.ProcessMemoryCounters} message ProcessMemoryCounters
                 * @param {$protobuf.IConversionOptions} [options] Conversion options
                 * @returns {Object.<string,*>} Plain object
                 */
                ProcessMemoryCounters.toObject = function toObject(message, options) {
                    if (!options)
                        options = {};
                    var object = {};
                    if (options.defaults) {
                        object.anonRss = null;
                        object.fileRss = null;
                        object.swap = null;
                        object.anonAndSwap = null;
                        object.javaHeap = null;
                    }
                    if (message.anonRss != null && message.hasOwnProperty("anonRss"))
                        object.anonRss = $root.perfetto.protos.AndroidMemoryMetric.Counter.toObject(message.anonRss, options);
                    if (message.fileRss != null && message.hasOwnProperty("fileRss"))
                        object.fileRss = $root.perfetto.protos.AndroidMemoryMetric.Counter.toObject(message.fileRss, options);
                    if (message.swap != null && message.hasOwnProperty("swap"))
                        object.swap = $root.perfetto.protos.AndroidMemoryMetric.Counter.toObject(message.swap, options);
                    if (message.anonAndSwap != null && message.hasOwnProperty("anonAndSwap"))
                        object.anonAndSwap = $root.perfetto.protos.AndroidMemoryMetric.Counter.toObject(message.anonAndSwap, options);
                    if (message.javaHeap != null && message.hasOwnProperty("javaHeap"))
                        object.javaHeap = $root.perfetto.protos.AndroidMemoryMetric.Counter.toObject(message.javaHeap, options);
                    return object;
                };

                /**
                 * Converts this ProcessMemoryCounters to JSON.
                 * @function toJSON
                 * @memberof perfetto.protos.AndroidMemoryMetric.ProcessMemoryCounters
                 * @instance
                 * @returns {Object.<string,*>} JSON object
                 */
                ProcessMemoryCounters.prototype.toJSON = function toJSON() {
                    return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
                };

                return ProcessMemoryCounters;
            })();

            AndroidMemoryMetric.Counter = (function() {

                /**
                 * Properties of a Counter.
                 * @memberof perfetto.protos.AndroidMemoryMetric
                 * @interface ICounter
                 * @property {number|null} [min] Counter min
                 * @property {number|null} [max] Counter max
                 * @property {number|null} [avg] Counter avg
                 */

                /**
                 * Constructs a new Counter.
                 * @memberof perfetto.protos.AndroidMemoryMetric
                 * @classdesc Represents a Counter.
                 * @implements ICounter
                 * @constructor
                 * @param {perfetto.protos.AndroidMemoryMetric.ICounter=} [properties] Properties to set
                 */
                function Counter(properties) {
                    if (properties)
                        for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                            if (properties[keys[i]] != null)
                                this[keys[i]] = properties[keys[i]];
                }

                /**
                 * Counter min.
                 * @member {number} min
                 * @memberof perfetto.protos.AndroidMemoryMetric.Counter
                 * @instance
                 */
                Counter.prototype.min = 0;

                /**
                 * Counter max.
                 * @member {number} max
                 * @memberof perfetto.protos.AndroidMemoryMetric.Counter
                 * @instance
                 */
                Counter.prototype.max = 0;

                /**
                 * Counter avg.
                 * @member {number} avg
                 * @memberof perfetto.protos.AndroidMemoryMetric.Counter
                 * @instance
                 */
                Counter.prototype.avg = 0;

                /**
                 * Creates a new Counter instance using the specified properties.
                 * @function create
                 * @memberof perfetto.protos.AndroidMemoryMetric.Counter
                 * @static
                 * @param {perfetto.protos.AndroidMemoryMetric.ICounter=} [properties] Properties to set
                 * @returns {perfetto.protos.AndroidMemoryMetric.Counter} Counter instance
                 */
                Counter.create = function create(properties) {
                    return new Counter(properties);
                };

                /**
                 * Encodes the specified Counter message. Does not implicitly {@link perfetto.protos.AndroidMemoryMetric.Counter.verify|verify} messages.
                 * @function encode
                 * @memberof perfetto.protos.AndroidMemoryMetric.Counter
                 * @static
                 * @param {perfetto.protos.AndroidMemoryMetric.ICounter} message Counter message or plain object to encode
                 * @param {$protobuf.Writer} [writer] Writer to encode to
                 * @returns {$protobuf.Writer} Writer
                 */
                Counter.encode = function encode(message, writer) {
                    if (!writer)
                        writer = $Writer.create();
                    if (message.min != null && Object.hasOwnProperty.call(message, "min"))
                        writer.uint32(/* id 1, wireType 1 =*/9).double(message.min);
                    if (message.max != null && Object.hasOwnProperty.call(message, "max"))
                        writer.uint32(/* id 2, wireType 1 =*/17).double(message.max);
                    if (message.avg != null && Object.hasOwnProperty.call(message, "avg"))
                        writer.uint32(/* id 3, wireType 1 =*/25).double(message.avg);
                    return writer;
                };

                /**
                 * Encodes the specified Counter message, length delimited. Does not implicitly {@link perfetto.protos.AndroidMemoryMetric.Counter.verify|verify} messages.
                 * @function encodeDelimited
                 * @memberof perfetto.protos.AndroidMemoryMetric.Counter
                 * @static
                 * @param {perfetto.protos.AndroidMemoryMetric.ICounter} message Counter message or plain object to encode
                 * @param {$protobuf.Writer} [writer] Writer to encode to
                 * @returns {$protobuf.Writer} Writer
                 */
                Counter.encodeDelimited = function encodeDelimited(message, writer) {
                    return this.encode(message, writer).ldelim();
                };

                /**
                 * Decodes a Counter message from the specified reader or buffer.
                 * @function decode
                 * @memberof perfetto.protos.AndroidMemoryMetric.Counter
                 * @static
                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                 * @param {number} [length] Message length if known beforehand
                 * @returns {perfetto.protos.AndroidMemoryMetric.Counter} Counter
                 * @throws {Error} If the payload is not a reader or valid buffer
                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
                 */
                Counter.decode = function decode(reader, length) {
                    if (!(reader instanceof $Reader))
                        reader = $Reader.create(reader);
                    var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.AndroidMemoryMetric.Counter();
                    while (reader.pos < end) {
                        var tag = reader.uint32();
                        switch (tag >>> 3) {
                        case 1:
                            message.min = reader.double();
                            break;
                        case 2:
                            message.max = reader.double();
                            break;
                        case 3:
                            message.avg = reader.double();
                            break;
                        default:
                            reader.skipType(tag & 7);
                            break;
                        }
                    }
                    return message;
                };

                /**
                 * Decodes a Counter message from the specified reader or buffer, length delimited.
                 * @function decodeDelimited
                 * @memberof perfetto.protos.AndroidMemoryMetric.Counter
                 * @static
                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                 * @returns {perfetto.protos.AndroidMemoryMetric.Counter} Counter
                 * @throws {Error} If the payload is not a reader or valid buffer
                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
                 */
                Counter.decodeDelimited = function decodeDelimited(reader) {
                    if (!(reader instanceof $Reader))
                        reader = new $Reader(reader);
                    return this.decode(reader, reader.uint32());
                };

                /**
                 * Verifies a Counter message.
                 * @function verify
                 * @memberof perfetto.protos.AndroidMemoryMetric.Counter
                 * @static
                 * @param {Object.<string,*>} message Plain object to verify
                 * @returns {string|null} `null` if valid, otherwise the reason why it is not
                 */
                Counter.verify = function verify(message) {
                    if (typeof message !== "object" || message === null)
                        return "object expected";
                    if (message.min != null && message.hasOwnProperty("min"))
                        if (typeof message.min !== "number")
                            return "min: number expected";
                    if (message.max != null && message.hasOwnProperty("max"))
                        if (typeof message.max !== "number")
                            return "max: number expected";
                    if (message.avg != null && message.hasOwnProperty("avg"))
                        if (typeof message.avg !== "number")
                            return "avg: number expected";
                    return null;
                };

                /**
                 * Creates a Counter message from a plain object. Also converts values to their respective internal types.
                 * @function fromObject
                 * @memberof perfetto.protos.AndroidMemoryMetric.Counter
                 * @static
                 * @param {Object.<string,*>} object Plain object
                 * @returns {perfetto.protos.AndroidMemoryMetric.Counter} Counter
                 */
                Counter.fromObject = function fromObject(object) {
                    if (object instanceof $root.perfetto.protos.AndroidMemoryMetric.Counter)
                        return object;
                    var message = new $root.perfetto.protos.AndroidMemoryMetric.Counter();
                    if (object.min != null)
                        message.min = Number(object.min);
                    if (object.max != null)
                        message.max = Number(object.max);
                    if (object.avg != null)
                        message.avg = Number(object.avg);
                    return message;
                };

                /**
                 * Creates a plain object from a Counter message. Also converts values to other types if specified.
                 * @function toObject
                 * @memberof perfetto.protos.AndroidMemoryMetric.Counter
                 * @static
                 * @param {perfetto.protos.AndroidMemoryMetric.Counter} message Counter
                 * @param {$protobuf.IConversionOptions} [options] Conversion options
                 * @returns {Object.<string,*>} Plain object
                 */
                Counter.toObject = function toObject(message, options) {
                    if (!options)
                        options = {};
                    var object = {};
                    if (options.defaults) {
                        object.min = 0;
                        object.max = 0;
                        object.avg = 0;
                    }
                    if (message.min != null && message.hasOwnProperty("min"))
                        object.min = options.json && !isFinite(message.min) ? String(message.min) : message.min;
                    if (message.max != null && message.hasOwnProperty("max"))
                        object.max = options.json && !isFinite(message.max) ? String(message.max) : message.max;
                    if (message.avg != null && message.hasOwnProperty("avg"))
                        object.avg = options.json && !isFinite(message.avg) ? String(message.avg) : message.avg;
                    return object;
                };

                /**
                 * Converts this Counter to JSON.
                 * @function toJSON
                 * @memberof perfetto.protos.AndroidMemoryMetric.Counter
                 * @instance
                 * @returns {Object.<string,*>} JSON object
                 */
                Counter.prototype.toJSON = function toJSON() {
                    return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
                };

                return Counter;
            })();

            return AndroidMemoryMetric;
        })();

        protos.AndroidMemoryUnaggregatedMetric = (function() {

            /**
             * Properties of an AndroidMemoryUnaggregatedMetric.
             * @memberof perfetto.protos
             * @interface IAndroidMemoryUnaggregatedMetric
             * @property {Array.<perfetto.protos.AndroidMemoryUnaggregatedMetric.IProcessValues>|null} [processValues] AndroidMemoryUnaggregatedMetric processValues
             */

            /**
             * Constructs a new AndroidMemoryUnaggregatedMetric.
             * @memberof perfetto.protos
             * @classdesc Represents an AndroidMemoryUnaggregatedMetric.
             * @implements IAndroidMemoryUnaggregatedMetric
             * @constructor
             * @param {perfetto.protos.IAndroidMemoryUnaggregatedMetric=} [properties] Properties to set
             */
            function AndroidMemoryUnaggregatedMetric(properties) {
                this.processValues = [];
                if (properties)
                    for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                        if (properties[keys[i]] != null)
                            this[keys[i]] = properties[keys[i]];
            }

            /**
             * AndroidMemoryUnaggregatedMetric processValues.
             * @member {Array.<perfetto.protos.AndroidMemoryUnaggregatedMetric.IProcessValues>} processValues
             * @memberof perfetto.protos.AndroidMemoryUnaggregatedMetric
             * @instance
             */
            AndroidMemoryUnaggregatedMetric.prototype.processValues = $util.emptyArray;

            /**
             * Creates a new AndroidMemoryUnaggregatedMetric instance using the specified properties.
             * @function create
             * @memberof perfetto.protos.AndroidMemoryUnaggregatedMetric
             * @static
             * @param {perfetto.protos.IAndroidMemoryUnaggregatedMetric=} [properties] Properties to set
             * @returns {perfetto.protos.AndroidMemoryUnaggregatedMetric} AndroidMemoryUnaggregatedMetric instance
             */
            AndroidMemoryUnaggregatedMetric.create = function create(properties) {
                return new AndroidMemoryUnaggregatedMetric(properties);
            };

            /**
             * Encodes the specified AndroidMemoryUnaggregatedMetric message. Does not implicitly {@link perfetto.protos.AndroidMemoryUnaggregatedMetric.verify|verify} messages.
             * @function encode
             * @memberof perfetto.protos.AndroidMemoryUnaggregatedMetric
             * @static
             * @param {perfetto.protos.IAndroidMemoryUnaggregatedMetric} message AndroidMemoryUnaggregatedMetric message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            AndroidMemoryUnaggregatedMetric.encode = function encode(message, writer) {
                if (!writer)
                    writer = $Writer.create();
                if (message.processValues != null && message.processValues.length)
                    for (var i = 0; i < message.processValues.length; ++i)
                        $root.perfetto.protos.AndroidMemoryUnaggregatedMetric.ProcessValues.encode(message.processValues[i], writer.uint32(/* id 1, wireType 2 =*/10).fork()).ldelim();
                return writer;
            };

            /**
             * Encodes the specified AndroidMemoryUnaggregatedMetric message, length delimited. Does not implicitly {@link perfetto.protos.AndroidMemoryUnaggregatedMetric.verify|verify} messages.
             * @function encodeDelimited
             * @memberof perfetto.protos.AndroidMemoryUnaggregatedMetric
             * @static
             * @param {perfetto.protos.IAndroidMemoryUnaggregatedMetric} message AndroidMemoryUnaggregatedMetric message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            AndroidMemoryUnaggregatedMetric.encodeDelimited = function encodeDelimited(message, writer) {
                return this.encode(message, writer).ldelim();
            };

            /**
             * Decodes an AndroidMemoryUnaggregatedMetric message from the specified reader or buffer.
             * @function decode
             * @memberof perfetto.protos.AndroidMemoryUnaggregatedMetric
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @param {number} [length] Message length if known beforehand
             * @returns {perfetto.protos.AndroidMemoryUnaggregatedMetric} AndroidMemoryUnaggregatedMetric
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            AndroidMemoryUnaggregatedMetric.decode = function decode(reader, length) {
                if (!(reader instanceof $Reader))
                    reader = $Reader.create(reader);
                var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.AndroidMemoryUnaggregatedMetric();
                while (reader.pos < end) {
                    var tag = reader.uint32();
                    switch (tag >>> 3) {
                    case 1:
                        if (!(message.processValues && message.processValues.length))
                            message.processValues = [];
                        message.processValues.push($root.perfetto.protos.AndroidMemoryUnaggregatedMetric.ProcessValues.decode(reader, reader.uint32()));
                        break;
                    default:
                        reader.skipType(tag & 7);
                        break;
                    }
                }
                return message;
            };

            /**
             * Decodes an AndroidMemoryUnaggregatedMetric message from the specified reader or buffer, length delimited.
             * @function decodeDelimited
             * @memberof perfetto.protos.AndroidMemoryUnaggregatedMetric
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @returns {perfetto.protos.AndroidMemoryUnaggregatedMetric} AndroidMemoryUnaggregatedMetric
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            AndroidMemoryUnaggregatedMetric.decodeDelimited = function decodeDelimited(reader) {
                if (!(reader instanceof $Reader))
                    reader = new $Reader(reader);
                return this.decode(reader, reader.uint32());
            };

            /**
             * Verifies an AndroidMemoryUnaggregatedMetric message.
             * @function verify
             * @memberof perfetto.protos.AndroidMemoryUnaggregatedMetric
             * @static
             * @param {Object.<string,*>} message Plain object to verify
             * @returns {string|null} `null` if valid, otherwise the reason why it is not
             */
            AndroidMemoryUnaggregatedMetric.verify = function verify(message) {
                if (typeof message !== "object" || message === null)
                    return "object expected";
                if (message.processValues != null && message.hasOwnProperty("processValues")) {
                    if (!Array.isArray(message.processValues))
                        return "processValues: array expected";
                    for (var i = 0; i < message.processValues.length; ++i) {
                        var error = $root.perfetto.protos.AndroidMemoryUnaggregatedMetric.ProcessValues.verify(message.processValues[i]);
                        if (error)
                            return "processValues." + error;
                    }
                }
                return null;
            };

            /**
             * Creates an AndroidMemoryUnaggregatedMetric message from a plain object. Also converts values to their respective internal types.
             * @function fromObject
             * @memberof perfetto.protos.AndroidMemoryUnaggregatedMetric
             * @static
             * @param {Object.<string,*>} object Plain object
             * @returns {perfetto.protos.AndroidMemoryUnaggregatedMetric} AndroidMemoryUnaggregatedMetric
             */
            AndroidMemoryUnaggregatedMetric.fromObject = function fromObject(object) {
                if (object instanceof $root.perfetto.protos.AndroidMemoryUnaggregatedMetric)
                    return object;
                var message = new $root.perfetto.protos.AndroidMemoryUnaggregatedMetric();
                if (object.processValues) {
                    if (!Array.isArray(object.processValues))
                        throw TypeError(".perfetto.protos.AndroidMemoryUnaggregatedMetric.processValues: array expected");
                    message.processValues = [];
                    for (var i = 0; i < object.processValues.length; ++i) {
                        if (typeof object.processValues[i] !== "object")
                            throw TypeError(".perfetto.protos.AndroidMemoryUnaggregatedMetric.processValues: object expected");
                        message.processValues[i] = $root.perfetto.protos.AndroidMemoryUnaggregatedMetric.ProcessValues.fromObject(object.processValues[i]);
                    }
                }
                return message;
            };

            /**
             * Creates a plain object from an AndroidMemoryUnaggregatedMetric message. Also converts values to other types if specified.
             * @function toObject
             * @memberof perfetto.protos.AndroidMemoryUnaggregatedMetric
             * @static
             * @param {perfetto.protos.AndroidMemoryUnaggregatedMetric} message AndroidMemoryUnaggregatedMetric
             * @param {$protobuf.IConversionOptions} [options] Conversion options
             * @returns {Object.<string,*>} Plain object
             */
            AndroidMemoryUnaggregatedMetric.toObject = function toObject(message, options) {
                if (!options)
                    options = {};
                var object = {};
                if (options.arrays || options.defaults)
                    object.processValues = [];
                if (message.processValues && message.processValues.length) {
                    object.processValues = [];
                    for (var j = 0; j < message.processValues.length; ++j)
                        object.processValues[j] = $root.perfetto.protos.AndroidMemoryUnaggregatedMetric.ProcessValues.toObject(message.processValues[j], options);
                }
                return object;
            };

            /**
             * Converts this AndroidMemoryUnaggregatedMetric to JSON.
             * @function toJSON
             * @memberof perfetto.protos.AndroidMemoryUnaggregatedMetric
             * @instance
             * @returns {Object.<string,*>} JSON object
             */
            AndroidMemoryUnaggregatedMetric.prototype.toJSON = function toJSON() {
                return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
            };

            AndroidMemoryUnaggregatedMetric.ProcessValues = (function() {

                /**
                 * Properties of a ProcessValues.
                 * @memberof perfetto.protos.AndroidMemoryUnaggregatedMetric
                 * @interface IProcessValues
                 * @property {string|null} [processName] ProcessValues processName
                 * @property {perfetto.protos.AndroidMemoryUnaggregatedMetric.IProcessMemoryValues|null} [memValues] ProcessValues memValues
                 */

                /**
                 * Constructs a new ProcessValues.
                 * @memberof perfetto.protos.AndroidMemoryUnaggregatedMetric
                 * @classdesc Represents a ProcessValues.
                 * @implements IProcessValues
                 * @constructor
                 * @param {perfetto.protos.AndroidMemoryUnaggregatedMetric.IProcessValues=} [properties] Properties to set
                 */
                function ProcessValues(properties) {
                    if (properties)
                        for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                            if (properties[keys[i]] != null)
                                this[keys[i]] = properties[keys[i]];
                }

                /**
                 * ProcessValues processName.
                 * @member {string} processName
                 * @memberof perfetto.protos.AndroidMemoryUnaggregatedMetric.ProcessValues
                 * @instance
                 */
                ProcessValues.prototype.processName = "";

                /**
                 * ProcessValues memValues.
                 * @member {perfetto.protos.AndroidMemoryUnaggregatedMetric.IProcessMemoryValues|null|undefined} memValues
                 * @memberof perfetto.protos.AndroidMemoryUnaggregatedMetric.ProcessValues
                 * @instance
                 */
                ProcessValues.prototype.memValues = null;

                /**
                 * Creates a new ProcessValues instance using the specified properties.
                 * @function create
                 * @memberof perfetto.protos.AndroidMemoryUnaggregatedMetric.ProcessValues
                 * @static
                 * @param {perfetto.protos.AndroidMemoryUnaggregatedMetric.IProcessValues=} [properties] Properties to set
                 * @returns {perfetto.protos.AndroidMemoryUnaggregatedMetric.ProcessValues} ProcessValues instance
                 */
                ProcessValues.create = function create(properties) {
                    return new ProcessValues(properties);
                };

                /**
                 * Encodes the specified ProcessValues message. Does not implicitly {@link perfetto.protos.AndroidMemoryUnaggregatedMetric.ProcessValues.verify|verify} messages.
                 * @function encode
                 * @memberof perfetto.protos.AndroidMemoryUnaggregatedMetric.ProcessValues
                 * @static
                 * @param {perfetto.protos.AndroidMemoryUnaggregatedMetric.IProcessValues} message ProcessValues message or plain object to encode
                 * @param {$protobuf.Writer} [writer] Writer to encode to
                 * @returns {$protobuf.Writer} Writer
                 */
                ProcessValues.encode = function encode(message, writer) {
                    if (!writer)
                        writer = $Writer.create();
                    if (message.processName != null && Object.hasOwnProperty.call(message, "processName"))
                        writer.uint32(/* id 1, wireType 2 =*/10).string(message.processName);
                    if (message.memValues != null && Object.hasOwnProperty.call(message, "memValues"))
                        $root.perfetto.protos.AndroidMemoryUnaggregatedMetric.ProcessMemoryValues.encode(message.memValues, writer.uint32(/* id 2, wireType 2 =*/18).fork()).ldelim();
                    return writer;
                };

                /**
                 * Encodes the specified ProcessValues message, length delimited. Does not implicitly {@link perfetto.protos.AndroidMemoryUnaggregatedMetric.ProcessValues.verify|verify} messages.
                 * @function encodeDelimited
                 * @memberof perfetto.protos.AndroidMemoryUnaggregatedMetric.ProcessValues
                 * @static
                 * @param {perfetto.protos.AndroidMemoryUnaggregatedMetric.IProcessValues} message ProcessValues message or plain object to encode
                 * @param {$protobuf.Writer} [writer] Writer to encode to
                 * @returns {$protobuf.Writer} Writer
                 */
                ProcessValues.encodeDelimited = function encodeDelimited(message, writer) {
                    return this.encode(message, writer).ldelim();
                };

                /**
                 * Decodes a ProcessValues message from the specified reader or buffer.
                 * @function decode
                 * @memberof perfetto.protos.AndroidMemoryUnaggregatedMetric.ProcessValues
                 * @static
                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                 * @param {number} [length] Message length if known beforehand
                 * @returns {perfetto.protos.AndroidMemoryUnaggregatedMetric.ProcessValues} ProcessValues
                 * @throws {Error} If the payload is not a reader or valid buffer
                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
                 */
                ProcessValues.decode = function decode(reader, length) {
                    if (!(reader instanceof $Reader))
                        reader = $Reader.create(reader);
                    var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.AndroidMemoryUnaggregatedMetric.ProcessValues();
                    while (reader.pos < end) {
                        var tag = reader.uint32();
                        switch (tag >>> 3) {
                        case 1:
                            message.processName = reader.string();
                            break;
                        case 2:
                            message.memValues = $root.perfetto.protos.AndroidMemoryUnaggregatedMetric.ProcessMemoryValues.decode(reader, reader.uint32());
                            break;
                        default:
                            reader.skipType(tag & 7);
                            break;
                        }
                    }
                    return message;
                };

                /**
                 * Decodes a ProcessValues message from the specified reader or buffer, length delimited.
                 * @function decodeDelimited
                 * @memberof perfetto.protos.AndroidMemoryUnaggregatedMetric.ProcessValues
                 * @static
                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                 * @returns {perfetto.protos.AndroidMemoryUnaggregatedMetric.ProcessValues} ProcessValues
                 * @throws {Error} If the payload is not a reader or valid buffer
                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
                 */
                ProcessValues.decodeDelimited = function decodeDelimited(reader) {
                    if (!(reader instanceof $Reader))
                        reader = new $Reader(reader);
                    return this.decode(reader, reader.uint32());
                };

                /**
                 * Verifies a ProcessValues message.
                 * @function verify
                 * @memberof perfetto.protos.AndroidMemoryUnaggregatedMetric.ProcessValues
                 * @static
                 * @param {Object.<string,*>} message Plain object to verify
                 * @returns {string|null} `null` if valid, otherwise the reason why it is not
                 */
                ProcessValues.verify = function verify(message) {
                    if (typeof message !== "object" || message === null)
                        return "object expected";
                    if (message.processName != null && message.hasOwnProperty("processName"))
                        if (!$util.isString(message.processName))
                            return "processName: string expected";
                    if (message.memValues != null && message.hasOwnProperty("memValues")) {
                        var error = $root.perfetto.protos.AndroidMemoryUnaggregatedMetric.ProcessMemoryValues.verify(message.memValues);
                        if (error)
                            return "memValues." + error;
                    }
                    return null;
                };

                /**
                 * Creates a ProcessValues message from a plain object. Also converts values to their respective internal types.
                 * @function fromObject
                 * @memberof perfetto.protos.AndroidMemoryUnaggregatedMetric.ProcessValues
                 * @static
                 * @param {Object.<string,*>} object Plain object
                 * @returns {perfetto.protos.AndroidMemoryUnaggregatedMetric.ProcessValues} ProcessValues
                 */
                ProcessValues.fromObject = function fromObject(object) {
                    if (object instanceof $root.perfetto.protos.AndroidMemoryUnaggregatedMetric.ProcessValues)
                        return object;
                    var message = new $root.perfetto.protos.AndroidMemoryUnaggregatedMetric.ProcessValues();
                    if (object.processName != null)
                        message.processName = String(object.processName);
                    if (object.memValues != null) {
                        if (typeof object.memValues !== "object")
                            throw TypeError(".perfetto.protos.AndroidMemoryUnaggregatedMetric.ProcessValues.memValues: object expected");
                        message.memValues = $root.perfetto.protos.AndroidMemoryUnaggregatedMetric.ProcessMemoryValues.fromObject(object.memValues);
                    }
                    return message;
                };

                /**
                 * Creates a plain object from a ProcessValues message. Also converts values to other types if specified.
                 * @function toObject
                 * @memberof perfetto.protos.AndroidMemoryUnaggregatedMetric.ProcessValues
                 * @static
                 * @param {perfetto.protos.AndroidMemoryUnaggregatedMetric.ProcessValues} message ProcessValues
                 * @param {$protobuf.IConversionOptions} [options] Conversion options
                 * @returns {Object.<string,*>} Plain object
                 */
                ProcessValues.toObject = function toObject(message, options) {
                    if (!options)
                        options = {};
                    var object = {};
                    if (options.defaults) {
                        object.processName = "";
                        object.memValues = null;
                    }
                    if (message.processName != null && message.hasOwnProperty("processName"))
                        object.processName = message.processName;
                    if (message.memValues != null && message.hasOwnProperty("memValues"))
                        object.memValues = $root.perfetto.protos.AndroidMemoryUnaggregatedMetric.ProcessMemoryValues.toObject(message.memValues, options);
                    return object;
                };

                /**
                 * Converts this ProcessValues to JSON.
                 * @function toJSON
                 * @memberof perfetto.protos.AndroidMemoryUnaggregatedMetric.ProcessValues
                 * @instance
                 * @returns {Object.<string,*>} JSON object
                 */
                ProcessValues.prototype.toJSON = function toJSON() {
                    return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
                };

                return ProcessValues;
            })();

            AndroidMemoryUnaggregatedMetric.ProcessMemoryValues = (function() {

                /**
                 * Properties of a ProcessMemoryValues.
                 * @memberof perfetto.protos.AndroidMemoryUnaggregatedMetric
                 * @interface IProcessMemoryValues
                 * @property {Array.<perfetto.protos.AndroidMemoryUnaggregatedMetric.IValue>|null} [anonRss] ProcessMemoryValues anonRss
                 * @property {Array.<perfetto.protos.AndroidMemoryUnaggregatedMetric.IValue>|null} [fileRss] ProcessMemoryValues fileRss
                 * @property {Array.<perfetto.protos.AndroidMemoryUnaggregatedMetric.IValue>|null} [swap] ProcessMemoryValues swap
                 * @property {Array.<perfetto.protos.AndroidMemoryUnaggregatedMetric.IValue>|null} [anonAndSwap] ProcessMemoryValues anonAndSwap
                 */

                /**
                 * Constructs a new ProcessMemoryValues.
                 * @memberof perfetto.protos.AndroidMemoryUnaggregatedMetric
                 * @classdesc Represents a ProcessMemoryValues.
                 * @implements IProcessMemoryValues
                 * @constructor
                 * @param {perfetto.protos.AndroidMemoryUnaggregatedMetric.IProcessMemoryValues=} [properties] Properties to set
                 */
                function ProcessMemoryValues(properties) {
                    this.anonRss = [];
                    this.fileRss = [];
                    this.swap = [];
                    this.anonAndSwap = [];
                    if (properties)
                        for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                            if (properties[keys[i]] != null)
                                this[keys[i]] = properties[keys[i]];
                }

                /**
                 * ProcessMemoryValues anonRss.
                 * @member {Array.<perfetto.protos.AndroidMemoryUnaggregatedMetric.IValue>} anonRss
                 * @memberof perfetto.protos.AndroidMemoryUnaggregatedMetric.ProcessMemoryValues
                 * @instance
                 */
                ProcessMemoryValues.prototype.anonRss = $util.emptyArray;

                /**
                 * ProcessMemoryValues fileRss.
                 * @member {Array.<perfetto.protos.AndroidMemoryUnaggregatedMetric.IValue>} fileRss
                 * @memberof perfetto.protos.AndroidMemoryUnaggregatedMetric.ProcessMemoryValues
                 * @instance
                 */
                ProcessMemoryValues.prototype.fileRss = $util.emptyArray;

                /**
                 * ProcessMemoryValues swap.
                 * @member {Array.<perfetto.protos.AndroidMemoryUnaggregatedMetric.IValue>} swap
                 * @memberof perfetto.protos.AndroidMemoryUnaggregatedMetric.ProcessMemoryValues
                 * @instance
                 */
                ProcessMemoryValues.prototype.swap = $util.emptyArray;

                /**
                 * ProcessMemoryValues anonAndSwap.
                 * @member {Array.<perfetto.protos.AndroidMemoryUnaggregatedMetric.IValue>} anonAndSwap
                 * @memberof perfetto.protos.AndroidMemoryUnaggregatedMetric.ProcessMemoryValues
                 * @instance
                 */
                ProcessMemoryValues.prototype.anonAndSwap = $util.emptyArray;

                /**
                 * Creates a new ProcessMemoryValues instance using the specified properties.
                 * @function create
                 * @memberof perfetto.protos.AndroidMemoryUnaggregatedMetric.ProcessMemoryValues
                 * @static
                 * @param {perfetto.protos.AndroidMemoryUnaggregatedMetric.IProcessMemoryValues=} [properties] Properties to set
                 * @returns {perfetto.protos.AndroidMemoryUnaggregatedMetric.ProcessMemoryValues} ProcessMemoryValues instance
                 */
                ProcessMemoryValues.create = function create(properties) {
                    return new ProcessMemoryValues(properties);
                };

                /**
                 * Encodes the specified ProcessMemoryValues message. Does not implicitly {@link perfetto.protos.AndroidMemoryUnaggregatedMetric.ProcessMemoryValues.verify|verify} messages.
                 * @function encode
                 * @memberof perfetto.protos.AndroidMemoryUnaggregatedMetric.ProcessMemoryValues
                 * @static
                 * @param {perfetto.protos.AndroidMemoryUnaggregatedMetric.IProcessMemoryValues} message ProcessMemoryValues message or plain object to encode
                 * @param {$protobuf.Writer} [writer] Writer to encode to
                 * @returns {$protobuf.Writer} Writer
                 */
                ProcessMemoryValues.encode = function encode(message, writer) {
                    if (!writer)
                        writer = $Writer.create();
                    if (message.anonRss != null && message.anonRss.length)
                        for (var i = 0; i < message.anonRss.length; ++i)
                            $root.perfetto.protos.AndroidMemoryUnaggregatedMetric.Value.encode(message.anonRss[i], writer.uint32(/* id 1, wireType 2 =*/10).fork()).ldelim();
                    if (message.fileRss != null && message.fileRss.length)
                        for (var i = 0; i < message.fileRss.length; ++i)
                            $root.perfetto.protos.AndroidMemoryUnaggregatedMetric.Value.encode(message.fileRss[i], writer.uint32(/* id 2, wireType 2 =*/18).fork()).ldelim();
                    if (message.swap != null && message.swap.length)
                        for (var i = 0; i < message.swap.length; ++i)
                            $root.perfetto.protos.AndroidMemoryUnaggregatedMetric.Value.encode(message.swap[i], writer.uint32(/* id 3, wireType 2 =*/26).fork()).ldelim();
                    if (message.anonAndSwap != null && message.anonAndSwap.length)
                        for (var i = 0; i < message.anonAndSwap.length; ++i)
                            $root.perfetto.protos.AndroidMemoryUnaggregatedMetric.Value.encode(message.anonAndSwap[i], writer.uint32(/* id 4, wireType 2 =*/34).fork()).ldelim();
                    return writer;
                };

                /**
                 * Encodes the specified ProcessMemoryValues message, length delimited. Does not implicitly {@link perfetto.protos.AndroidMemoryUnaggregatedMetric.ProcessMemoryValues.verify|verify} messages.
                 * @function encodeDelimited
                 * @memberof perfetto.protos.AndroidMemoryUnaggregatedMetric.ProcessMemoryValues
                 * @static
                 * @param {perfetto.protos.AndroidMemoryUnaggregatedMetric.IProcessMemoryValues} message ProcessMemoryValues message or plain object to encode
                 * @param {$protobuf.Writer} [writer] Writer to encode to
                 * @returns {$protobuf.Writer} Writer
                 */
                ProcessMemoryValues.encodeDelimited = function encodeDelimited(message, writer) {
                    return this.encode(message, writer).ldelim();
                };

                /**
                 * Decodes a ProcessMemoryValues message from the specified reader or buffer.
                 * @function decode
                 * @memberof perfetto.protos.AndroidMemoryUnaggregatedMetric.ProcessMemoryValues
                 * @static
                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                 * @param {number} [length] Message length if known beforehand
                 * @returns {perfetto.protos.AndroidMemoryUnaggregatedMetric.ProcessMemoryValues} ProcessMemoryValues
                 * @throws {Error} If the payload is not a reader or valid buffer
                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
                 */
                ProcessMemoryValues.decode = function decode(reader, length) {
                    if (!(reader instanceof $Reader))
                        reader = $Reader.create(reader);
                    var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.AndroidMemoryUnaggregatedMetric.ProcessMemoryValues();
                    while (reader.pos < end) {
                        var tag = reader.uint32();
                        switch (tag >>> 3) {
                        case 1:
                            if (!(message.anonRss && message.anonRss.length))
                                message.anonRss = [];
                            message.anonRss.push($root.perfetto.protos.AndroidMemoryUnaggregatedMetric.Value.decode(reader, reader.uint32()));
                            break;
                        case 2:
                            if (!(message.fileRss && message.fileRss.length))
                                message.fileRss = [];
                            message.fileRss.push($root.perfetto.protos.AndroidMemoryUnaggregatedMetric.Value.decode(reader, reader.uint32()));
                            break;
                        case 3:
                            if (!(message.swap && message.swap.length))
                                message.swap = [];
                            message.swap.push($root.perfetto.protos.AndroidMemoryUnaggregatedMetric.Value.decode(reader, reader.uint32()));
                            break;
                        case 4:
                            if (!(message.anonAndSwap && message.anonAndSwap.length))
                                message.anonAndSwap = [];
                            message.anonAndSwap.push($root.perfetto.protos.AndroidMemoryUnaggregatedMetric.Value.decode(reader, reader.uint32()));
                            break;
                        default:
                            reader.skipType(tag & 7);
                            break;
                        }
                    }
                    return message;
                };

                /**
                 * Decodes a ProcessMemoryValues message from the specified reader or buffer, length delimited.
                 * @function decodeDelimited
                 * @memberof perfetto.protos.AndroidMemoryUnaggregatedMetric.ProcessMemoryValues
                 * @static
                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                 * @returns {perfetto.protos.AndroidMemoryUnaggregatedMetric.ProcessMemoryValues} ProcessMemoryValues
                 * @throws {Error} If the payload is not a reader or valid buffer
                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
                 */
                ProcessMemoryValues.decodeDelimited = function decodeDelimited(reader) {
                    if (!(reader instanceof $Reader))
                        reader = new $Reader(reader);
                    return this.decode(reader, reader.uint32());
                };

                /**
                 * Verifies a ProcessMemoryValues message.
                 * @function verify
                 * @memberof perfetto.protos.AndroidMemoryUnaggregatedMetric.ProcessMemoryValues
                 * @static
                 * @param {Object.<string,*>} message Plain object to verify
                 * @returns {string|null} `null` if valid, otherwise the reason why it is not
                 */
                ProcessMemoryValues.verify = function verify(message) {
                    if (typeof message !== "object" || message === null)
                        return "object expected";
                    if (message.anonRss != null && message.hasOwnProperty("anonRss")) {
                        if (!Array.isArray(message.anonRss))
                            return "anonRss: array expected";
                        for (var i = 0; i < message.anonRss.length; ++i) {
                            var error = $root.perfetto.protos.AndroidMemoryUnaggregatedMetric.Value.verify(message.anonRss[i]);
                            if (error)
                                return "anonRss." + error;
                        }
                    }
                    if (message.fileRss != null && message.hasOwnProperty("fileRss")) {
                        if (!Array.isArray(message.fileRss))
                            return "fileRss: array expected";
                        for (var i = 0; i < message.fileRss.length; ++i) {
                            var error = $root.perfetto.protos.AndroidMemoryUnaggregatedMetric.Value.verify(message.fileRss[i]);
                            if (error)
                                return "fileRss." + error;
                        }
                    }
                    if (message.swap != null && message.hasOwnProperty("swap")) {
                        if (!Array.isArray(message.swap))
                            return "swap: array expected";
                        for (var i = 0; i < message.swap.length; ++i) {
                            var error = $root.perfetto.protos.AndroidMemoryUnaggregatedMetric.Value.verify(message.swap[i]);
                            if (error)
                                return "swap." + error;
                        }
                    }
                    if (message.anonAndSwap != null && message.hasOwnProperty("anonAndSwap")) {
                        if (!Array.isArray(message.anonAndSwap))
                            return "anonAndSwap: array expected";
                        for (var i = 0; i < message.anonAndSwap.length; ++i) {
                            var error = $root.perfetto.protos.AndroidMemoryUnaggregatedMetric.Value.verify(message.anonAndSwap[i]);
                            if (error)
                                return "anonAndSwap." + error;
                        }
                    }
                    return null;
                };

                /**
                 * Creates a ProcessMemoryValues message from a plain object. Also converts values to their respective internal types.
                 * @function fromObject
                 * @memberof perfetto.protos.AndroidMemoryUnaggregatedMetric.ProcessMemoryValues
                 * @static
                 * @param {Object.<string,*>} object Plain object
                 * @returns {perfetto.protos.AndroidMemoryUnaggregatedMetric.ProcessMemoryValues} ProcessMemoryValues
                 */
                ProcessMemoryValues.fromObject = function fromObject(object) {
                    if (object instanceof $root.perfetto.protos.AndroidMemoryUnaggregatedMetric.ProcessMemoryValues)
                        return object;
                    var message = new $root.perfetto.protos.AndroidMemoryUnaggregatedMetric.ProcessMemoryValues();
                    if (object.anonRss) {
                        if (!Array.isArray(object.anonRss))
                            throw TypeError(".perfetto.protos.AndroidMemoryUnaggregatedMetric.ProcessMemoryValues.anonRss: array expected");
                        message.anonRss = [];
                        for (var i = 0; i < object.anonRss.length; ++i) {
                            if (typeof object.anonRss[i] !== "object")
                                throw TypeError(".perfetto.protos.AndroidMemoryUnaggregatedMetric.ProcessMemoryValues.anonRss: object expected");
                            message.anonRss[i] = $root.perfetto.protos.AndroidMemoryUnaggregatedMetric.Value.fromObject(object.anonRss[i]);
                        }
                    }
                    if (object.fileRss) {
                        if (!Array.isArray(object.fileRss))
                            throw TypeError(".perfetto.protos.AndroidMemoryUnaggregatedMetric.ProcessMemoryValues.fileRss: array expected");
                        message.fileRss = [];
                        for (var i = 0; i < object.fileRss.length; ++i) {
                            if (typeof object.fileRss[i] !== "object")
                                throw TypeError(".perfetto.protos.AndroidMemoryUnaggregatedMetric.ProcessMemoryValues.fileRss: object expected");
                            message.fileRss[i] = $root.perfetto.protos.AndroidMemoryUnaggregatedMetric.Value.fromObject(object.fileRss[i]);
                        }
                    }
                    if (object.swap) {
                        if (!Array.isArray(object.swap))
                            throw TypeError(".perfetto.protos.AndroidMemoryUnaggregatedMetric.ProcessMemoryValues.swap: array expected");
                        message.swap = [];
                        for (var i = 0; i < object.swap.length; ++i) {
                            if (typeof object.swap[i] !== "object")
                                throw TypeError(".perfetto.protos.AndroidMemoryUnaggregatedMetric.ProcessMemoryValues.swap: object expected");
                            message.swap[i] = $root.perfetto.protos.AndroidMemoryUnaggregatedMetric.Value.fromObject(object.swap[i]);
                        }
                    }
                    if (object.anonAndSwap) {
                        if (!Array.isArray(object.anonAndSwap))
                            throw TypeError(".perfetto.protos.AndroidMemoryUnaggregatedMetric.ProcessMemoryValues.anonAndSwap: array expected");
                        message.anonAndSwap = [];
                        for (var i = 0; i < object.anonAndSwap.length; ++i) {
                            if (typeof object.anonAndSwap[i] !== "object")
                                throw TypeError(".perfetto.protos.AndroidMemoryUnaggregatedMetric.ProcessMemoryValues.anonAndSwap: object expected");
                            message.anonAndSwap[i] = $root.perfetto.protos.AndroidMemoryUnaggregatedMetric.Value.fromObject(object.anonAndSwap[i]);
                        }
                    }
                    return message;
                };

                /**
                 * Creates a plain object from a ProcessMemoryValues message. Also converts values to other types if specified.
                 * @function toObject
                 * @memberof perfetto.protos.AndroidMemoryUnaggregatedMetric.ProcessMemoryValues
                 * @static
                 * @param {perfetto.protos.AndroidMemoryUnaggregatedMetric.ProcessMemoryValues} message ProcessMemoryValues
                 * @param {$protobuf.IConversionOptions} [options] Conversion options
                 * @returns {Object.<string,*>} Plain object
                 */
                ProcessMemoryValues.toObject = function toObject(message, options) {
                    if (!options)
                        options = {};
                    var object = {};
                    if (options.arrays || options.defaults) {
                        object.anonRss = [];
                        object.fileRss = [];
                        object.swap = [];
                        object.anonAndSwap = [];
                    }
                    if (message.anonRss && message.anonRss.length) {
                        object.anonRss = [];
                        for (var j = 0; j < message.anonRss.length; ++j)
                            object.anonRss[j] = $root.perfetto.protos.AndroidMemoryUnaggregatedMetric.Value.toObject(message.anonRss[j], options);
                    }
                    if (message.fileRss && message.fileRss.length) {
                        object.fileRss = [];
                        for (var j = 0; j < message.fileRss.length; ++j)
                            object.fileRss[j] = $root.perfetto.protos.AndroidMemoryUnaggregatedMetric.Value.toObject(message.fileRss[j], options);
                    }
                    if (message.swap && message.swap.length) {
                        object.swap = [];
                        for (var j = 0; j < message.swap.length; ++j)
                            object.swap[j] = $root.perfetto.protos.AndroidMemoryUnaggregatedMetric.Value.toObject(message.swap[j], options);
                    }
                    if (message.anonAndSwap && message.anonAndSwap.length) {
                        object.anonAndSwap = [];
                        for (var j = 0; j < message.anonAndSwap.length; ++j)
                            object.anonAndSwap[j] = $root.perfetto.protos.AndroidMemoryUnaggregatedMetric.Value.toObject(message.anonAndSwap[j], options);
                    }
                    return object;
                };

                /**
                 * Converts this ProcessMemoryValues to JSON.
                 * @function toJSON
                 * @memberof perfetto.protos.AndroidMemoryUnaggregatedMetric.ProcessMemoryValues
                 * @instance
                 * @returns {Object.<string,*>} JSON object
                 */
                ProcessMemoryValues.prototype.toJSON = function toJSON() {
                    return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
                };

                return ProcessMemoryValues;
            })();

            AndroidMemoryUnaggregatedMetric.Value = (function() {

                /**
                 * Properties of a Value.
                 * @memberof perfetto.protos.AndroidMemoryUnaggregatedMetric
                 * @interface IValue
                 * @property {number|null} [ts] Value ts
                 * @property {number|null} [oomScore] Value oomScore
                 * @property {number|null} [value] Value value
                 */

                /**
                 * Constructs a new Value.
                 * @memberof perfetto.protos.AndroidMemoryUnaggregatedMetric
                 * @classdesc Represents a Value.
                 * @implements IValue
                 * @constructor
                 * @param {perfetto.protos.AndroidMemoryUnaggregatedMetric.IValue=} [properties] Properties to set
                 */
                function Value(properties) {
                    if (properties)
                        for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                            if (properties[keys[i]] != null)
                                this[keys[i]] = properties[keys[i]];
                }

                /**
                 * Value ts.
                 * @member {number} ts
                 * @memberof perfetto.protos.AndroidMemoryUnaggregatedMetric.Value
                 * @instance
                 */
                Value.prototype.ts = $util.Long ? $util.Long.fromBits(0,0,false) : 0;

                /**
                 * Value oomScore.
                 * @member {number} oomScore
                 * @memberof perfetto.protos.AndroidMemoryUnaggregatedMetric.Value
                 * @instance
                 */
                Value.prototype.oomScore = 0;

                /**
                 * Value value.
                 * @member {number} value
                 * @memberof perfetto.protos.AndroidMemoryUnaggregatedMetric.Value
                 * @instance
                 */
                Value.prototype.value = 0;

                /**
                 * Creates a new Value instance using the specified properties.
                 * @function create
                 * @memberof perfetto.protos.AndroidMemoryUnaggregatedMetric.Value
                 * @static
                 * @param {perfetto.protos.AndroidMemoryUnaggregatedMetric.IValue=} [properties] Properties to set
                 * @returns {perfetto.protos.AndroidMemoryUnaggregatedMetric.Value} Value instance
                 */
                Value.create = function create(properties) {
                    return new Value(properties);
                };

                /**
                 * Encodes the specified Value message. Does not implicitly {@link perfetto.protos.AndroidMemoryUnaggregatedMetric.Value.verify|verify} messages.
                 * @function encode
                 * @memberof perfetto.protos.AndroidMemoryUnaggregatedMetric.Value
                 * @static
                 * @param {perfetto.protos.AndroidMemoryUnaggregatedMetric.IValue} message Value message or plain object to encode
                 * @param {$protobuf.Writer} [writer] Writer to encode to
                 * @returns {$protobuf.Writer} Writer
                 */
                Value.encode = function encode(message, writer) {
                    if (!writer)
                        writer = $Writer.create();
                    if (message.ts != null && Object.hasOwnProperty.call(message, "ts"))
                        writer.uint32(/* id 1, wireType 0 =*/8).int64(message.ts);
                    if (message.oomScore != null && Object.hasOwnProperty.call(message, "oomScore"))
                        writer.uint32(/* id 2, wireType 0 =*/16).int32(message.oomScore);
                    if (message.value != null && Object.hasOwnProperty.call(message, "value"))
                        writer.uint32(/* id 3, wireType 1 =*/25).double(message.value);
                    return writer;
                };

                /**
                 * Encodes the specified Value message, length delimited. Does not implicitly {@link perfetto.protos.AndroidMemoryUnaggregatedMetric.Value.verify|verify} messages.
                 * @function encodeDelimited
                 * @memberof perfetto.protos.AndroidMemoryUnaggregatedMetric.Value
                 * @static
                 * @param {perfetto.protos.AndroidMemoryUnaggregatedMetric.IValue} message Value message or plain object to encode
                 * @param {$protobuf.Writer} [writer] Writer to encode to
                 * @returns {$protobuf.Writer} Writer
                 */
                Value.encodeDelimited = function encodeDelimited(message, writer) {
                    return this.encode(message, writer).ldelim();
                };

                /**
                 * Decodes a Value message from the specified reader or buffer.
                 * @function decode
                 * @memberof perfetto.protos.AndroidMemoryUnaggregatedMetric.Value
                 * @static
                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                 * @param {number} [length] Message length if known beforehand
                 * @returns {perfetto.protos.AndroidMemoryUnaggregatedMetric.Value} Value
                 * @throws {Error} If the payload is not a reader or valid buffer
                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
                 */
                Value.decode = function decode(reader, length) {
                    if (!(reader instanceof $Reader))
                        reader = $Reader.create(reader);
                    var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.AndroidMemoryUnaggregatedMetric.Value();
                    while (reader.pos < end) {
                        var tag = reader.uint32();
                        switch (tag >>> 3) {
                        case 1:
                            message.ts = reader.int64();
                            break;
                        case 2:
                            message.oomScore = reader.int32();
                            break;
                        case 3:
                            message.value = reader.double();
                            break;
                        default:
                            reader.skipType(tag & 7);
                            break;
                        }
                    }
                    return message;
                };

                /**
                 * Decodes a Value message from the specified reader or buffer, length delimited.
                 * @function decodeDelimited
                 * @memberof perfetto.protos.AndroidMemoryUnaggregatedMetric.Value
                 * @static
                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                 * @returns {perfetto.protos.AndroidMemoryUnaggregatedMetric.Value} Value
                 * @throws {Error} If the payload is not a reader or valid buffer
                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
                 */
                Value.decodeDelimited = function decodeDelimited(reader) {
                    if (!(reader instanceof $Reader))
                        reader = new $Reader(reader);
                    return this.decode(reader, reader.uint32());
                };

                /**
                 * Verifies a Value message.
                 * @function verify
                 * @memberof perfetto.protos.AndroidMemoryUnaggregatedMetric.Value
                 * @static
                 * @param {Object.<string,*>} message Plain object to verify
                 * @returns {string|null} `null` if valid, otherwise the reason why it is not
                 */
                Value.verify = function verify(message) {
                    if (typeof message !== "object" || message === null)
                        return "object expected";
                    if (message.ts != null && message.hasOwnProperty("ts"))
                        if (!$util.isInteger(message.ts) && !(message.ts && $util.isInteger(message.ts.low) && $util.isInteger(message.ts.high)))
                            return "ts: integer|Long expected";
                    if (message.oomScore != null && message.hasOwnProperty("oomScore"))
                        if (!$util.isInteger(message.oomScore))
                            return "oomScore: integer expected";
                    if (message.value != null && message.hasOwnProperty("value"))
                        if (typeof message.value !== "number")
                            return "value: number expected";
                    return null;
                };

                /**
                 * Creates a Value message from a plain object. Also converts values to their respective internal types.
                 * @function fromObject
                 * @memberof perfetto.protos.AndroidMemoryUnaggregatedMetric.Value
                 * @static
                 * @param {Object.<string,*>} object Plain object
                 * @returns {perfetto.protos.AndroidMemoryUnaggregatedMetric.Value} Value
                 */
                Value.fromObject = function fromObject(object) {
                    if (object instanceof $root.perfetto.protos.AndroidMemoryUnaggregatedMetric.Value)
                        return object;
                    var message = new $root.perfetto.protos.AndroidMemoryUnaggregatedMetric.Value();
                    if (object.ts != null)
                        if ($util.Long)
                            (message.ts = $util.Long.fromValue(object.ts)).unsigned = false;
                        else if (typeof object.ts === "string")
                            message.ts = parseInt(object.ts, 10);
                        else if (typeof object.ts === "number")
                            message.ts = object.ts;
                        else if (typeof object.ts === "object")
                            message.ts = new $util.LongBits(object.ts.low >>> 0, object.ts.high >>> 0).toNumber();
                    if (object.oomScore != null)
                        message.oomScore = object.oomScore | 0;
                    if (object.value != null)
                        message.value = Number(object.value);
                    return message;
                };

                /**
                 * Creates a plain object from a Value message. Also converts values to other types if specified.
                 * @function toObject
                 * @memberof perfetto.protos.AndroidMemoryUnaggregatedMetric.Value
                 * @static
                 * @param {perfetto.protos.AndroidMemoryUnaggregatedMetric.Value} message Value
                 * @param {$protobuf.IConversionOptions} [options] Conversion options
                 * @returns {Object.<string,*>} Plain object
                 */
                Value.toObject = function toObject(message, options) {
                    if (!options)
                        options = {};
                    var object = {};
                    if (options.defaults) {
                        if ($util.Long) {
                            var long = new $util.Long(0, 0, false);
                            object.ts = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
                        } else
                            object.ts = options.longs === String ? "0" : 0;
                        object.oomScore = 0;
                        object.value = 0;
                    }
                    if (message.ts != null && message.hasOwnProperty("ts"))
                        if (typeof message.ts === "number")
                            object.ts = options.longs === String ? String(message.ts) : message.ts;
                        else
                            object.ts = options.longs === String ? $util.Long.prototype.toString.call(message.ts) : options.longs === Number ? new $util.LongBits(message.ts.low >>> 0, message.ts.high >>> 0).toNumber() : message.ts;
                    if (message.oomScore != null && message.hasOwnProperty("oomScore"))
                        object.oomScore = message.oomScore;
                    if (message.value != null && message.hasOwnProperty("value"))
                        object.value = options.json && !isFinite(message.value) ? String(message.value) : message.value;
                    return object;
                };

                /**
                 * Converts this Value to JSON.
                 * @function toJSON
                 * @memberof perfetto.protos.AndroidMemoryUnaggregatedMetric.Value
                 * @instance
                 * @returns {Object.<string,*>} JSON object
                 */
                Value.prototype.toJSON = function toJSON() {
                    return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
                };

                return Value;
            })();

            return AndroidMemoryUnaggregatedMetric;
        })();

        protos.AndroidPackageList = (function() {

            /**
             * Properties of an AndroidPackageList.
             * @memberof perfetto.protos
             * @interface IAndroidPackageList
             * @property {Array.<perfetto.protos.AndroidPackageList.IPackage>|null} [packages] AndroidPackageList packages
             */

            /**
             * Constructs a new AndroidPackageList.
             * @memberof perfetto.protos
             * @classdesc Represents an AndroidPackageList.
             * @implements IAndroidPackageList
             * @constructor
             * @param {perfetto.protos.IAndroidPackageList=} [properties] Properties to set
             */
            function AndroidPackageList(properties) {
                this.packages = [];
                if (properties)
                    for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                        if (properties[keys[i]] != null)
                            this[keys[i]] = properties[keys[i]];
            }

            /**
             * AndroidPackageList packages.
             * @member {Array.<perfetto.protos.AndroidPackageList.IPackage>} packages
             * @memberof perfetto.protos.AndroidPackageList
             * @instance
             */
            AndroidPackageList.prototype.packages = $util.emptyArray;

            /**
             * Creates a new AndroidPackageList instance using the specified properties.
             * @function create
             * @memberof perfetto.protos.AndroidPackageList
             * @static
             * @param {perfetto.protos.IAndroidPackageList=} [properties] Properties to set
             * @returns {perfetto.protos.AndroidPackageList} AndroidPackageList instance
             */
            AndroidPackageList.create = function create(properties) {
                return new AndroidPackageList(properties);
            };

            /**
             * Encodes the specified AndroidPackageList message. Does not implicitly {@link perfetto.protos.AndroidPackageList.verify|verify} messages.
             * @function encode
             * @memberof perfetto.protos.AndroidPackageList
             * @static
             * @param {perfetto.protos.IAndroidPackageList} message AndroidPackageList message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            AndroidPackageList.encode = function encode(message, writer) {
                if (!writer)
                    writer = $Writer.create();
                if (message.packages != null && message.packages.length)
                    for (var i = 0; i < message.packages.length; ++i)
                        $root.perfetto.protos.AndroidPackageList.Package.encode(message.packages[i], writer.uint32(/* id 1, wireType 2 =*/10).fork()).ldelim();
                return writer;
            };

            /**
             * Encodes the specified AndroidPackageList message, length delimited. Does not implicitly {@link perfetto.protos.AndroidPackageList.verify|verify} messages.
             * @function encodeDelimited
             * @memberof perfetto.protos.AndroidPackageList
             * @static
             * @param {perfetto.protos.IAndroidPackageList} message AndroidPackageList message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            AndroidPackageList.encodeDelimited = function encodeDelimited(message, writer) {
                return this.encode(message, writer).ldelim();
            };

            /**
             * Decodes an AndroidPackageList message from the specified reader or buffer.
             * @function decode
             * @memberof perfetto.protos.AndroidPackageList
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @param {number} [length] Message length if known beforehand
             * @returns {perfetto.protos.AndroidPackageList} AndroidPackageList
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            AndroidPackageList.decode = function decode(reader, length) {
                if (!(reader instanceof $Reader))
                    reader = $Reader.create(reader);
                var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.AndroidPackageList();
                while (reader.pos < end) {
                    var tag = reader.uint32();
                    switch (tag >>> 3) {
                    case 1:
                        if (!(message.packages && message.packages.length))
                            message.packages = [];
                        message.packages.push($root.perfetto.protos.AndroidPackageList.Package.decode(reader, reader.uint32()));
                        break;
                    default:
                        reader.skipType(tag & 7);
                        break;
                    }
                }
                return message;
            };

            /**
             * Decodes an AndroidPackageList message from the specified reader or buffer, length delimited.
             * @function decodeDelimited
             * @memberof perfetto.protos.AndroidPackageList
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @returns {perfetto.protos.AndroidPackageList} AndroidPackageList
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            AndroidPackageList.decodeDelimited = function decodeDelimited(reader) {
                if (!(reader instanceof $Reader))
                    reader = new $Reader(reader);
                return this.decode(reader, reader.uint32());
            };

            /**
             * Verifies an AndroidPackageList message.
             * @function verify
             * @memberof perfetto.protos.AndroidPackageList
             * @static
             * @param {Object.<string,*>} message Plain object to verify
             * @returns {string|null} `null` if valid, otherwise the reason why it is not
             */
            AndroidPackageList.verify = function verify(message) {
                if (typeof message !== "object" || message === null)
                    return "object expected";
                if (message.packages != null && message.hasOwnProperty("packages")) {
                    if (!Array.isArray(message.packages))
                        return "packages: array expected";
                    for (var i = 0; i < message.packages.length; ++i) {
                        var error = $root.perfetto.protos.AndroidPackageList.Package.verify(message.packages[i]);
                        if (error)
                            return "packages." + error;
                    }
                }
                return null;
            };

            /**
             * Creates an AndroidPackageList message from a plain object. Also converts values to their respective internal types.
             * @function fromObject
             * @memberof perfetto.protos.AndroidPackageList
             * @static
             * @param {Object.<string,*>} object Plain object
             * @returns {perfetto.protos.AndroidPackageList} AndroidPackageList
             */
            AndroidPackageList.fromObject = function fromObject(object) {
                if (object instanceof $root.perfetto.protos.AndroidPackageList)
                    return object;
                var message = new $root.perfetto.protos.AndroidPackageList();
                if (object.packages) {
                    if (!Array.isArray(object.packages))
                        throw TypeError(".perfetto.protos.AndroidPackageList.packages: array expected");
                    message.packages = [];
                    for (var i = 0; i < object.packages.length; ++i) {
                        if (typeof object.packages[i] !== "object")
                            throw TypeError(".perfetto.protos.AndroidPackageList.packages: object expected");
                        message.packages[i] = $root.perfetto.protos.AndroidPackageList.Package.fromObject(object.packages[i]);
                    }
                }
                return message;
            };

            /**
             * Creates a plain object from an AndroidPackageList message. Also converts values to other types if specified.
             * @function toObject
             * @memberof perfetto.protos.AndroidPackageList
             * @static
             * @param {perfetto.protos.AndroidPackageList} message AndroidPackageList
             * @param {$protobuf.IConversionOptions} [options] Conversion options
             * @returns {Object.<string,*>} Plain object
             */
            AndroidPackageList.toObject = function toObject(message, options) {
                if (!options)
                    options = {};
                var object = {};
                if (options.arrays || options.defaults)
                    object.packages = [];
                if (message.packages && message.packages.length) {
                    object.packages = [];
                    for (var j = 0; j < message.packages.length; ++j)
                        object.packages[j] = $root.perfetto.protos.AndroidPackageList.Package.toObject(message.packages[j], options);
                }
                return object;
            };

            /**
             * Converts this AndroidPackageList to JSON.
             * @function toJSON
             * @memberof perfetto.protos.AndroidPackageList
             * @instance
             * @returns {Object.<string,*>} JSON object
             */
            AndroidPackageList.prototype.toJSON = function toJSON() {
                return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
            };

            AndroidPackageList.Package = (function() {

                /**
                 * Properties of a Package.
                 * @memberof perfetto.protos.AndroidPackageList
                 * @interface IPackage
                 * @property {string|null} [packageName] Package packageName
                 * @property {number|null} [uid] Package uid
                 * @property {number|null} [versionCode] Package versionCode
                 */

                /**
                 * Constructs a new Package.
                 * @memberof perfetto.protos.AndroidPackageList
                 * @classdesc Represents a Package.
                 * @implements IPackage
                 * @constructor
                 * @param {perfetto.protos.AndroidPackageList.IPackage=} [properties] Properties to set
                 */
                function Package(properties) {
                    if (properties)
                        for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                            if (properties[keys[i]] != null)
                                this[keys[i]] = properties[keys[i]];
                }

                /**
                 * Package packageName.
                 * @member {string} packageName
                 * @memberof perfetto.protos.AndroidPackageList.Package
                 * @instance
                 */
                Package.prototype.packageName = "";

                /**
                 * Package uid.
                 * @member {number} uid
                 * @memberof perfetto.protos.AndroidPackageList.Package
                 * @instance
                 */
                Package.prototype.uid = $util.Long ? $util.Long.fromBits(0,0,false) : 0;

                /**
                 * Package versionCode.
                 * @member {number} versionCode
                 * @memberof perfetto.protos.AndroidPackageList.Package
                 * @instance
                 */
                Package.prototype.versionCode = $util.Long ? $util.Long.fromBits(0,0,false) : 0;

                /**
                 * Creates a new Package instance using the specified properties.
                 * @function create
                 * @memberof perfetto.protos.AndroidPackageList.Package
                 * @static
                 * @param {perfetto.protos.AndroidPackageList.IPackage=} [properties] Properties to set
                 * @returns {perfetto.protos.AndroidPackageList.Package} Package instance
                 */
                Package.create = function create(properties) {
                    return new Package(properties);
                };

                /**
                 * Encodes the specified Package message. Does not implicitly {@link perfetto.protos.AndroidPackageList.Package.verify|verify} messages.
                 * @function encode
                 * @memberof perfetto.protos.AndroidPackageList.Package
                 * @static
                 * @param {perfetto.protos.AndroidPackageList.IPackage} message Package message or plain object to encode
                 * @param {$protobuf.Writer} [writer] Writer to encode to
                 * @returns {$protobuf.Writer} Writer
                 */
                Package.encode = function encode(message, writer) {
                    if (!writer)
                        writer = $Writer.create();
                    if (message.packageName != null && Object.hasOwnProperty.call(message, "packageName"))
                        writer.uint32(/* id 1, wireType 2 =*/10).string(message.packageName);
                    if (message.uid != null && Object.hasOwnProperty.call(message, "uid"))
                        writer.uint32(/* id 2, wireType 0 =*/16).int64(message.uid);
                    if (message.versionCode != null && Object.hasOwnProperty.call(message, "versionCode"))
                        writer.uint32(/* id 3, wireType 0 =*/24).int64(message.versionCode);
                    return writer;
                };

                /**
                 * Encodes the specified Package message, length delimited. Does not implicitly {@link perfetto.protos.AndroidPackageList.Package.verify|verify} messages.
                 * @function encodeDelimited
                 * @memberof perfetto.protos.AndroidPackageList.Package
                 * @static
                 * @param {perfetto.protos.AndroidPackageList.IPackage} message Package message or plain object to encode
                 * @param {$protobuf.Writer} [writer] Writer to encode to
                 * @returns {$protobuf.Writer} Writer
                 */
                Package.encodeDelimited = function encodeDelimited(message, writer) {
                    return this.encode(message, writer).ldelim();
                };

                /**
                 * Decodes a Package message from the specified reader or buffer.
                 * @function decode
                 * @memberof perfetto.protos.AndroidPackageList.Package
                 * @static
                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                 * @param {number} [length] Message length if known beforehand
                 * @returns {perfetto.protos.AndroidPackageList.Package} Package
                 * @throws {Error} If the payload is not a reader or valid buffer
                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
                 */
                Package.decode = function decode(reader, length) {
                    if (!(reader instanceof $Reader))
                        reader = $Reader.create(reader);
                    var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.AndroidPackageList.Package();
                    while (reader.pos < end) {
                        var tag = reader.uint32();
                        switch (tag >>> 3) {
                        case 1:
                            message.packageName = reader.string();
                            break;
                        case 2:
                            message.uid = reader.int64();
                            break;
                        case 3:
                            message.versionCode = reader.int64();
                            break;
                        default:
                            reader.skipType(tag & 7);
                            break;
                        }
                    }
                    return message;
                };

                /**
                 * Decodes a Package message from the specified reader or buffer, length delimited.
                 * @function decodeDelimited
                 * @memberof perfetto.protos.AndroidPackageList.Package
                 * @static
                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                 * @returns {perfetto.protos.AndroidPackageList.Package} Package
                 * @throws {Error} If the payload is not a reader or valid buffer
                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
                 */
                Package.decodeDelimited = function decodeDelimited(reader) {
                    if (!(reader instanceof $Reader))
                        reader = new $Reader(reader);
                    return this.decode(reader, reader.uint32());
                };

                /**
                 * Verifies a Package message.
                 * @function verify
                 * @memberof perfetto.protos.AndroidPackageList.Package
                 * @static
                 * @param {Object.<string,*>} message Plain object to verify
                 * @returns {string|null} `null` if valid, otherwise the reason why it is not
                 */
                Package.verify = function verify(message) {
                    if (typeof message !== "object" || message === null)
                        return "object expected";
                    if (message.packageName != null && message.hasOwnProperty("packageName"))
                        if (!$util.isString(message.packageName))
                            return "packageName: string expected";
                    if (message.uid != null && message.hasOwnProperty("uid"))
                        if (!$util.isInteger(message.uid) && !(message.uid && $util.isInteger(message.uid.low) && $util.isInteger(message.uid.high)))
                            return "uid: integer|Long expected";
                    if (message.versionCode != null && message.hasOwnProperty("versionCode"))
                        if (!$util.isInteger(message.versionCode) && !(message.versionCode && $util.isInteger(message.versionCode.low) && $util.isInteger(message.versionCode.high)))
                            return "versionCode: integer|Long expected";
                    return null;
                };

                /**
                 * Creates a Package message from a plain object. Also converts values to their respective internal types.
                 * @function fromObject
                 * @memberof perfetto.protos.AndroidPackageList.Package
                 * @static
                 * @param {Object.<string,*>} object Plain object
                 * @returns {perfetto.protos.AndroidPackageList.Package} Package
                 */
                Package.fromObject = function fromObject(object) {
                    if (object instanceof $root.perfetto.protos.AndroidPackageList.Package)
                        return object;
                    var message = new $root.perfetto.protos.AndroidPackageList.Package();
                    if (object.packageName != null)
                        message.packageName = String(object.packageName);
                    if (object.uid != null)
                        if ($util.Long)
                            (message.uid = $util.Long.fromValue(object.uid)).unsigned = false;
                        else if (typeof object.uid === "string")
                            message.uid = parseInt(object.uid, 10);
                        else if (typeof object.uid === "number")
                            message.uid = object.uid;
                        else if (typeof object.uid === "object")
                            message.uid = new $util.LongBits(object.uid.low >>> 0, object.uid.high >>> 0).toNumber();
                    if (object.versionCode != null)
                        if ($util.Long)
                            (message.versionCode = $util.Long.fromValue(object.versionCode)).unsigned = false;
                        else if (typeof object.versionCode === "string")
                            message.versionCode = parseInt(object.versionCode, 10);
                        else if (typeof object.versionCode === "number")
                            message.versionCode = object.versionCode;
                        else if (typeof object.versionCode === "object")
                            message.versionCode = new $util.LongBits(object.versionCode.low >>> 0, object.versionCode.high >>> 0).toNumber();
                    return message;
                };

                /**
                 * Creates a plain object from a Package message. Also converts values to other types if specified.
                 * @function toObject
                 * @memberof perfetto.protos.AndroidPackageList.Package
                 * @static
                 * @param {perfetto.protos.AndroidPackageList.Package} message Package
                 * @param {$protobuf.IConversionOptions} [options] Conversion options
                 * @returns {Object.<string,*>} Plain object
                 */
                Package.toObject = function toObject(message, options) {
                    if (!options)
                        options = {};
                    var object = {};
                    if (options.defaults) {
                        object.packageName = "";
                        if ($util.Long) {
                            var long = new $util.Long(0, 0, false);
                            object.uid = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
                        } else
                            object.uid = options.longs === String ? "0" : 0;
                        if ($util.Long) {
                            var long = new $util.Long(0, 0, false);
                            object.versionCode = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
                        } else
                            object.versionCode = options.longs === String ? "0" : 0;
                    }
                    if (message.packageName != null && message.hasOwnProperty("packageName"))
                        object.packageName = message.packageName;
                    if (message.uid != null && message.hasOwnProperty("uid"))
                        if (typeof message.uid === "number")
                            object.uid = options.longs === String ? String(message.uid) : message.uid;
                        else
                            object.uid = options.longs === String ? $util.Long.prototype.toString.call(message.uid) : options.longs === Number ? new $util.LongBits(message.uid.low >>> 0, message.uid.high >>> 0).toNumber() : message.uid;
                    if (message.versionCode != null && message.hasOwnProperty("versionCode"))
                        if (typeof message.versionCode === "number")
                            object.versionCode = options.longs === String ? String(message.versionCode) : message.versionCode;
                        else
                            object.versionCode = options.longs === String ? $util.Long.prototype.toString.call(message.versionCode) : options.longs === Number ? new $util.LongBits(message.versionCode.low >>> 0, message.versionCode.high >>> 0).toNumber() : message.versionCode;
                    return object;
                };

                /**
                 * Converts this Package to JSON.
                 * @function toJSON
                 * @memberof perfetto.protos.AndroidPackageList.Package
                 * @instance
                 * @returns {Object.<string,*>} JSON object
                 */
                Package.prototype.toJSON = function toJSON() {
                    return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
                };

                return Package;
            })();

            return AndroidPackageList;
        })();

        protos.AndroidPowerRails = (function() {

            /**
             * Properties of an AndroidPowerRails.
             * @memberof perfetto.protos
             * @interface IAndroidPowerRails
             * @property {Array.<perfetto.protos.AndroidPowerRails.IPowerRails>|null} [powerRails] AndroidPowerRails powerRails
             */

            /**
             * Constructs a new AndroidPowerRails.
             * @memberof perfetto.protos
             * @classdesc Represents an AndroidPowerRails.
             * @implements IAndroidPowerRails
             * @constructor
             * @param {perfetto.protos.IAndroidPowerRails=} [properties] Properties to set
             */
            function AndroidPowerRails(properties) {
                this.powerRails = [];
                if (properties)
                    for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                        if (properties[keys[i]] != null)
                            this[keys[i]] = properties[keys[i]];
            }

            /**
             * AndroidPowerRails powerRails.
             * @member {Array.<perfetto.protos.AndroidPowerRails.IPowerRails>} powerRails
             * @memberof perfetto.protos.AndroidPowerRails
             * @instance
             */
            AndroidPowerRails.prototype.powerRails = $util.emptyArray;

            /**
             * Creates a new AndroidPowerRails instance using the specified properties.
             * @function create
             * @memberof perfetto.protos.AndroidPowerRails
             * @static
             * @param {perfetto.protos.IAndroidPowerRails=} [properties] Properties to set
             * @returns {perfetto.protos.AndroidPowerRails} AndroidPowerRails instance
             */
            AndroidPowerRails.create = function create(properties) {
                return new AndroidPowerRails(properties);
            };

            /**
             * Encodes the specified AndroidPowerRails message. Does not implicitly {@link perfetto.protos.AndroidPowerRails.verify|verify} messages.
             * @function encode
             * @memberof perfetto.protos.AndroidPowerRails
             * @static
             * @param {perfetto.protos.IAndroidPowerRails} message AndroidPowerRails message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            AndroidPowerRails.encode = function encode(message, writer) {
                if (!writer)
                    writer = $Writer.create();
                if (message.powerRails != null && message.powerRails.length)
                    for (var i = 0; i < message.powerRails.length; ++i)
                        $root.perfetto.protos.AndroidPowerRails.PowerRails.encode(message.powerRails[i], writer.uint32(/* id 1, wireType 2 =*/10).fork()).ldelim();
                return writer;
            };

            /**
             * Encodes the specified AndroidPowerRails message, length delimited. Does not implicitly {@link perfetto.protos.AndroidPowerRails.verify|verify} messages.
             * @function encodeDelimited
             * @memberof perfetto.protos.AndroidPowerRails
             * @static
             * @param {perfetto.protos.IAndroidPowerRails} message AndroidPowerRails message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            AndroidPowerRails.encodeDelimited = function encodeDelimited(message, writer) {
                return this.encode(message, writer).ldelim();
            };

            /**
             * Decodes an AndroidPowerRails message from the specified reader or buffer.
             * @function decode
             * @memberof perfetto.protos.AndroidPowerRails
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @param {number} [length] Message length if known beforehand
             * @returns {perfetto.protos.AndroidPowerRails} AndroidPowerRails
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            AndroidPowerRails.decode = function decode(reader, length) {
                if (!(reader instanceof $Reader))
                    reader = $Reader.create(reader);
                var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.AndroidPowerRails();
                while (reader.pos < end) {
                    var tag = reader.uint32();
                    switch (tag >>> 3) {
                    case 1:
                        if (!(message.powerRails && message.powerRails.length))
                            message.powerRails = [];
                        message.powerRails.push($root.perfetto.protos.AndroidPowerRails.PowerRails.decode(reader, reader.uint32()));
                        break;
                    default:
                        reader.skipType(tag & 7);
                        break;
                    }
                }
                return message;
            };

            /**
             * Decodes an AndroidPowerRails message from the specified reader or buffer, length delimited.
             * @function decodeDelimited
             * @memberof perfetto.protos.AndroidPowerRails
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @returns {perfetto.protos.AndroidPowerRails} AndroidPowerRails
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            AndroidPowerRails.decodeDelimited = function decodeDelimited(reader) {
                if (!(reader instanceof $Reader))
                    reader = new $Reader(reader);
                return this.decode(reader, reader.uint32());
            };

            /**
             * Verifies an AndroidPowerRails message.
             * @function verify
             * @memberof perfetto.protos.AndroidPowerRails
             * @static
             * @param {Object.<string,*>} message Plain object to verify
             * @returns {string|null} `null` if valid, otherwise the reason why it is not
             */
            AndroidPowerRails.verify = function verify(message) {
                if (typeof message !== "object" || message === null)
                    return "object expected";
                if (message.powerRails != null && message.hasOwnProperty("powerRails")) {
                    if (!Array.isArray(message.powerRails))
                        return "powerRails: array expected";
                    for (var i = 0; i < message.powerRails.length; ++i) {
                        var error = $root.perfetto.protos.AndroidPowerRails.PowerRails.verify(message.powerRails[i]);
                        if (error)
                            return "powerRails." + error;
                    }
                }
                return null;
            };

            /**
             * Creates an AndroidPowerRails message from a plain object. Also converts values to their respective internal types.
             * @function fromObject
             * @memberof perfetto.protos.AndroidPowerRails
             * @static
             * @param {Object.<string,*>} object Plain object
             * @returns {perfetto.protos.AndroidPowerRails} AndroidPowerRails
             */
            AndroidPowerRails.fromObject = function fromObject(object) {
                if (object instanceof $root.perfetto.protos.AndroidPowerRails)
                    return object;
                var message = new $root.perfetto.protos.AndroidPowerRails();
                if (object.powerRails) {
                    if (!Array.isArray(object.powerRails))
                        throw TypeError(".perfetto.protos.AndroidPowerRails.powerRails: array expected");
                    message.powerRails = [];
                    for (var i = 0; i < object.powerRails.length; ++i) {
                        if (typeof object.powerRails[i] !== "object")
                            throw TypeError(".perfetto.protos.AndroidPowerRails.powerRails: object expected");
                        message.powerRails[i] = $root.perfetto.protos.AndroidPowerRails.PowerRails.fromObject(object.powerRails[i]);
                    }
                }
                return message;
            };

            /**
             * Creates a plain object from an AndroidPowerRails message. Also converts values to other types if specified.
             * @function toObject
             * @memberof perfetto.protos.AndroidPowerRails
             * @static
             * @param {perfetto.protos.AndroidPowerRails} message AndroidPowerRails
             * @param {$protobuf.IConversionOptions} [options] Conversion options
             * @returns {Object.<string,*>} Plain object
             */
            AndroidPowerRails.toObject = function toObject(message, options) {
                if (!options)
                    options = {};
                var object = {};
                if (options.arrays || options.defaults)
                    object.powerRails = [];
                if (message.powerRails && message.powerRails.length) {
                    object.powerRails = [];
                    for (var j = 0; j < message.powerRails.length; ++j)
                        object.powerRails[j] = $root.perfetto.protos.AndroidPowerRails.PowerRails.toObject(message.powerRails[j], options);
                }
                return object;
            };

            /**
             * Converts this AndroidPowerRails to JSON.
             * @function toJSON
             * @memberof perfetto.protos.AndroidPowerRails
             * @instance
             * @returns {Object.<string,*>} JSON object
             */
            AndroidPowerRails.prototype.toJSON = function toJSON() {
                return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
            };

            AndroidPowerRails.EnergyData = (function() {

                /**
                 * Properties of an EnergyData.
                 * @memberof perfetto.protos.AndroidPowerRails
                 * @interface IEnergyData
                 * @property {number|null} [timestampMs] EnergyData timestampMs
                 * @property {number|null} [energyUws] EnergyData energyUws
                 */

                /**
                 * Constructs a new EnergyData.
                 * @memberof perfetto.protos.AndroidPowerRails
                 * @classdesc Represents an EnergyData.
                 * @implements IEnergyData
                 * @constructor
                 * @param {perfetto.protos.AndroidPowerRails.IEnergyData=} [properties] Properties to set
                 */
                function EnergyData(properties) {
                    if (properties)
                        for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                            if (properties[keys[i]] != null)
                                this[keys[i]] = properties[keys[i]];
                }

                /**
                 * EnergyData timestampMs.
                 * @member {number} timestampMs
                 * @memberof perfetto.protos.AndroidPowerRails.EnergyData
                 * @instance
                 */
                EnergyData.prototype.timestampMs = $util.Long ? $util.Long.fromBits(0,0,false) : 0;

                /**
                 * EnergyData energyUws.
                 * @member {number} energyUws
                 * @memberof perfetto.protos.AndroidPowerRails.EnergyData
                 * @instance
                 */
                EnergyData.prototype.energyUws = 0;

                /**
                 * Creates a new EnergyData instance using the specified properties.
                 * @function create
                 * @memberof perfetto.protos.AndroidPowerRails.EnergyData
                 * @static
                 * @param {perfetto.protos.AndroidPowerRails.IEnergyData=} [properties] Properties to set
                 * @returns {perfetto.protos.AndroidPowerRails.EnergyData} EnergyData instance
                 */
                EnergyData.create = function create(properties) {
                    return new EnergyData(properties);
                };

                /**
                 * Encodes the specified EnergyData message. Does not implicitly {@link perfetto.protos.AndroidPowerRails.EnergyData.verify|verify} messages.
                 * @function encode
                 * @memberof perfetto.protos.AndroidPowerRails.EnergyData
                 * @static
                 * @param {perfetto.protos.AndroidPowerRails.IEnergyData} message EnergyData message or plain object to encode
                 * @param {$protobuf.Writer} [writer] Writer to encode to
                 * @returns {$protobuf.Writer} Writer
                 */
                EnergyData.encode = function encode(message, writer) {
                    if (!writer)
                        writer = $Writer.create();
                    if (message.timestampMs != null && Object.hasOwnProperty.call(message, "timestampMs"))
                        writer.uint32(/* id 1, wireType 0 =*/8).int64(message.timestampMs);
                    if (message.energyUws != null && Object.hasOwnProperty.call(message, "energyUws"))
                        writer.uint32(/* id 2, wireType 1 =*/17).double(message.energyUws);
                    return writer;
                };

                /**
                 * Encodes the specified EnergyData message, length delimited. Does not implicitly {@link perfetto.protos.AndroidPowerRails.EnergyData.verify|verify} messages.
                 * @function encodeDelimited
                 * @memberof perfetto.protos.AndroidPowerRails.EnergyData
                 * @static
                 * @param {perfetto.protos.AndroidPowerRails.IEnergyData} message EnergyData message or plain object to encode
                 * @param {$protobuf.Writer} [writer] Writer to encode to
                 * @returns {$protobuf.Writer} Writer
                 */
                EnergyData.encodeDelimited = function encodeDelimited(message, writer) {
                    return this.encode(message, writer).ldelim();
                };

                /**
                 * Decodes an EnergyData message from the specified reader or buffer.
                 * @function decode
                 * @memberof perfetto.protos.AndroidPowerRails.EnergyData
                 * @static
                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                 * @param {number} [length] Message length if known beforehand
                 * @returns {perfetto.protos.AndroidPowerRails.EnergyData} EnergyData
                 * @throws {Error} If the payload is not a reader or valid buffer
                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
                 */
                EnergyData.decode = function decode(reader, length) {
                    if (!(reader instanceof $Reader))
                        reader = $Reader.create(reader);
                    var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.AndroidPowerRails.EnergyData();
                    while (reader.pos < end) {
                        var tag = reader.uint32();
                        switch (tag >>> 3) {
                        case 1:
                            message.timestampMs = reader.int64();
                            break;
                        case 2:
                            message.energyUws = reader.double();
                            break;
                        default:
                            reader.skipType(tag & 7);
                            break;
                        }
                    }
                    return message;
                };

                /**
                 * Decodes an EnergyData message from the specified reader or buffer, length delimited.
                 * @function decodeDelimited
                 * @memberof perfetto.protos.AndroidPowerRails.EnergyData
                 * @static
                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                 * @returns {perfetto.protos.AndroidPowerRails.EnergyData} EnergyData
                 * @throws {Error} If the payload is not a reader or valid buffer
                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
                 */
                EnergyData.decodeDelimited = function decodeDelimited(reader) {
                    if (!(reader instanceof $Reader))
                        reader = new $Reader(reader);
                    return this.decode(reader, reader.uint32());
                };

                /**
                 * Verifies an EnergyData message.
                 * @function verify
                 * @memberof perfetto.protos.AndroidPowerRails.EnergyData
                 * @static
                 * @param {Object.<string,*>} message Plain object to verify
                 * @returns {string|null} `null` if valid, otherwise the reason why it is not
                 */
                EnergyData.verify = function verify(message) {
                    if (typeof message !== "object" || message === null)
                        return "object expected";
                    if (message.timestampMs != null && message.hasOwnProperty("timestampMs"))
                        if (!$util.isInteger(message.timestampMs) && !(message.timestampMs && $util.isInteger(message.timestampMs.low) && $util.isInteger(message.timestampMs.high)))
                            return "timestampMs: integer|Long expected";
                    if (message.energyUws != null && message.hasOwnProperty("energyUws"))
                        if (typeof message.energyUws !== "number")
                            return "energyUws: number expected";
                    return null;
                };

                /**
                 * Creates an EnergyData message from a plain object. Also converts values to their respective internal types.
                 * @function fromObject
                 * @memberof perfetto.protos.AndroidPowerRails.EnergyData
                 * @static
                 * @param {Object.<string,*>} object Plain object
                 * @returns {perfetto.protos.AndroidPowerRails.EnergyData} EnergyData
                 */
                EnergyData.fromObject = function fromObject(object) {
                    if (object instanceof $root.perfetto.protos.AndroidPowerRails.EnergyData)
                        return object;
                    var message = new $root.perfetto.protos.AndroidPowerRails.EnergyData();
                    if (object.timestampMs != null)
                        if ($util.Long)
                            (message.timestampMs = $util.Long.fromValue(object.timestampMs)).unsigned = false;
                        else if (typeof object.timestampMs === "string")
                            message.timestampMs = parseInt(object.timestampMs, 10);
                        else if (typeof object.timestampMs === "number")
                            message.timestampMs = object.timestampMs;
                        else if (typeof object.timestampMs === "object")
                            message.timestampMs = new $util.LongBits(object.timestampMs.low >>> 0, object.timestampMs.high >>> 0).toNumber();
                    if (object.energyUws != null)
                        message.energyUws = Number(object.energyUws);
                    return message;
                };

                /**
                 * Creates a plain object from an EnergyData message. Also converts values to other types if specified.
                 * @function toObject
                 * @memberof perfetto.protos.AndroidPowerRails.EnergyData
                 * @static
                 * @param {perfetto.protos.AndroidPowerRails.EnergyData} message EnergyData
                 * @param {$protobuf.IConversionOptions} [options] Conversion options
                 * @returns {Object.<string,*>} Plain object
                 */
                EnergyData.toObject = function toObject(message, options) {
                    if (!options)
                        options = {};
                    var object = {};
                    if (options.defaults) {
                        if ($util.Long) {
                            var long = new $util.Long(0, 0, false);
                            object.timestampMs = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
                        } else
                            object.timestampMs = options.longs === String ? "0" : 0;
                        object.energyUws = 0;
                    }
                    if (message.timestampMs != null && message.hasOwnProperty("timestampMs"))
                        if (typeof message.timestampMs === "number")
                            object.timestampMs = options.longs === String ? String(message.timestampMs) : message.timestampMs;
                        else
                            object.timestampMs = options.longs === String ? $util.Long.prototype.toString.call(message.timestampMs) : options.longs === Number ? new $util.LongBits(message.timestampMs.low >>> 0, message.timestampMs.high >>> 0).toNumber() : message.timestampMs;
                    if (message.energyUws != null && message.hasOwnProperty("energyUws"))
                        object.energyUws = options.json && !isFinite(message.energyUws) ? String(message.energyUws) : message.energyUws;
                    return object;
                };

                /**
                 * Converts this EnergyData to JSON.
                 * @function toJSON
                 * @memberof perfetto.protos.AndroidPowerRails.EnergyData
                 * @instance
                 * @returns {Object.<string,*>} JSON object
                 */
                EnergyData.prototype.toJSON = function toJSON() {
                    return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
                };

                return EnergyData;
            })();

            AndroidPowerRails.PowerRails = (function() {

                /**
                 * Properties of a PowerRails.
                 * @memberof perfetto.protos.AndroidPowerRails
                 * @interface IPowerRails
                 * @property {string|null} [name] PowerRails name
                 * @property {Array.<perfetto.protos.AndroidPowerRails.IEnergyData>|null} [energyData] PowerRails energyData
                 */

                /**
                 * Constructs a new PowerRails.
                 * @memberof perfetto.protos.AndroidPowerRails
                 * @classdesc Represents a PowerRails.
                 * @implements IPowerRails
                 * @constructor
                 * @param {perfetto.protos.AndroidPowerRails.IPowerRails=} [properties] Properties to set
                 */
                function PowerRails(properties) {
                    this.energyData = [];
                    if (properties)
                        for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                            if (properties[keys[i]] != null)
                                this[keys[i]] = properties[keys[i]];
                }

                /**
                 * PowerRails name.
                 * @member {string} name
                 * @memberof perfetto.protos.AndroidPowerRails.PowerRails
                 * @instance
                 */
                PowerRails.prototype.name = "";

                /**
                 * PowerRails energyData.
                 * @member {Array.<perfetto.protos.AndroidPowerRails.IEnergyData>} energyData
                 * @memberof perfetto.protos.AndroidPowerRails.PowerRails
                 * @instance
                 */
                PowerRails.prototype.energyData = $util.emptyArray;

                /**
                 * Creates a new PowerRails instance using the specified properties.
                 * @function create
                 * @memberof perfetto.protos.AndroidPowerRails.PowerRails
                 * @static
                 * @param {perfetto.protos.AndroidPowerRails.IPowerRails=} [properties] Properties to set
                 * @returns {perfetto.protos.AndroidPowerRails.PowerRails} PowerRails instance
                 */
                PowerRails.create = function create(properties) {
                    return new PowerRails(properties);
                };

                /**
                 * Encodes the specified PowerRails message. Does not implicitly {@link perfetto.protos.AndroidPowerRails.PowerRails.verify|verify} messages.
                 * @function encode
                 * @memberof perfetto.protos.AndroidPowerRails.PowerRails
                 * @static
                 * @param {perfetto.protos.AndroidPowerRails.IPowerRails} message PowerRails message or plain object to encode
                 * @param {$protobuf.Writer} [writer] Writer to encode to
                 * @returns {$protobuf.Writer} Writer
                 */
                PowerRails.encode = function encode(message, writer) {
                    if (!writer)
                        writer = $Writer.create();
                    if (message.name != null && Object.hasOwnProperty.call(message, "name"))
                        writer.uint32(/* id 1, wireType 2 =*/10).string(message.name);
                    if (message.energyData != null && message.energyData.length)
                        for (var i = 0; i < message.energyData.length; ++i)
                            $root.perfetto.protos.AndroidPowerRails.EnergyData.encode(message.energyData[i], writer.uint32(/* id 2, wireType 2 =*/18).fork()).ldelim();
                    return writer;
                };

                /**
                 * Encodes the specified PowerRails message, length delimited. Does not implicitly {@link perfetto.protos.AndroidPowerRails.PowerRails.verify|verify} messages.
                 * @function encodeDelimited
                 * @memberof perfetto.protos.AndroidPowerRails.PowerRails
                 * @static
                 * @param {perfetto.protos.AndroidPowerRails.IPowerRails} message PowerRails message or plain object to encode
                 * @param {$protobuf.Writer} [writer] Writer to encode to
                 * @returns {$protobuf.Writer} Writer
                 */
                PowerRails.encodeDelimited = function encodeDelimited(message, writer) {
                    return this.encode(message, writer).ldelim();
                };

                /**
                 * Decodes a PowerRails message from the specified reader or buffer.
                 * @function decode
                 * @memberof perfetto.protos.AndroidPowerRails.PowerRails
                 * @static
                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                 * @param {number} [length] Message length if known beforehand
                 * @returns {perfetto.protos.AndroidPowerRails.PowerRails} PowerRails
                 * @throws {Error} If the payload is not a reader or valid buffer
                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
                 */
                PowerRails.decode = function decode(reader, length) {
                    if (!(reader instanceof $Reader))
                        reader = $Reader.create(reader);
                    var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.AndroidPowerRails.PowerRails();
                    while (reader.pos < end) {
                        var tag = reader.uint32();
                        switch (tag >>> 3) {
                        case 1:
                            message.name = reader.string();
                            break;
                        case 2:
                            if (!(message.energyData && message.energyData.length))
                                message.energyData = [];
                            message.energyData.push($root.perfetto.protos.AndroidPowerRails.EnergyData.decode(reader, reader.uint32()));
                            break;
                        default:
                            reader.skipType(tag & 7);
                            break;
                        }
                    }
                    return message;
                };

                /**
                 * Decodes a PowerRails message from the specified reader or buffer, length delimited.
                 * @function decodeDelimited
                 * @memberof perfetto.protos.AndroidPowerRails.PowerRails
                 * @static
                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                 * @returns {perfetto.protos.AndroidPowerRails.PowerRails} PowerRails
                 * @throws {Error} If the payload is not a reader or valid buffer
                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
                 */
                PowerRails.decodeDelimited = function decodeDelimited(reader) {
                    if (!(reader instanceof $Reader))
                        reader = new $Reader(reader);
                    return this.decode(reader, reader.uint32());
                };

                /**
                 * Verifies a PowerRails message.
                 * @function verify
                 * @memberof perfetto.protos.AndroidPowerRails.PowerRails
                 * @static
                 * @param {Object.<string,*>} message Plain object to verify
                 * @returns {string|null} `null` if valid, otherwise the reason why it is not
                 */
                PowerRails.verify = function verify(message) {
                    if (typeof message !== "object" || message === null)
                        return "object expected";
                    if (message.name != null && message.hasOwnProperty("name"))
                        if (!$util.isString(message.name))
                            return "name: string expected";
                    if (message.energyData != null && message.hasOwnProperty("energyData")) {
                        if (!Array.isArray(message.energyData))
                            return "energyData: array expected";
                        for (var i = 0; i < message.energyData.length; ++i) {
                            var error = $root.perfetto.protos.AndroidPowerRails.EnergyData.verify(message.energyData[i]);
                            if (error)
                                return "energyData." + error;
                        }
                    }
                    return null;
                };

                /**
                 * Creates a PowerRails message from a plain object. Also converts values to their respective internal types.
                 * @function fromObject
                 * @memberof perfetto.protos.AndroidPowerRails.PowerRails
                 * @static
                 * @param {Object.<string,*>} object Plain object
                 * @returns {perfetto.protos.AndroidPowerRails.PowerRails} PowerRails
                 */
                PowerRails.fromObject = function fromObject(object) {
                    if (object instanceof $root.perfetto.protos.AndroidPowerRails.PowerRails)
                        return object;
                    var message = new $root.perfetto.protos.AndroidPowerRails.PowerRails();
                    if (object.name != null)
                        message.name = String(object.name);
                    if (object.energyData) {
                        if (!Array.isArray(object.energyData))
                            throw TypeError(".perfetto.protos.AndroidPowerRails.PowerRails.energyData: array expected");
                        message.energyData = [];
                        for (var i = 0; i < object.energyData.length; ++i) {
                            if (typeof object.energyData[i] !== "object")
                                throw TypeError(".perfetto.protos.AndroidPowerRails.PowerRails.energyData: object expected");
                            message.energyData[i] = $root.perfetto.protos.AndroidPowerRails.EnergyData.fromObject(object.energyData[i]);
                        }
                    }
                    return message;
                };

                /**
                 * Creates a plain object from a PowerRails message. Also converts values to other types if specified.
                 * @function toObject
                 * @memberof perfetto.protos.AndroidPowerRails.PowerRails
                 * @static
                 * @param {perfetto.protos.AndroidPowerRails.PowerRails} message PowerRails
                 * @param {$protobuf.IConversionOptions} [options] Conversion options
                 * @returns {Object.<string,*>} Plain object
                 */
                PowerRails.toObject = function toObject(message, options) {
                    if (!options)
                        options = {};
                    var object = {};
                    if (options.arrays || options.defaults)
                        object.energyData = [];
                    if (options.defaults)
                        object.name = "";
                    if (message.name != null && message.hasOwnProperty("name"))
                        object.name = message.name;
                    if (message.energyData && message.energyData.length) {
                        object.energyData = [];
                        for (var j = 0; j < message.energyData.length; ++j)
                            object.energyData[j] = $root.perfetto.protos.AndroidPowerRails.EnergyData.toObject(message.energyData[j], options);
                    }
                    return object;
                };

                /**
                 * Converts this PowerRails to JSON.
                 * @function toJSON
                 * @memberof perfetto.protos.AndroidPowerRails.PowerRails
                 * @instance
                 * @returns {Object.<string,*>} JSON object
                 */
                PowerRails.prototype.toJSON = function toJSON() {
                    return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
                };

                return PowerRails;
            })();

            return AndroidPowerRails;
        })();

        protos.AndroidStartupMetric = (function() {

            /**
             * Properties of an AndroidStartupMetric.
             * @memberof perfetto.protos
             * @interface IAndroidStartupMetric
             * @property {Array.<perfetto.protos.AndroidStartupMetric.IStartup>|null} [startup] AndroidStartupMetric startup
             */

            /**
             * Constructs a new AndroidStartupMetric.
             * @memberof perfetto.protos
             * @classdesc Represents an AndroidStartupMetric.
             * @implements IAndroidStartupMetric
             * @constructor
             * @param {perfetto.protos.IAndroidStartupMetric=} [properties] Properties to set
             */
            function AndroidStartupMetric(properties) {
                this.startup = [];
                if (properties)
                    for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                        if (properties[keys[i]] != null)
                            this[keys[i]] = properties[keys[i]];
            }

            /**
             * AndroidStartupMetric startup.
             * @member {Array.<perfetto.protos.AndroidStartupMetric.IStartup>} startup
             * @memberof perfetto.protos.AndroidStartupMetric
             * @instance
             */
            AndroidStartupMetric.prototype.startup = $util.emptyArray;

            /**
             * Creates a new AndroidStartupMetric instance using the specified properties.
             * @function create
             * @memberof perfetto.protos.AndroidStartupMetric
             * @static
             * @param {perfetto.protos.IAndroidStartupMetric=} [properties] Properties to set
             * @returns {perfetto.protos.AndroidStartupMetric} AndroidStartupMetric instance
             */
            AndroidStartupMetric.create = function create(properties) {
                return new AndroidStartupMetric(properties);
            };

            /**
             * Encodes the specified AndroidStartupMetric message. Does not implicitly {@link perfetto.protos.AndroidStartupMetric.verify|verify} messages.
             * @function encode
             * @memberof perfetto.protos.AndroidStartupMetric
             * @static
             * @param {perfetto.protos.IAndroidStartupMetric} message AndroidStartupMetric message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            AndroidStartupMetric.encode = function encode(message, writer) {
                if (!writer)
                    writer = $Writer.create();
                if (message.startup != null && message.startup.length)
                    for (var i = 0; i < message.startup.length; ++i)
                        $root.perfetto.protos.AndroidStartupMetric.Startup.encode(message.startup[i], writer.uint32(/* id 1, wireType 2 =*/10).fork()).ldelim();
                return writer;
            };

            /**
             * Encodes the specified AndroidStartupMetric message, length delimited. Does not implicitly {@link perfetto.protos.AndroidStartupMetric.verify|verify} messages.
             * @function encodeDelimited
             * @memberof perfetto.protos.AndroidStartupMetric
             * @static
             * @param {perfetto.protos.IAndroidStartupMetric} message AndroidStartupMetric message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            AndroidStartupMetric.encodeDelimited = function encodeDelimited(message, writer) {
                return this.encode(message, writer).ldelim();
            };

            /**
             * Decodes an AndroidStartupMetric message from the specified reader or buffer.
             * @function decode
             * @memberof perfetto.protos.AndroidStartupMetric
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @param {number} [length] Message length if known beforehand
             * @returns {perfetto.protos.AndroidStartupMetric} AndroidStartupMetric
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            AndroidStartupMetric.decode = function decode(reader, length) {
                if (!(reader instanceof $Reader))
                    reader = $Reader.create(reader);
                var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.AndroidStartupMetric();
                while (reader.pos < end) {
                    var tag = reader.uint32();
                    switch (tag >>> 3) {
                    case 1:
                        if (!(message.startup && message.startup.length))
                            message.startup = [];
                        message.startup.push($root.perfetto.protos.AndroidStartupMetric.Startup.decode(reader, reader.uint32()));
                        break;
                    default:
                        reader.skipType(tag & 7);
                        break;
                    }
                }
                return message;
            };

            /**
             * Decodes an AndroidStartupMetric message from the specified reader or buffer, length delimited.
             * @function decodeDelimited
             * @memberof perfetto.protos.AndroidStartupMetric
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @returns {perfetto.protos.AndroidStartupMetric} AndroidStartupMetric
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            AndroidStartupMetric.decodeDelimited = function decodeDelimited(reader) {
                if (!(reader instanceof $Reader))
                    reader = new $Reader(reader);
                return this.decode(reader, reader.uint32());
            };

            /**
             * Verifies an AndroidStartupMetric message.
             * @function verify
             * @memberof perfetto.protos.AndroidStartupMetric
             * @static
             * @param {Object.<string,*>} message Plain object to verify
             * @returns {string|null} `null` if valid, otherwise the reason why it is not
             */
            AndroidStartupMetric.verify = function verify(message) {
                if (typeof message !== "object" || message === null)
                    return "object expected";
                if (message.startup != null && message.hasOwnProperty("startup")) {
                    if (!Array.isArray(message.startup))
                        return "startup: array expected";
                    for (var i = 0; i < message.startup.length; ++i) {
                        var error = $root.perfetto.protos.AndroidStartupMetric.Startup.verify(message.startup[i]);
                        if (error)
                            return "startup." + error;
                    }
                }
                return null;
            };

            /**
             * Creates an AndroidStartupMetric message from a plain object. Also converts values to their respective internal types.
             * @function fromObject
             * @memberof perfetto.protos.AndroidStartupMetric
             * @static
             * @param {Object.<string,*>} object Plain object
             * @returns {perfetto.protos.AndroidStartupMetric} AndroidStartupMetric
             */
            AndroidStartupMetric.fromObject = function fromObject(object) {
                if (object instanceof $root.perfetto.protos.AndroidStartupMetric)
                    return object;
                var message = new $root.perfetto.protos.AndroidStartupMetric();
                if (object.startup) {
                    if (!Array.isArray(object.startup))
                        throw TypeError(".perfetto.protos.AndroidStartupMetric.startup: array expected");
                    message.startup = [];
                    for (var i = 0; i < object.startup.length; ++i) {
                        if (typeof object.startup[i] !== "object")
                            throw TypeError(".perfetto.protos.AndroidStartupMetric.startup: object expected");
                        message.startup[i] = $root.perfetto.protos.AndroidStartupMetric.Startup.fromObject(object.startup[i]);
                    }
                }
                return message;
            };

            /**
             * Creates a plain object from an AndroidStartupMetric message. Also converts values to other types if specified.
             * @function toObject
             * @memberof perfetto.protos.AndroidStartupMetric
             * @static
             * @param {perfetto.protos.AndroidStartupMetric} message AndroidStartupMetric
             * @param {$protobuf.IConversionOptions} [options] Conversion options
             * @returns {Object.<string,*>} Plain object
             */
            AndroidStartupMetric.toObject = function toObject(message, options) {
                if (!options)
                    options = {};
                var object = {};
                if (options.arrays || options.defaults)
                    object.startup = [];
                if (message.startup && message.startup.length) {
                    object.startup = [];
                    for (var j = 0; j < message.startup.length; ++j)
                        object.startup[j] = $root.perfetto.protos.AndroidStartupMetric.Startup.toObject(message.startup[j], options);
                }
                return object;
            };

            /**
             * Converts this AndroidStartupMetric to JSON.
             * @function toJSON
             * @memberof perfetto.protos.AndroidStartupMetric
             * @instance
             * @returns {Object.<string,*>} JSON object
             */
            AndroidStartupMetric.prototype.toJSON = function toJSON() {
                return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
            };

            AndroidStartupMetric.TaskStateBreakdown = (function() {

                /**
                 * Properties of a TaskStateBreakdown.
                 * @memberof perfetto.protos.AndroidStartupMetric
                 * @interface ITaskStateBreakdown
                 * @property {number|null} [runningDurNs] TaskStateBreakdown runningDurNs
                 * @property {number|null} [runnableDurNs] TaskStateBreakdown runnableDurNs
                 * @property {number|null} [uninterruptibleSleepDurNs] TaskStateBreakdown uninterruptibleSleepDurNs
                 * @property {number|null} [interruptibleSleepDurNs] TaskStateBreakdown interruptibleSleepDurNs
                 */

                /**
                 * Constructs a new TaskStateBreakdown.
                 * @memberof perfetto.protos.AndroidStartupMetric
                 * @classdesc Represents a TaskStateBreakdown.
                 * @implements ITaskStateBreakdown
                 * @constructor
                 * @param {perfetto.protos.AndroidStartupMetric.ITaskStateBreakdown=} [properties] Properties to set
                 */
                function TaskStateBreakdown(properties) {
                    if (properties)
                        for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                            if (properties[keys[i]] != null)
                                this[keys[i]] = properties[keys[i]];
                }

                /**
                 * TaskStateBreakdown runningDurNs.
                 * @member {number} runningDurNs
                 * @memberof perfetto.protos.AndroidStartupMetric.TaskStateBreakdown
                 * @instance
                 */
                TaskStateBreakdown.prototype.runningDurNs = $util.Long ? $util.Long.fromBits(0,0,false) : 0;

                /**
                 * TaskStateBreakdown runnableDurNs.
                 * @member {number} runnableDurNs
                 * @memberof perfetto.protos.AndroidStartupMetric.TaskStateBreakdown
                 * @instance
                 */
                TaskStateBreakdown.prototype.runnableDurNs = $util.Long ? $util.Long.fromBits(0,0,false) : 0;

                /**
                 * TaskStateBreakdown uninterruptibleSleepDurNs.
                 * @member {number} uninterruptibleSleepDurNs
                 * @memberof perfetto.protos.AndroidStartupMetric.TaskStateBreakdown
                 * @instance
                 */
                TaskStateBreakdown.prototype.uninterruptibleSleepDurNs = $util.Long ? $util.Long.fromBits(0,0,false) : 0;

                /**
                 * TaskStateBreakdown interruptibleSleepDurNs.
                 * @member {number} interruptibleSleepDurNs
                 * @memberof perfetto.protos.AndroidStartupMetric.TaskStateBreakdown
                 * @instance
                 */
                TaskStateBreakdown.prototype.interruptibleSleepDurNs = $util.Long ? $util.Long.fromBits(0,0,false) : 0;

                /**
                 * Creates a new TaskStateBreakdown instance using the specified properties.
                 * @function create
                 * @memberof perfetto.protos.AndroidStartupMetric.TaskStateBreakdown
                 * @static
                 * @param {perfetto.protos.AndroidStartupMetric.ITaskStateBreakdown=} [properties] Properties to set
                 * @returns {perfetto.protos.AndroidStartupMetric.TaskStateBreakdown} TaskStateBreakdown instance
                 */
                TaskStateBreakdown.create = function create(properties) {
                    return new TaskStateBreakdown(properties);
                };

                /**
                 * Encodes the specified TaskStateBreakdown message. Does not implicitly {@link perfetto.protos.AndroidStartupMetric.TaskStateBreakdown.verify|verify} messages.
                 * @function encode
                 * @memberof perfetto.protos.AndroidStartupMetric.TaskStateBreakdown
                 * @static
                 * @param {perfetto.protos.AndroidStartupMetric.ITaskStateBreakdown} message TaskStateBreakdown message or plain object to encode
                 * @param {$protobuf.Writer} [writer] Writer to encode to
                 * @returns {$protobuf.Writer} Writer
                 */
                TaskStateBreakdown.encode = function encode(message, writer) {
                    if (!writer)
                        writer = $Writer.create();
                    if (message.runningDurNs != null && Object.hasOwnProperty.call(message, "runningDurNs"))
                        writer.uint32(/* id 1, wireType 0 =*/8).int64(message.runningDurNs);
                    if (message.runnableDurNs != null && Object.hasOwnProperty.call(message, "runnableDurNs"))
                        writer.uint32(/* id 2, wireType 0 =*/16).int64(message.runnableDurNs);
                    if (message.uninterruptibleSleepDurNs != null && Object.hasOwnProperty.call(message, "uninterruptibleSleepDurNs"))
                        writer.uint32(/* id 3, wireType 0 =*/24).int64(message.uninterruptibleSleepDurNs);
                    if (message.interruptibleSleepDurNs != null && Object.hasOwnProperty.call(message, "interruptibleSleepDurNs"))
                        writer.uint32(/* id 4, wireType 0 =*/32).int64(message.interruptibleSleepDurNs);
                    return writer;
                };

                /**
                 * Encodes the specified TaskStateBreakdown message, length delimited. Does not implicitly {@link perfetto.protos.AndroidStartupMetric.TaskStateBreakdown.verify|verify} messages.
                 * @function encodeDelimited
                 * @memberof perfetto.protos.AndroidStartupMetric.TaskStateBreakdown
                 * @static
                 * @param {perfetto.protos.AndroidStartupMetric.ITaskStateBreakdown} message TaskStateBreakdown message or plain object to encode
                 * @param {$protobuf.Writer} [writer] Writer to encode to
                 * @returns {$protobuf.Writer} Writer
                 */
                TaskStateBreakdown.encodeDelimited = function encodeDelimited(message, writer) {
                    return this.encode(message, writer).ldelim();
                };

                /**
                 * Decodes a TaskStateBreakdown message from the specified reader or buffer.
                 * @function decode
                 * @memberof perfetto.protos.AndroidStartupMetric.TaskStateBreakdown
                 * @static
                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                 * @param {number} [length] Message length if known beforehand
                 * @returns {perfetto.protos.AndroidStartupMetric.TaskStateBreakdown} TaskStateBreakdown
                 * @throws {Error} If the payload is not a reader or valid buffer
                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
                 */
                TaskStateBreakdown.decode = function decode(reader, length) {
                    if (!(reader instanceof $Reader))
                        reader = $Reader.create(reader);
                    var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.AndroidStartupMetric.TaskStateBreakdown();
                    while (reader.pos < end) {
                        var tag = reader.uint32();
                        switch (tag >>> 3) {
                        case 1:
                            message.runningDurNs = reader.int64();
                            break;
                        case 2:
                            message.runnableDurNs = reader.int64();
                            break;
                        case 3:
                            message.uninterruptibleSleepDurNs = reader.int64();
                            break;
                        case 4:
                            message.interruptibleSleepDurNs = reader.int64();
                            break;
                        default:
                            reader.skipType(tag & 7);
                            break;
                        }
                    }
                    return message;
                };

                /**
                 * Decodes a TaskStateBreakdown message from the specified reader or buffer, length delimited.
                 * @function decodeDelimited
                 * @memberof perfetto.protos.AndroidStartupMetric.TaskStateBreakdown
                 * @static
                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                 * @returns {perfetto.protos.AndroidStartupMetric.TaskStateBreakdown} TaskStateBreakdown
                 * @throws {Error} If the payload is not a reader or valid buffer
                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
                 */
                TaskStateBreakdown.decodeDelimited = function decodeDelimited(reader) {
                    if (!(reader instanceof $Reader))
                        reader = new $Reader(reader);
                    return this.decode(reader, reader.uint32());
                };

                /**
                 * Verifies a TaskStateBreakdown message.
                 * @function verify
                 * @memberof perfetto.protos.AndroidStartupMetric.TaskStateBreakdown
                 * @static
                 * @param {Object.<string,*>} message Plain object to verify
                 * @returns {string|null} `null` if valid, otherwise the reason why it is not
                 */
                TaskStateBreakdown.verify = function verify(message) {
                    if (typeof message !== "object" || message === null)
                        return "object expected";
                    if (message.runningDurNs != null && message.hasOwnProperty("runningDurNs"))
                        if (!$util.isInteger(message.runningDurNs) && !(message.runningDurNs && $util.isInteger(message.runningDurNs.low) && $util.isInteger(message.runningDurNs.high)))
                            return "runningDurNs: integer|Long expected";
                    if (message.runnableDurNs != null && message.hasOwnProperty("runnableDurNs"))
                        if (!$util.isInteger(message.runnableDurNs) && !(message.runnableDurNs && $util.isInteger(message.runnableDurNs.low) && $util.isInteger(message.runnableDurNs.high)))
                            return "runnableDurNs: integer|Long expected";
                    if (message.uninterruptibleSleepDurNs != null && message.hasOwnProperty("uninterruptibleSleepDurNs"))
                        if (!$util.isInteger(message.uninterruptibleSleepDurNs) && !(message.uninterruptibleSleepDurNs && $util.isInteger(message.uninterruptibleSleepDurNs.low) && $util.isInteger(message.uninterruptibleSleepDurNs.high)))
                            return "uninterruptibleSleepDurNs: integer|Long expected";
                    if (message.interruptibleSleepDurNs != null && message.hasOwnProperty("interruptibleSleepDurNs"))
                        if (!$util.isInteger(message.interruptibleSleepDurNs) && !(message.interruptibleSleepDurNs && $util.isInteger(message.interruptibleSleepDurNs.low) && $util.isInteger(message.interruptibleSleepDurNs.high)))
                            return "interruptibleSleepDurNs: integer|Long expected";
                    return null;
                };

                /**
                 * Creates a TaskStateBreakdown message from a plain object. Also converts values to their respective internal types.
                 * @function fromObject
                 * @memberof perfetto.protos.AndroidStartupMetric.TaskStateBreakdown
                 * @static
                 * @param {Object.<string,*>} object Plain object
                 * @returns {perfetto.protos.AndroidStartupMetric.TaskStateBreakdown} TaskStateBreakdown
                 */
                TaskStateBreakdown.fromObject = function fromObject(object) {
                    if (object instanceof $root.perfetto.protos.AndroidStartupMetric.TaskStateBreakdown)
                        return object;
                    var message = new $root.perfetto.protos.AndroidStartupMetric.TaskStateBreakdown();
                    if (object.runningDurNs != null)
                        if ($util.Long)
                            (message.runningDurNs = $util.Long.fromValue(object.runningDurNs)).unsigned = false;
                        else if (typeof object.runningDurNs === "string")
                            message.runningDurNs = parseInt(object.runningDurNs, 10);
                        else if (typeof object.runningDurNs === "number")
                            message.runningDurNs = object.runningDurNs;
                        else if (typeof object.runningDurNs === "object")
                            message.runningDurNs = new $util.LongBits(object.runningDurNs.low >>> 0, object.runningDurNs.high >>> 0).toNumber();
                    if (object.runnableDurNs != null)
                        if ($util.Long)
                            (message.runnableDurNs = $util.Long.fromValue(object.runnableDurNs)).unsigned = false;
                        else if (typeof object.runnableDurNs === "string")
                            message.runnableDurNs = parseInt(object.runnableDurNs, 10);
                        else if (typeof object.runnableDurNs === "number")
                            message.runnableDurNs = object.runnableDurNs;
                        else if (typeof object.runnableDurNs === "object")
                            message.runnableDurNs = new $util.LongBits(object.runnableDurNs.low >>> 0, object.runnableDurNs.high >>> 0).toNumber();
                    if (object.uninterruptibleSleepDurNs != null)
                        if ($util.Long)
                            (message.uninterruptibleSleepDurNs = $util.Long.fromValue(object.uninterruptibleSleepDurNs)).unsigned = false;
                        else if (typeof object.uninterruptibleSleepDurNs === "string")
                            message.uninterruptibleSleepDurNs = parseInt(object.uninterruptibleSleepDurNs, 10);
                        else if (typeof object.uninterruptibleSleepDurNs === "number")
                            message.uninterruptibleSleepDurNs = object.uninterruptibleSleepDurNs;
                        else if (typeof object.uninterruptibleSleepDurNs === "object")
                            message.uninterruptibleSleepDurNs = new $util.LongBits(object.uninterruptibleSleepDurNs.low >>> 0, object.uninterruptibleSleepDurNs.high >>> 0).toNumber();
                    if (object.interruptibleSleepDurNs != null)
                        if ($util.Long)
                            (message.interruptibleSleepDurNs = $util.Long.fromValue(object.interruptibleSleepDurNs)).unsigned = false;
                        else if (typeof object.interruptibleSleepDurNs === "string")
                            message.interruptibleSleepDurNs = parseInt(object.interruptibleSleepDurNs, 10);
                        else if (typeof object.interruptibleSleepDurNs === "number")
                            message.interruptibleSleepDurNs = object.interruptibleSleepDurNs;
                        else if (typeof object.interruptibleSleepDurNs === "object")
                            message.interruptibleSleepDurNs = new $util.LongBits(object.interruptibleSleepDurNs.low >>> 0, object.interruptibleSleepDurNs.high >>> 0).toNumber();
                    return message;
                };

                /**
                 * Creates a plain object from a TaskStateBreakdown message. Also converts values to other types if specified.
                 * @function toObject
                 * @memberof perfetto.protos.AndroidStartupMetric.TaskStateBreakdown
                 * @static
                 * @param {perfetto.protos.AndroidStartupMetric.TaskStateBreakdown} message TaskStateBreakdown
                 * @param {$protobuf.IConversionOptions} [options] Conversion options
                 * @returns {Object.<string,*>} Plain object
                 */
                TaskStateBreakdown.toObject = function toObject(message, options) {
                    if (!options)
                        options = {};
                    var object = {};
                    if (options.defaults) {
                        if ($util.Long) {
                            var long = new $util.Long(0, 0, false);
                            object.runningDurNs = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
                        } else
                            object.runningDurNs = options.longs === String ? "0" : 0;
                        if ($util.Long) {
                            var long = new $util.Long(0, 0, false);
                            object.runnableDurNs = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
                        } else
                            object.runnableDurNs = options.longs === String ? "0" : 0;
                        if ($util.Long) {
                            var long = new $util.Long(0, 0, false);
                            object.uninterruptibleSleepDurNs = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
                        } else
                            object.uninterruptibleSleepDurNs = options.longs === String ? "0" : 0;
                        if ($util.Long) {
                            var long = new $util.Long(0, 0, false);
                            object.interruptibleSleepDurNs = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
                        } else
                            object.interruptibleSleepDurNs = options.longs === String ? "0" : 0;
                    }
                    if (message.runningDurNs != null && message.hasOwnProperty("runningDurNs"))
                        if (typeof message.runningDurNs === "number")
                            object.runningDurNs = options.longs === String ? String(message.runningDurNs) : message.runningDurNs;
                        else
                            object.runningDurNs = options.longs === String ? $util.Long.prototype.toString.call(message.runningDurNs) : options.longs === Number ? new $util.LongBits(message.runningDurNs.low >>> 0, message.runningDurNs.high >>> 0).toNumber() : message.runningDurNs;
                    if (message.runnableDurNs != null && message.hasOwnProperty("runnableDurNs"))
                        if (typeof message.runnableDurNs === "number")
                            object.runnableDurNs = options.longs === String ? String(message.runnableDurNs) : message.runnableDurNs;
                        else
                            object.runnableDurNs = options.longs === String ? $util.Long.prototype.toString.call(message.runnableDurNs) : options.longs === Number ? new $util.LongBits(message.runnableDurNs.low >>> 0, message.runnableDurNs.high >>> 0).toNumber() : message.runnableDurNs;
                    if (message.uninterruptibleSleepDurNs != null && message.hasOwnProperty("uninterruptibleSleepDurNs"))
                        if (typeof message.uninterruptibleSleepDurNs === "number")
                            object.uninterruptibleSleepDurNs = options.longs === String ? String(message.uninterruptibleSleepDurNs) : message.uninterruptibleSleepDurNs;
                        else
                            object.uninterruptibleSleepDurNs = options.longs === String ? $util.Long.prototype.toString.call(message.uninterruptibleSleepDurNs) : options.longs === Number ? new $util.LongBits(message.uninterruptibleSleepDurNs.low >>> 0, message.uninterruptibleSleepDurNs.high >>> 0).toNumber() : message.uninterruptibleSleepDurNs;
                    if (message.interruptibleSleepDurNs != null && message.hasOwnProperty("interruptibleSleepDurNs"))
                        if (typeof message.interruptibleSleepDurNs === "number")
                            object.interruptibleSleepDurNs = options.longs === String ? String(message.interruptibleSleepDurNs) : message.interruptibleSleepDurNs;
                        else
                            object.interruptibleSleepDurNs = options.longs === String ? $util.Long.prototype.toString.call(message.interruptibleSleepDurNs) : options.longs === Number ? new $util.LongBits(message.interruptibleSleepDurNs.low >>> 0, message.interruptibleSleepDurNs.high >>> 0).toNumber() : message.interruptibleSleepDurNs;
                    return object;
                };

                /**
                 * Converts this TaskStateBreakdown to JSON.
                 * @function toJSON
                 * @memberof perfetto.protos.AndroidStartupMetric.TaskStateBreakdown
                 * @instance
                 * @returns {Object.<string,*>} JSON object
                 */
                TaskStateBreakdown.prototype.toJSON = function toJSON() {
                    return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
                };

                return TaskStateBreakdown;
            })();

            AndroidStartupMetric.McyclesByCoreType = (function() {

                /**
                 * Properties of a McyclesByCoreType.
                 * @memberof perfetto.protos.AndroidStartupMetric
                 * @interface IMcyclesByCoreType
                 * @property {number|null} [little] McyclesByCoreType little
                 * @property {number|null} [big] McyclesByCoreType big
                 * @property {number|null} [bigger] McyclesByCoreType bigger
                 * @property {number|null} [unknown] McyclesByCoreType unknown
                 */

                /**
                 * Constructs a new McyclesByCoreType.
                 * @memberof perfetto.protos.AndroidStartupMetric
                 * @classdesc Represents a McyclesByCoreType.
                 * @implements IMcyclesByCoreType
                 * @constructor
                 * @param {perfetto.protos.AndroidStartupMetric.IMcyclesByCoreType=} [properties] Properties to set
                 */
                function McyclesByCoreType(properties) {
                    if (properties)
                        for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                            if (properties[keys[i]] != null)
                                this[keys[i]] = properties[keys[i]];
                }

                /**
                 * McyclesByCoreType little.
                 * @member {number} little
                 * @memberof perfetto.protos.AndroidStartupMetric.McyclesByCoreType
                 * @instance
                 */
                McyclesByCoreType.prototype.little = $util.Long ? $util.Long.fromBits(0,0,false) : 0;

                /**
                 * McyclesByCoreType big.
                 * @member {number} big
                 * @memberof perfetto.protos.AndroidStartupMetric.McyclesByCoreType
                 * @instance
                 */
                McyclesByCoreType.prototype.big = $util.Long ? $util.Long.fromBits(0,0,false) : 0;

                /**
                 * McyclesByCoreType bigger.
                 * @member {number} bigger
                 * @memberof perfetto.protos.AndroidStartupMetric.McyclesByCoreType
                 * @instance
                 */
                McyclesByCoreType.prototype.bigger = $util.Long ? $util.Long.fromBits(0,0,false) : 0;

                /**
                 * McyclesByCoreType unknown.
                 * @member {number} unknown
                 * @memberof perfetto.protos.AndroidStartupMetric.McyclesByCoreType
                 * @instance
                 */
                McyclesByCoreType.prototype.unknown = $util.Long ? $util.Long.fromBits(0,0,false) : 0;

                /**
                 * Creates a new McyclesByCoreType instance using the specified properties.
                 * @function create
                 * @memberof perfetto.protos.AndroidStartupMetric.McyclesByCoreType
                 * @static
                 * @param {perfetto.protos.AndroidStartupMetric.IMcyclesByCoreType=} [properties] Properties to set
                 * @returns {perfetto.protos.AndroidStartupMetric.McyclesByCoreType} McyclesByCoreType instance
                 */
                McyclesByCoreType.create = function create(properties) {
                    return new McyclesByCoreType(properties);
                };

                /**
                 * Encodes the specified McyclesByCoreType message. Does not implicitly {@link perfetto.protos.AndroidStartupMetric.McyclesByCoreType.verify|verify} messages.
                 * @function encode
                 * @memberof perfetto.protos.AndroidStartupMetric.McyclesByCoreType
                 * @static
                 * @param {perfetto.protos.AndroidStartupMetric.IMcyclesByCoreType} message McyclesByCoreType message or plain object to encode
                 * @param {$protobuf.Writer} [writer] Writer to encode to
                 * @returns {$protobuf.Writer} Writer
                 */
                McyclesByCoreType.encode = function encode(message, writer) {
                    if (!writer)
                        writer = $Writer.create();
                    if (message.little != null && Object.hasOwnProperty.call(message, "little"))
                        writer.uint32(/* id 1, wireType 0 =*/8).int64(message.little);
                    if (message.big != null && Object.hasOwnProperty.call(message, "big"))
                        writer.uint32(/* id 2, wireType 0 =*/16).int64(message.big);
                    if (message.bigger != null && Object.hasOwnProperty.call(message, "bigger"))
                        writer.uint32(/* id 3, wireType 0 =*/24).int64(message.bigger);
                    if (message.unknown != null && Object.hasOwnProperty.call(message, "unknown"))
                        writer.uint32(/* id 4, wireType 0 =*/32).int64(message.unknown);
                    return writer;
                };

                /**
                 * Encodes the specified McyclesByCoreType message, length delimited. Does not implicitly {@link perfetto.protos.AndroidStartupMetric.McyclesByCoreType.verify|verify} messages.
                 * @function encodeDelimited
                 * @memberof perfetto.protos.AndroidStartupMetric.McyclesByCoreType
                 * @static
                 * @param {perfetto.protos.AndroidStartupMetric.IMcyclesByCoreType} message McyclesByCoreType message or plain object to encode
                 * @param {$protobuf.Writer} [writer] Writer to encode to
                 * @returns {$protobuf.Writer} Writer
                 */
                McyclesByCoreType.encodeDelimited = function encodeDelimited(message, writer) {
                    return this.encode(message, writer).ldelim();
                };

                /**
                 * Decodes a McyclesByCoreType message from the specified reader or buffer.
                 * @function decode
                 * @memberof perfetto.protos.AndroidStartupMetric.McyclesByCoreType
                 * @static
                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                 * @param {number} [length] Message length if known beforehand
                 * @returns {perfetto.protos.AndroidStartupMetric.McyclesByCoreType} McyclesByCoreType
                 * @throws {Error} If the payload is not a reader or valid buffer
                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
                 */
                McyclesByCoreType.decode = function decode(reader, length) {
                    if (!(reader instanceof $Reader))
                        reader = $Reader.create(reader);
                    var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.AndroidStartupMetric.McyclesByCoreType();
                    while (reader.pos < end) {
                        var tag = reader.uint32();
                        switch (tag >>> 3) {
                        case 1:
                            message.little = reader.int64();
                            break;
                        case 2:
                            message.big = reader.int64();
                            break;
                        case 3:
                            message.bigger = reader.int64();
                            break;
                        case 4:
                            message.unknown = reader.int64();
                            break;
                        default:
                            reader.skipType(tag & 7);
                            break;
                        }
                    }
                    return message;
                };

                /**
                 * Decodes a McyclesByCoreType message from the specified reader or buffer, length delimited.
                 * @function decodeDelimited
                 * @memberof perfetto.protos.AndroidStartupMetric.McyclesByCoreType
                 * @static
                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                 * @returns {perfetto.protos.AndroidStartupMetric.McyclesByCoreType} McyclesByCoreType
                 * @throws {Error} If the payload is not a reader or valid buffer
                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
                 */
                McyclesByCoreType.decodeDelimited = function decodeDelimited(reader) {
                    if (!(reader instanceof $Reader))
                        reader = new $Reader(reader);
                    return this.decode(reader, reader.uint32());
                };

                /**
                 * Verifies a McyclesByCoreType message.
                 * @function verify
                 * @memberof perfetto.protos.AndroidStartupMetric.McyclesByCoreType
                 * @static
                 * @param {Object.<string,*>} message Plain object to verify
                 * @returns {string|null} `null` if valid, otherwise the reason why it is not
                 */
                McyclesByCoreType.verify = function verify(message) {
                    if (typeof message !== "object" || message === null)
                        return "object expected";
                    if (message.little != null && message.hasOwnProperty("little"))
                        if (!$util.isInteger(message.little) && !(message.little && $util.isInteger(message.little.low) && $util.isInteger(message.little.high)))
                            return "little: integer|Long expected";
                    if (message.big != null && message.hasOwnProperty("big"))
                        if (!$util.isInteger(message.big) && !(message.big && $util.isInteger(message.big.low) && $util.isInteger(message.big.high)))
                            return "big: integer|Long expected";
                    if (message.bigger != null && message.hasOwnProperty("bigger"))
                        if (!$util.isInteger(message.bigger) && !(message.bigger && $util.isInteger(message.bigger.low) && $util.isInteger(message.bigger.high)))
                            return "bigger: integer|Long expected";
                    if (message.unknown != null && message.hasOwnProperty("unknown"))
                        if (!$util.isInteger(message.unknown) && !(message.unknown && $util.isInteger(message.unknown.low) && $util.isInteger(message.unknown.high)))
                            return "unknown: integer|Long expected";
                    return null;
                };

                /**
                 * Creates a McyclesByCoreType message from a plain object. Also converts values to their respective internal types.
                 * @function fromObject
                 * @memberof perfetto.protos.AndroidStartupMetric.McyclesByCoreType
                 * @static
                 * @param {Object.<string,*>} object Plain object
                 * @returns {perfetto.protos.AndroidStartupMetric.McyclesByCoreType} McyclesByCoreType
                 */
                McyclesByCoreType.fromObject = function fromObject(object) {
                    if (object instanceof $root.perfetto.protos.AndroidStartupMetric.McyclesByCoreType)
                        return object;
                    var message = new $root.perfetto.protos.AndroidStartupMetric.McyclesByCoreType();
                    if (object.little != null)
                        if ($util.Long)
                            (message.little = $util.Long.fromValue(object.little)).unsigned = false;
                        else if (typeof object.little === "string")
                            message.little = parseInt(object.little, 10);
                        else if (typeof object.little === "number")
                            message.little = object.little;
                        else if (typeof object.little === "object")
                            message.little = new $util.LongBits(object.little.low >>> 0, object.little.high >>> 0).toNumber();
                    if (object.big != null)
                        if ($util.Long)
                            (message.big = $util.Long.fromValue(object.big)).unsigned = false;
                        else if (typeof object.big === "string")
                            message.big = parseInt(object.big, 10);
                        else if (typeof object.big === "number")
                            message.big = object.big;
                        else if (typeof object.big === "object")
                            message.big = new $util.LongBits(object.big.low >>> 0, object.big.high >>> 0).toNumber();
                    if (object.bigger != null)
                        if ($util.Long)
                            (message.bigger = $util.Long.fromValue(object.bigger)).unsigned = false;
                        else if (typeof object.bigger === "string")
                            message.bigger = parseInt(object.bigger, 10);
                        else if (typeof object.bigger === "number")
                            message.bigger = object.bigger;
                        else if (typeof object.bigger === "object")
                            message.bigger = new $util.LongBits(object.bigger.low >>> 0, object.bigger.high >>> 0).toNumber();
                    if (object.unknown != null)
                        if ($util.Long)
                            (message.unknown = $util.Long.fromValue(object.unknown)).unsigned = false;
                        else if (typeof object.unknown === "string")
                            message.unknown = parseInt(object.unknown, 10);
                        else if (typeof object.unknown === "number")
                            message.unknown = object.unknown;
                        else if (typeof object.unknown === "object")
                            message.unknown = new $util.LongBits(object.unknown.low >>> 0, object.unknown.high >>> 0).toNumber();
                    return message;
                };

                /**
                 * Creates a plain object from a McyclesByCoreType message. Also converts values to other types if specified.
                 * @function toObject
                 * @memberof perfetto.protos.AndroidStartupMetric.McyclesByCoreType
                 * @static
                 * @param {perfetto.protos.AndroidStartupMetric.McyclesByCoreType} message McyclesByCoreType
                 * @param {$protobuf.IConversionOptions} [options] Conversion options
                 * @returns {Object.<string,*>} Plain object
                 */
                McyclesByCoreType.toObject = function toObject(message, options) {
                    if (!options)
                        options = {};
                    var object = {};
                    if (options.defaults) {
                        if ($util.Long) {
                            var long = new $util.Long(0, 0, false);
                            object.little = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
                        } else
                            object.little = options.longs === String ? "0" : 0;
                        if ($util.Long) {
                            var long = new $util.Long(0, 0, false);
                            object.big = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
                        } else
                            object.big = options.longs === String ? "0" : 0;
                        if ($util.Long) {
                            var long = new $util.Long(0, 0, false);
                            object.bigger = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
                        } else
                            object.bigger = options.longs === String ? "0" : 0;
                        if ($util.Long) {
                            var long = new $util.Long(0, 0, false);
                            object.unknown = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
                        } else
                            object.unknown = options.longs === String ? "0" : 0;
                    }
                    if (message.little != null && message.hasOwnProperty("little"))
                        if (typeof message.little === "number")
                            object.little = options.longs === String ? String(message.little) : message.little;
                        else
                            object.little = options.longs === String ? $util.Long.prototype.toString.call(message.little) : options.longs === Number ? new $util.LongBits(message.little.low >>> 0, message.little.high >>> 0).toNumber() : message.little;
                    if (message.big != null && message.hasOwnProperty("big"))
                        if (typeof message.big === "number")
                            object.big = options.longs === String ? String(message.big) : message.big;
                        else
                            object.big = options.longs === String ? $util.Long.prototype.toString.call(message.big) : options.longs === Number ? new $util.LongBits(message.big.low >>> 0, message.big.high >>> 0).toNumber() : message.big;
                    if (message.bigger != null && message.hasOwnProperty("bigger"))
                        if (typeof message.bigger === "number")
                            object.bigger = options.longs === String ? String(message.bigger) : message.bigger;
                        else
                            object.bigger = options.longs === String ? $util.Long.prototype.toString.call(message.bigger) : options.longs === Number ? new $util.LongBits(message.bigger.low >>> 0, message.bigger.high >>> 0).toNumber() : message.bigger;
                    if (message.unknown != null && message.hasOwnProperty("unknown"))
                        if (typeof message.unknown === "number")
                            object.unknown = options.longs === String ? String(message.unknown) : message.unknown;
                        else
                            object.unknown = options.longs === String ? $util.Long.prototype.toString.call(message.unknown) : options.longs === Number ? new $util.LongBits(message.unknown.low >>> 0, message.unknown.high >>> 0).toNumber() : message.unknown;
                    return object;
                };

                /**
                 * Converts this McyclesByCoreType to JSON.
                 * @function toJSON
                 * @memberof perfetto.protos.AndroidStartupMetric.McyclesByCoreType
                 * @instance
                 * @returns {Object.<string,*>} JSON object
                 */
                McyclesByCoreType.prototype.toJSON = function toJSON() {
                    return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
                };

                return McyclesByCoreType;
            })();

            AndroidStartupMetric.Slice = (function() {

                /**
                 * Properties of a Slice.
                 * @memberof perfetto.protos.AndroidStartupMetric
                 * @interface ISlice
                 * @property {number|null} [durNs] Slice durNs
                 * @property {number|null} [durMs] Slice durMs
                 */

                /**
                 * Constructs a new Slice.
                 * @memberof perfetto.protos.AndroidStartupMetric
                 * @classdesc Represents a Slice.
                 * @implements ISlice
                 * @constructor
                 * @param {perfetto.protos.AndroidStartupMetric.ISlice=} [properties] Properties to set
                 */
                function Slice(properties) {
                    if (properties)
                        for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                            if (properties[keys[i]] != null)
                                this[keys[i]] = properties[keys[i]];
                }

                /**
                 * Slice durNs.
                 * @member {number} durNs
                 * @memberof perfetto.protos.AndroidStartupMetric.Slice
                 * @instance
                 */
                Slice.prototype.durNs = $util.Long ? $util.Long.fromBits(0,0,false) : 0;

                /**
                 * Slice durMs.
                 * @member {number} durMs
                 * @memberof perfetto.protos.AndroidStartupMetric.Slice
                 * @instance
                 */
                Slice.prototype.durMs = 0;

                /**
                 * Creates a new Slice instance using the specified properties.
                 * @function create
                 * @memberof perfetto.protos.AndroidStartupMetric.Slice
                 * @static
                 * @param {perfetto.protos.AndroidStartupMetric.ISlice=} [properties] Properties to set
                 * @returns {perfetto.protos.AndroidStartupMetric.Slice} Slice instance
                 */
                Slice.create = function create(properties) {
                    return new Slice(properties);
                };

                /**
                 * Encodes the specified Slice message. Does not implicitly {@link perfetto.protos.AndroidStartupMetric.Slice.verify|verify} messages.
                 * @function encode
                 * @memberof perfetto.protos.AndroidStartupMetric.Slice
                 * @static
                 * @param {perfetto.protos.AndroidStartupMetric.ISlice} message Slice message or plain object to encode
                 * @param {$protobuf.Writer} [writer] Writer to encode to
                 * @returns {$protobuf.Writer} Writer
                 */
                Slice.encode = function encode(message, writer) {
                    if (!writer)
                        writer = $Writer.create();
                    if (message.durNs != null && Object.hasOwnProperty.call(message, "durNs"))
                        writer.uint32(/* id 1, wireType 0 =*/8).int64(message.durNs);
                    if (message.durMs != null && Object.hasOwnProperty.call(message, "durMs"))
                        writer.uint32(/* id 2, wireType 1 =*/17).double(message.durMs);
                    return writer;
                };

                /**
                 * Encodes the specified Slice message, length delimited. Does not implicitly {@link perfetto.protos.AndroidStartupMetric.Slice.verify|verify} messages.
                 * @function encodeDelimited
                 * @memberof perfetto.protos.AndroidStartupMetric.Slice
                 * @static
                 * @param {perfetto.protos.AndroidStartupMetric.ISlice} message Slice message or plain object to encode
                 * @param {$protobuf.Writer} [writer] Writer to encode to
                 * @returns {$protobuf.Writer} Writer
                 */
                Slice.encodeDelimited = function encodeDelimited(message, writer) {
                    return this.encode(message, writer).ldelim();
                };

                /**
                 * Decodes a Slice message from the specified reader or buffer.
                 * @function decode
                 * @memberof perfetto.protos.AndroidStartupMetric.Slice
                 * @static
                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                 * @param {number} [length] Message length if known beforehand
                 * @returns {perfetto.protos.AndroidStartupMetric.Slice} Slice
                 * @throws {Error} If the payload is not a reader or valid buffer
                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
                 */
                Slice.decode = function decode(reader, length) {
                    if (!(reader instanceof $Reader))
                        reader = $Reader.create(reader);
                    var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.AndroidStartupMetric.Slice();
                    while (reader.pos < end) {
                        var tag = reader.uint32();
                        switch (tag >>> 3) {
                        case 1:
                            message.durNs = reader.int64();
                            break;
                        case 2:
                            message.durMs = reader.double();
                            break;
                        default:
                            reader.skipType(tag & 7);
                            break;
                        }
                    }
                    return message;
                };

                /**
                 * Decodes a Slice message from the specified reader or buffer, length delimited.
                 * @function decodeDelimited
                 * @memberof perfetto.protos.AndroidStartupMetric.Slice
                 * @static
                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                 * @returns {perfetto.protos.AndroidStartupMetric.Slice} Slice
                 * @throws {Error} If the payload is not a reader or valid buffer
                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
                 */
                Slice.decodeDelimited = function decodeDelimited(reader) {
                    if (!(reader instanceof $Reader))
                        reader = new $Reader(reader);
                    return this.decode(reader, reader.uint32());
                };

                /**
                 * Verifies a Slice message.
                 * @function verify
                 * @memberof perfetto.protos.AndroidStartupMetric.Slice
                 * @static
                 * @param {Object.<string,*>} message Plain object to verify
                 * @returns {string|null} `null` if valid, otherwise the reason why it is not
                 */
                Slice.verify = function verify(message) {
                    if (typeof message !== "object" || message === null)
                        return "object expected";
                    if (message.durNs != null && message.hasOwnProperty("durNs"))
                        if (!$util.isInteger(message.durNs) && !(message.durNs && $util.isInteger(message.durNs.low) && $util.isInteger(message.durNs.high)))
                            return "durNs: integer|Long expected";
                    if (message.durMs != null && message.hasOwnProperty("durMs"))
                        if (typeof message.durMs !== "number")
                            return "durMs: number expected";
                    return null;
                };

                /**
                 * Creates a Slice message from a plain object. Also converts values to their respective internal types.
                 * @function fromObject
                 * @memberof perfetto.protos.AndroidStartupMetric.Slice
                 * @static
                 * @param {Object.<string,*>} object Plain object
                 * @returns {perfetto.protos.AndroidStartupMetric.Slice} Slice
                 */
                Slice.fromObject = function fromObject(object) {
                    if (object instanceof $root.perfetto.protos.AndroidStartupMetric.Slice)
                        return object;
                    var message = new $root.perfetto.protos.AndroidStartupMetric.Slice();
                    if (object.durNs != null)
                        if ($util.Long)
                            (message.durNs = $util.Long.fromValue(object.durNs)).unsigned = false;
                        else if (typeof object.durNs === "string")
                            message.durNs = parseInt(object.durNs, 10);
                        else if (typeof object.durNs === "number")
                            message.durNs = object.durNs;
                        else if (typeof object.durNs === "object")
                            message.durNs = new $util.LongBits(object.durNs.low >>> 0, object.durNs.high >>> 0).toNumber();
                    if (object.durMs != null)
                        message.durMs = Number(object.durMs);
                    return message;
                };

                /**
                 * Creates a plain object from a Slice message. Also converts values to other types if specified.
                 * @function toObject
                 * @memberof perfetto.protos.AndroidStartupMetric.Slice
                 * @static
                 * @param {perfetto.protos.AndroidStartupMetric.Slice} message Slice
                 * @param {$protobuf.IConversionOptions} [options] Conversion options
                 * @returns {Object.<string,*>} Plain object
                 */
                Slice.toObject = function toObject(message, options) {
                    if (!options)
                        options = {};
                    var object = {};
                    if (options.defaults) {
                        if ($util.Long) {
                            var long = new $util.Long(0, 0, false);
                            object.durNs = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
                        } else
                            object.durNs = options.longs === String ? "0" : 0;
                        object.durMs = 0;
                    }
                    if (message.durNs != null && message.hasOwnProperty("durNs"))
                        if (typeof message.durNs === "number")
                            object.durNs = options.longs === String ? String(message.durNs) : message.durNs;
                        else
                            object.durNs = options.longs === String ? $util.Long.prototype.toString.call(message.durNs) : options.longs === Number ? new $util.LongBits(message.durNs.low >>> 0, message.durNs.high >>> 0).toNumber() : message.durNs;
                    if (message.durMs != null && message.hasOwnProperty("durMs"))
                        object.durMs = options.json && !isFinite(message.durMs) ? String(message.durMs) : message.durMs;
                    return object;
                };

                /**
                 * Converts this Slice to JSON.
                 * @function toJSON
                 * @memberof perfetto.protos.AndroidStartupMetric.Slice
                 * @instance
                 * @returns {Object.<string,*>} JSON object
                 */
                Slice.prototype.toJSON = function toJSON() {
                    return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
                };

                return Slice;
            })();

            AndroidStartupMetric.ToFirstFrame = (function() {

                /**
                 * Properties of a ToFirstFrame.
                 * @memberof perfetto.protos.AndroidStartupMetric
                 * @interface IToFirstFrame
                 * @property {number|null} [durNs] ToFirstFrame durNs
                 * @property {number|null} [durMs] ToFirstFrame durMs
                 * @property {perfetto.protos.AndroidStartupMetric.ITaskStateBreakdown|null} [mainThreadByTaskState] ToFirstFrame mainThreadByTaskState
                 * @property {perfetto.protos.AndroidStartupMetric.IMcyclesByCoreType|null} [mcyclesByCoreType] ToFirstFrame mcyclesByCoreType
                 * @property {number|null} [otherProcessesSpawnedCount] ToFirstFrame otherProcessesSpawnedCount
                 * @property {perfetto.protos.AndroidStartupMetric.ISlice|null} [timeActivityManager] ToFirstFrame timeActivityManager
                 * @property {perfetto.protos.AndroidStartupMetric.ISlice|null} [timeActivityThreadMain] ToFirstFrame timeActivityThreadMain
                 * @property {perfetto.protos.AndroidStartupMetric.ISlice|null} [timeBindApplication] ToFirstFrame timeBindApplication
                 * @property {perfetto.protos.AndroidStartupMetric.ISlice|null} [timeActivityStart] ToFirstFrame timeActivityStart
                 * @property {perfetto.protos.AndroidStartupMetric.ISlice|null} [timeActivityResume] ToFirstFrame timeActivityResume
                 * @property {perfetto.protos.AndroidStartupMetric.ISlice|null} [timeActivityRestart] ToFirstFrame timeActivityRestart
                 * @property {perfetto.protos.AndroidStartupMetric.ISlice|null} [timeChoreographer] ToFirstFrame timeChoreographer
                 * @property {perfetto.protos.AndroidStartupMetric.ISlice|null} [timeInflate] ToFirstFrame timeInflate
                 * @property {perfetto.protos.AndroidStartupMetric.ISlice|null} [timeGetResources] ToFirstFrame timeGetResources
                 * @property {perfetto.protos.AndroidStartupMetric.ISlice|null} [timeBeforeStartProcess] ToFirstFrame timeBeforeStartProcess
                 * @property {perfetto.protos.AndroidStartupMetric.ISlice|null} [timeDuringStartProcess] ToFirstFrame timeDuringStartProcess
                 * @property {perfetto.protos.AndroidStartupMetric.ISlice|null} [toPostFork] ToFirstFrame toPostFork
                 * @property {perfetto.protos.AndroidStartupMetric.ISlice|null} [toActivityThreadMain] ToFirstFrame toActivityThreadMain
                 * @property {perfetto.protos.AndroidStartupMetric.ISlice|null} [toBindApplication] ToFirstFrame toBindApplication
                 * @property {perfetto.protos.AndroidStartupMetric.ISlice|null} [timePostFork] ToFirstFrame timePostFork
                 * @property {perfetto.protos.AndroidStartupMetric.ISlice|null} [timeDexOpen] ToFirstFrame timeDexOpen
                 * @property {perfetto.protos.AndroidStartupMetric.ISlice|null} [timeVerifyClass] ToFirstFrame timeVerifyClass
                 * @property {number|null} [jitCompiledMethods] ToFirstFrame jitCompiledMethods
                 * @property {perfetto.protos.AndroidStartupMetric.ISlice|null} [timeJitThreadPoolOnCpu] ToFirstFrame timeJitThreadPoolOnCpu
                 * @property {perfetto.protos.AndroidStartupMetric.ISlice|null} [timeGcTotal] ToFirstFrame timeGcTotal
                 * @property {perfetto.protos.AndroidStartupMetric.ISlice|null} [timeGcOnCpu] ToFirstFrame timeGcOnCpu
                 */

                /**
                 * Constructs a new ToFirstFrame.
                 * @memberof perfetto.protos.AndroidStartupMetric
                 * @classdesc Represents a ToFirstFrame.
                 * @implements IToFirstFrame
                 * @constructor
                 * @param {perfetto.protos.AndroidStartupMetric.IToFirstFrame=} [properties] Properties to set
                 */
                function ToFirstFrame(properties) {
                    if (properties)
                        for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                            if (properties[keys[i]] != null)
                                this[keys[i]] = properties[keys[i]];
                }

                /**
                 * ToFirstFrame durNs.
                 * @member {number} durNs
                 * @memberof perfetto.protos.AndroidStartupMetric.ToFirstFrame
                 * @instance
                 */
                ToFirstFrame.prototype.durNs = $util.Long ? $util.Long.fromBits(0,0,false) : 0;

                /**
                 * ToFirstFrame durMs.
                 * @member {number} durMs
                 * @memberof perfetto.protos.AndroidStartupMetric.ToFirstFrame
                 * @instance
                 */
                ToFirstFrame.prototype.durMs = 0;

                /**
                 * ToFirstFrame mainThreadByTaskState.
                 * @member {perfetto.protos.AndroidStartupMetric.ITaskStateBreakdown|null|undefined} mainThreadByTaskState
                 * @memberof perfetto.protos.AndroidStartupMetric.ToFirstFrame
                 * @instance
                 */
                ToFirstFrame.prototype.mainThreadByTaskState = null;

                /**
                 * ToFirstFrame mcyclesByCoreType.
                 * @member {perfetto.protos.AndroidStartupMetric.IMcyclesByCoreType|null|undefined} mcyclesByCoreType
                 * @memberof perfetto.protos.AndroidStartupMetric.ToFirstFrame
                 * @instance
                 */
                ToFirstFrame.prototype.mcyclesByCoreType = null;

                /**
                 * ToFirstFrame otherProcessesSpawnedCount.
                 * @member {number} otherProcessesSpawnedCount
                 * @memberof perfetto.protos.AndroidStartupMetric.ToFirstFrame
                 * @instance
                 */
                ToFirstFrame.prototype.otherProcessesSpawnedCount = 0;

                /**
                 * ToFirstFrame timeActivityManager.
                 * @member {perfetto.protos.AndroidStartupMetric.ISlice|null|undefined} timeActivityManager
                 * @memberof perfetto.protos.AndroidStartupMetric.ToFirstFrame
                 * @instance
                 */
                ToFirstFrame.prototype.timeActivityManager = null;

                /**
                 * ToFirstFrame timeActivityThreadMain.
                 * @member {perfetto.protos.AndroidStartupMetric.ISlice|null|undefined} timeActivityThreadMain
                 * @memberof perfetto.protos.AndroidStartupMetric.ToFirstFrame
                 * @instance
                 */
                ToFirstFrame.prototype.timeActivityThreadMain = null;

                /**
                 * ToFirstFrame timeBindApplication.
                 * @member {perfetto.protos.AndroidStartupMetric.ISlice|null|undefined} timeBindApplication
                 * @memberof perfetto.protos.AndroidStartupMetric.ToFirstFrame
                 * @instance
                 */
                ToFirstFrame.prototype.timeBindApplication = null;

                /**
                 * ToFirstFrame timeActivityStart.
                 * @member {perfetto.protos.AndroidStartupMetric.ISlice|null|undefined} timeActivityStart
                 * @memberof perfetto.protos.AndroidStartupMetric.ToFirstFrame
                 * @instance
                 */
                ToFirstFrame.prototype.timeActivityStart = null;

                /**
                 * ToFirstFrame timeActivityResume.
                 * @member {perfetto.protos.AndroidStartupMetric.ISlice|null|undefined} timeActivityResume
                 * @memberof perfetto.protos.AndroidStartupMetric.ToFirstFrame
                 * @instance
                 */
                ToFirstFrame.prototype.timeActivityResume = null;

                /**
                 * ToFirstFrame timeActivityRestart.
                 * @member {perfetto.protos.AndroidStartupMetric.ISlice|null|undefined} timeActivityRestart
                 * @memberof perfetto.protos.AndroidStartupMetric.ToFirstFrame
                 * @instance
                 */
                ToFirstFrame.prototype.timeActivityRestart = null;

                /**
                 * ToFirstFrame timeChoreographer.
                 * @member {perfetto.protos.AndroidStartupMetric.ISlice|null|undefined} timeChoreographer
                 * @memberof perfetto.protos.AndroidStartupMetric.ToFirstFrame
                 * @instance
                 */
                ToFirstFrame.prototype.timeChoreographer = null;

                /**
                 * ToFirstFrame timeInflate.
                 * @member {perfetto.protos.AndroidStartupMetric.ISlice|null|undefined} timeInflate
                 * @memberof perfetto.protos.AndroidStartupMetric.ToFirstFrame
                 * @instance
                 */
                ToFirstFrame.prototype.timeInflate = null;

                /**
                 * ToFirstFrame timeGetResources.
                 * @member {perfetto.protos.AndroidStartupMetric.ISlice|null|undefined} timeGetResources
                 * @memberof perfetto.protos.AndroidStartupMetric.ToFirstFrame
                 * @instance
                 */
                ToFirstFrame.prototype.timeGetResources = null;

                /**
                 * ToFirstFrame timeBeforeStartProcess.
                 * @member {perfetto.protos.AndroidStartupMetric.ISlice|null|undefined} timeBeforeStartProcess
                 * @memberof perfetto.protos.AndroidStartupMetric.ToFirstFrame
                 * @instance
                 */
                ToFirstFrame.prototype.timeBeforeStartProcess = null;

                /**
                 * ToFirstFrame timeDuringStartProcess.
                 * @member {perfetto.protos.AndroidStartupMetric.ISlice|null|undefined} timeDuringStartProcess
                 * @memberof perfetto.protos.AndroidStartupMetric.ToFirstFrame
                 * @instance
                 */
                ToFirstFrame.prototype.timeDuringStartProcess = null;

                /**
                 * ToFirstFrame toPostFork.
                 * @member {perfetto.protos.AndroidStartupMetric.ISlice|null|undefined} toPostFork
                 * @memberof perfetto.protos.AndroidStartupMetric.ToFirstFrame
                 * @instance
                 */
                ToFirstFrame.prototype.toPostFork = null;

                /**
                 * ToFirstFrame toActivityThreadMain.
                 * @member {perfetto.protos.AndroidStartupMetric.ISlice|null|undefined} toActivityThreadMain
                 * @memberof perfetto.protos.AndroidStartupMetric.ToFirstFrame
                 * @instance
                 */
                ToFirstFrame.prototype.toActivityThreadMain = null;

                /**
                 * ToFirstFrame toBindApplication.
                 * @member {perfetto.protos.AndroidStartupMetric.ISlice|null|undefined} toBindApplication
                 * @memberof perfetto.protos.AndroidStartupMetric.ToFirstFrame
                 * @instance
                 */
                ToFirstFrame.prototype.toBindApplication = null;

                /**
                 * ToFirstFrame timePostFork.
                 * @member {perfetto.protos.AndroidStartupMetric.ISlice|null|undefined} timePostFork
                 * @memberof perfetto.protos.AndroidStartupMetric.ToFirstFrame
                 * @instance
                 */
                ToFirstFrame.prototype.timePostFork = null;

                /**
                 * ToFirstFrame timeDexOpen.
                 * @member {perfetto.protos.AndroidStartupMetric.ISlice|null|undefined} timeDexOpen
                 * @memberof perfetto.protos.AndroidStartupMetric.ToFirstFrame
                 * @instance
                 */
                ToFirstFrame.prototype.timeDexOpen = null;

                /**
                 * ToFirstFrame timeVerifyClass.
                 * @member {perfetto.protos.AndroidStartupMetric.ISlice|null|undefined} timeVerifyClass
                 * @memberof perfetto.protos.AndroidStartupMetric.ToFirstFrame
                 * @instance
                 */
                ToFirstFrame.prototype.timeVerifyClass = null;

                /**
                 * ToFirstFrame jitCompiledMethods.
                 * @member {number} jitCompiledMethods
                 * @memberof perfetto.protos.AndroidStartupMetric.ToFirstFrame
                 * @instance
                 */
                ToFirstFrame.prototype.jitCompiledMethods = 0;

                /**
                 * ToFirstFrame timeJitThreadPoolOnCpu.
                 * @member {perfetto.protos.AndroidStartupMetric.ISlice|null|undefined} timeJitThreadPoolOnCpu
                 * @memberof perfetto.protos.AndroidStartupMetric.ToFirstFrame
                 * @instance
                 */
                ToFirstFrame.prototype.timeJitThreadPoolOnCpu = null;

                /**
                 * ToFirstFrame timeGcTotal.
                 * @member {perfetto.protos.AndroidStartupMetric.ISlice|null|undefined} timeGcTotal
                 * @memberof perfetto.protos.AndroidStartupMetric.ToFirstFrame
                 * @instance
                 */
                ToFirstFrame.prototype.timeGcTotal = null;

                /**
                 * ToFirstFrame timeGcOnCpu.
                 * @member {perfetto.protos.AndroidStartupMetric.ISlice|null|undefined} timeGcOnCpu
                 * @memberof perfetto.protos.AndroidStartupMetric.ToFirstFrame
                 * @instance
                 */
                ToFirstFrame.prototype.timeGcOnCpu = null;

                /**
                 * Creates a new ToFirstFrame instance using the specified properties.
                 * @function create
                 * @memberof perfetto.protos.AndroidStartupMetric.ToFirstFrame
                 * @static
                 * @param {perfetto.protos.AndroidStartupMetric.IToFirstFrame=} [properties] Properties to set
                 * @returns {perfetto.protos.AndroidStartupMetric.ToFirstFrame} ToFirstFrame instance
                 */
                ToFirstFrame.create = function create(properties) {
                    return new ToFirstFrame(properties);
                };

                /**
                 * Encodes the specified ToFirstFrame message. Does not implicitly {@link perfetto.protos.AndroidStartupMetric.ToFirstFrame.verify|verify} messages.
                 * @function encode
                 * @memberof perfetto.protos.AndroidStartupMetric.ToFirstFrame
                 * @static
                 * @param {perfetto.protos.AndroidStartupMetric.IToFirstFrame} message ToFirstFrame message or plain object to encode
                 * @param {$protobuf.Writer} [writer] Writer to encode to
                 * @returns {$protobuf.Writer} Writer
                 */
                ToFirstFrame.encode = function encode(message, writer) {
                    if (!writer)
                        writer = $Writer.create();
                    if (message.durNs != null && Object.hasOwnProperty.call(message, "durNs"))
                        writer.uint32(/* id 1, wireType 0 =*/8).int64(message.durNs);
                    if (message.mainThreadByTaskState != null && Object.hasOwnProperty.call(message, "mainThreadByTaskState"))
                        $root.perfetto.protos.AndroidStartupMetric.TaskStateBreakdown.encode(message.mainThreadByTaskState, writer.uint32(/* id 2, wireType 2 =*/18).fork()).ldelim();
                    if (message.otherProcessesSpawnedCount != null && Object.hasOwnProperty.call(message, "otherProcessesSpawnedCount"))
                        writer.uint32(/* id 3, wireType 0 =*/24).uint32(message.otherProcessesSpawnedCount);
                    if (message.timeActivityManager != null && Object.hasOwnProperty.call(message, "timeActivityManager"))
                        $root.perfetto.protos.AndroidStartupMetric.Slice.encode(message.timeActivityManager, writer.uint32(/* id 4, wireType 2 =*/34).fork()).ldelim();
                    if (message.timeActivityThreadMain != null && Object.hasOwnProperty.call(message, "timeActivityThreadMain"))
                        $root.perfetto.protos.AndroidStartupMetric.Slice.encode(message.timeActivityThreadMain, writer.uint32(/* id 5, wireType 2 =*/42).fork()).ldelim();
                    if (message.timeBindApplication != null && Object.hasOwnProperty.call(message, "timeBindApplication"))
                        $root.perfetto.protos.AndroidStartupMetric.Slice.encode(message.timeBindApplication, writer.uint32(/* id 6, wireType 2 =*/50).fork()).ldelim();
                    if (message.timeActivityStart != null && Object.hasOwnProperty.call(message, "timeActivityStart"))
                        $root.perfetto.protos.AndroidStartupMetric.Slice.encode(message.timeActivityStart, writer.uint32(/* id 7, wireType 2 =*/58).fork()).ldelim();
                    if (message.timeActivityResume != null && Object.hasOwnProperty.call(message, "timeActivityResume"))
                        $root.perfetto.protos.AndroidStartupMetric.Slice.encode(message.timeActivityResume, writer.uint32(/* id 8, wireType 2 =*/66).fork()).ldelim();
                    if (message.timeChoreographer != null && Object.hasOwnProperty.call(message, "timeChoreographer"))
                        $root.perfetto.protos.AndroidStartupMetric.Slice.encode(message.timeChoreographer, writer.uint32(/* id 9, wireType 2 =*/74).fork()).ldelim();
                    if (message.timeBeforeStartProcess != null && Object.hasOwnProperty.call(message, "timeBeforeStartProcess"))
                        $root.perfetto.protos.AndroidStartupMetric.Slice.encode(message.timeBeforeStartProcess, writer.uint32(/* id 10, wireType 2 =*/82).fork()).ldelim();
                    if (message.timeDuringStartProcess != null && Object.hasOwnProperty.call(message, "timeDuringStartProcess"))
                        $root.perfetto.protos.AndroidStartupMetric.Slice.encode(message.timeDuringStartProcess, writer.uint32(/* id 11, wireType 2 =*/90).fork()).ldelim();
                    if (message.timePostFork != null && Object.hasOwnProperty.call(message, "timePostFork"))
                        $root.perfetto.protos.AndroidStartupMetric.Slice.encode(message.timePostFork, writer.uint32(/* id 16, wireType 2 =*/130).fork()).ldelim();
                    if (message.durMs != null && Object.hasOwnProperty.call(message, "durMs"))
                        writer.uint32(/* id 17, wireType 1 =*/137).double(message.durMs);
                    if (message.toPostFork != null && Object.hasOwnProperty.call(message, "toPostFork"))
                        $root.perfetto.protos.AndroidStartupMetric.Slice.encode(message.toPostFork, writer.uint32(/* id 18, wireType 2 =*/146).fork()).ldelim();
                    if (message.toActivityThreadMain != null && Object.hasOwnProperty.call(message, "toActivityThreadMain"))
                        $root.perfetto.protos.AndroidStartupMetric.Slice.encode(message.toActivityThreadMain, writer.uint32(/* id 19, wireType 2 =*/154).fork()).ldelim();
                    if (message.toBindApplication != null && Object.hasOwnProperty.call(message, "toBindApplication"))
                        $root.perfetto.protos.AndroidStartupMetric.Slice.encode(message.toBindApplication, writer.uint32(/* id 20, wireType 2 =*/162).fork()).ldelim();
                    if (message.timeActivityRestart != null && Object.hasOwnProperty.call(message, "timeActivityRestart"))
                        $root.perfetto.protos.AndroidStartupMetric.Slice.encode(message.timeActivityRestart, writer.uint32(/* id 21, wireType 2 =*/170).fork()).ldelim();
                    if (message.timeInflate != null && Object.hasOwnProperty.call(message, "timeInflate"))
                        $root.perfetto.protos.AndroidStartupMetric.Slice.encode(message.timeInflate, writer.uint32(/* id 22, wireType 2 =*/178).fork()).ldelim();
                    if (message.timeGetResources != null && Object.hasOwnProperty.call(message, "timeGetResources"))
                        $root.perfetto.protos.AndroidStartupMetric.Slice.encode(message.timeGetResources, writer.uint32(/* id 23, wireType 2 =*/186).fork()).ldelim();
                    if (message.timeDexOpen != null && Object.hasOwnProperty.call(message, "timeDexOpen"))
                        $root.perfetto.protos.AndroidStartupMetric.Slice.encode(message.timeDexOpen, writer.uint32(/* id 24, wireType 2 =*/194).fork()).ldelim();
                    if (message.timeVerifyClass != null && Object.hasOwnProperty.call(message, "timeVerifyClass"))
                        $root.perfetto.protos.AndroidStartupMetric.Slice.encode(message.timeVerifyClass, writer.uint32(/* id 25, wireType 2 =*/202).fork()).ldelim();
                    if (message.mcyclesByCoreType != null && Object.hasOwnProperty.call(message, "mcyclesByCoreType"))
                        $root.perfetto.protos.AndroidStartupMetric.McyclesByCoreType.encode(message.mcyclesByCoreType, writer.uint32(/* id 26, wireType 2 =*/210).fork()).ldelim();
                    if (message.jitCompiledMethods != null && Object.hasOwnProperty.call(message, "jitCompiledMethods"))
                        writer.uint32(/* id 27, wireType 0 =*/216).uint32(message.jitCompiledMethods);
                    if (message.timeJitThreadPoolOnCpu != null && Object.hasOwnProperty.call(message, "timeJitThreadPoolOnCpu"))
                        $root.perfetto.protos.AndroidStartupMetric.Slice.encode(message.timeJitThreadPoolOnCpu, writer.uint32(/* id 28, wireType 2 =*/226).fork()).ldelim();
                    if (message.timeGcTotal != null && Object.hasOwnProperty.call(message, "timeGcTotal"))
                        $root.perfetto.protos.AndroidStartupMetric.Slice.encode(message.timeGcTotal, writer.uint32(/* id 29, wireType 2 =*/234).fork()).ldelim();
                    if (message.timeGcOnCpu != null && Object.hasOwnProperty.call(message, "timeGcOnCpu"))
                        $root.perfetto.protos.AndroidStartupMetric.Slice.encode(message.timeGcOnCpu, writer.uint32(/* id 30, wireType 2 =*/242).fork()).ldelim();
                    return writer;
                };

                /**
                 * Encodes the specified ToFirstFrame message, length delimited. Does not implicitly {@link perfetto.protos.AndroidStartupMetric.ToFirstFrame.verify|verify} messages.
                 * @function encodeDelimited
                 * @memberof perfetto.protos.AndroidStartupMetric.ToFirstFrame
                 * @static
                 * @param {perfetto.protos.AndroidStartupMetric.IToFirstFrame} message ToFirstFrame message or plain object to encode
                 * @param {$protobuf.Writer} [writer] Writer to encode to
                 * @returns {$protobuf.Writer} Writer
                 */
                ToFirstFrame.encodeDelimited = function encodeDelimited(message, writer) {
                    return this.encode(message, writer).ldelim();
                };

                /**
                 * Decodes a ToFirstFrame message from the specified reader or buffer.
                 * @function decode
                 * @memberof perfetto.protos.AndroidStartupMetric.ToFirstFrame
                 * @static
                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                 * @param {number} [length] Message length if known beforehand
                 * @returns {perfetto.protos.AndroidStartupMetric.ToFirstFrame} ToFirstFrame
                 * @throws {Error} If the payload is not a reader or valid buffer
                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
                 */
                ToFirstFrame.decode = function decode(reader, length) {
                    if (!(reader instanceof $Reader))
                        reader = $Reader.create(reader);
                    var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.AndroidStartupMetric.ToFirstFrame();
                    while (reader.pos < end) {
                        var tag = reader.uint32();
                        switch (tag >>> 3) {
                        case 1:
                            message.durNs = reader.int64();
                            break;
                        case 17:
                            message.durMs = reader.double();
                            break;
                        case 2:
                            message.mainThreadByTaskState = $root.perfetto.protos.AndroidStartupMetric.TaskStateBreakdown.decode(reader, reader.uint32());
                            break;
                        case 26:
                            message.mcyclesByCoreType = $root.perfetto.protos.AndroidStartupMetric.McyclesByCoreType.decode(reader, reader.uint32());
                            break;
                        case 3:
                            message.otherProcessesSpawnedCount = reader.uint32();
                            break;
                        case 4:
                            message.timeActivityManager = $root.perfetto.protos.AndroidStartupMetric.Slice.decode(reader, reader.uint32());
                            break;
                        case 5:
                            message.timeActivityThreadMain = $root.perfetto.protos.AndroidStartupMetric.Slice.decode(reader, reader.uint32());
                            break;
                        case 6:
                            message.timeBindApplication = $root.perfetto.protos.AndroidStartupMetric.Slice.decode(reader, reader.uint32());
                            break;
                        case 7:
                            message.timeActivityStart = $root.perfetto.protos.AndroidStartupMetric.Slice.decode(reader, reader.uint32());
                            break;
                        case 8:
                            message.timeActivityResume = $root.perfetto.protos.AndroidStartupMetric.Slice.decode(reader, reader.uint32());
                            break;
                        case 21:
                            message.timeActivityRestart = $root.perfetto.protos.AndroidStartupMetric.Slice.decode(reader, reader.uint32());
                            break;
                        case 9:
                            message.timeChoreographer = $root.perfetto.protos.AndroidStartupMetric.Slice.decode(reader, reader.uint32());
                            break;
                        case 22:
                            message.timeInflate = $root.perfetto.protos.AndroidStartupMetric.Slice.decode(reader, reader.uint32());
                            break;
                        case 23:
                            message.timeGetResources = $root.perfetto.protos.AndroidStartupMetric.Slice.decode(reader, reader.uint32());
                            break;
                        case 10:
                            message.timeBeforeStartProcess = $root.perfetto.protos.AndroidStartupMetric.Slice.decode(reader, reader.uint32());
                            break;
                        case 11:
                            message.timeDuringStartProcess = $root.perfetto.protos.AndroidStartupMetric.Slice.decode(reader, reader.uint32());
                            break;
                        case 18:
                            message.toPostFork = $root.perfetto.protos.AndroidStartupMetric.Slice.decode(reader, reader.uint32());
                            break;
                        case 19:
                            message.toActivityThreadMain = $root.perfetto.protos.AndroidStartupMetric.Slice.decode(reader, reader.uint32());
                            break;
                        case 20:
                            message.toBindApplication = $root.perfetto.protos.AndroidStartupMetric.Slice.decode(reader, reader.uint32());
                            break;
                        case 16:
                            message.timePostFork = $root.perfetto.protos.AndroidStartupMetric.Slice.decode(reader, reader.uint32());
                            break;
                        case 24:
                            message.timeDexOpen = $root.perfetto.protos.AndroidStartupMetric.Slice.decode(reader, reader.uint32());
                            break;
                        case 25:
                            message.timeVerifyClass = $root.perfetto.protos.AndroidStartupMetric.Slice.decode(reader, reader.uint32());
                            break;
                        case 27:
                            message.jitCompiledMethods = reader.uint32();
                            break;
                        case 28:
                            message.timeJitThreadPoolOnCpu = $root.perfetto.protos.AndroidStartupMetric.Slice.decode(reader, reader.uint32());
                            break;
                        case 29:
                            message.timeGcTotal = $root.perfetto.protos.AndroidStartupMetric.Slice.decode(reader, reader.uint32());
                            break;
                        case 30:
                            message.timeGcOnCpu = $root.perfetto.protos.AndroidStartupMetric.Slice.decode(reader, reader.uint32());
                            break;
                        default:
                            reader.skipType(tag & 7);
                            break;
                        }
                    }
                    return message;
                };

                /**
                 * Decodes a ToFirstFrame message from the specified reader or buffer, length delimited.
                 * @function decodeDelimited
                 * @memberof perfetto.protos.AndroidStartupMetric.ToFirstFrame
                 * @static
                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                 * @returns {perfetto.protos.AndroidStartupMetric.ToFirstFrame} ToFirstFrame
                 * @throws {Error} If the payload is not a reader or valid buffer
                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
                 */
                ToFirstFrame.decodeDelimited = function decodeDelimited(reader) {
                    if (!(reader instanceof $Reader))
                        reader = new $Reader(reader);
                    return this.decode(reader, reader.uint32());
                };

                /**
                 * Verifies a ToFirstFrame message.
                 * @function verify
                 * @memberof perfetto.protos.AndroidStartupMetric.ToFirstFrame
                 * @static
                 * @param {Object.<string,*>} message Plain object to verify
                 * @returns {string|null} `null` if valid, otherwise the reason why it is not
                 */
                ToFirstFrame.verify = function verify(message) {
                    if (typeof message !== "object" || message === null)
                        return "object expected";
                    if (message.durNs != null && message.hasOwnProperty("durNs"))
                        if (!$util.isInteger(message.durNs) && !(message.durNs && $util.isInteger(message.durNs.low) && $util.isInteger(message.durNs.high)))
                            return "durNs: integer|Long expected";
                    if (message.durMs != null && message.hasOwnProperty("durMs"))
                        if (typeof message.durMs !== "number")
                            return "durMs: number expected";
                    if (message.mainThreadByTaskState != null && message.hasOwnProperty("mainThreadByTaskState")) {
                        var error = $root.perfetto.protos.AndroidStartupMetric.TaskStateBreakdown.verify(message.mainThreadByTaskState);
                        if (error)
                            return "mainThreadByTaskState." + error;
                    }
                    if (message.mcyclesByCoreType != null && message.hasOwnProperty("mcyclesByCoreType")) {
                        var error = $root.perfetto.protos.AndroidStartupMetric.McyclesByCoreType.verify(message.mcyclesByCoreType);
                        if (error)
                            return "mcyclesByCoreType." + error;
                    }
                    if (message.otherProcessesSpawnedCount != null && message.hasOwnProperty("otherProcessesSpawnedCount"))
                        if (!$util.isInteger(message.otherProcessesSpawnedCount))
                            return "otherProcessesSpawnedCount: integer expected";
                    if (message.timeActivityManager != null && message.hasOwnProperty("timeActivityManager")) {
                        var error = $root.perfetto.protos.AndroidStartupMetric.Slice.verify(message.timeActivityManager);
                        if (error)
                            return "timeActivityManager." + error;
                    }
                    if (message.timeActivityThreadMain != null && message.hasOwnProperty("timeActivityThreadMain")) {
                        var error = $root.perfetto.protos.AndroidStartupMetric.Slice.verify(message.timeActivityThreadMain);
                        if (error)
                            return "timeActivityThreadMain." + error;
                    }
                    if (message.timeBindApplication != null && message.hasOwnProperty("timeBindApplication")) {
                        var error = $root.perfetto.protos.AndroidStartupMetric.Slice.verify(message.timeBindApplication);
                        if (error)
                            return "timeBindApplication." + error;
                    }
                    if (message.timeActivityStart != null && message.hasOwnProperty("timeActivityStart")) {
                        var error = $root.perfetto.protos.AndroidStartupMetric.Slice.verify(message.timeActivityStart);
                        if (error)
                            return "timeActivityStart." + error;
                    }
                    if (message.timeActivityResume != null && message.hasOwnProperty("timeActivityResume")) {
                        var error = $root.perfetto.protos.AndroidStartupMetric.Slice.verify(message.timeActivityResume);
                        if (error)
                            return "timeActivityResume." + error;
                    }
                    if (message.timeActivityRestart != null && message.hasOwnProperty("timeActivityRestart")) {
                        var error = $root.perfetto.protos.AndroidStartupMetric.Slice.verify(message.timeActivityRestart);
                        if (error)
                            return "timeActivityRestart." + error;
                    }
                    if (message.timeChoreographer != null && message.hasOwnProperty("timeChoreographer")) {
                        var error = $root.perfetto.protos.AndroidStartupMetric.Slice.verify(message.timeChoreographer);
                        if (error)
                            return "timeChoreographer." + error;
                    }
                    if (message.timeInflate != null && message.hasOwnProperty("timeInflate")) {
                        var error = $root.perfetto.protos.AndroidStartupMetric.Slice.verify(message.timeInflate);
                        if (error)
                            return "timeInflate." + error;
                    }
                    if (message.timeGetResources != null && message.hasOwnProperty("timeGetResources")) {
                        var error = $root.perfetto.protos.AndroidStartupMetric.Slice.verify(message.timeGetResources);
                        if (error)
                            return "timeGetResources." + error;
                    }
                    if (message.timeBeforeStartProcess != null && message.hasOwnProperty("timeBeforeStartProcess")) {
                        var error = $root.perfetto.protos.AndroidStartupMetric.Slice.verify(message.timeBeforeStartProcess);
                        if (error)
                            return "timeBeforeStartProcess." + error;
                    }
                    if (message.timeDuringStartProcess != null && message.hasOwnProperty("timeDuringStartProcess")) {
                        var error = $root.perfetto.protos.AndroidStartupMetric.Slice.verify(message.timeDuringStartProcess);
                        if (error)
                            return "timeDuringStartProcess." + error;
                    }
                    if (message.toPostFork != null && message.hasOwnProperty("toPostFork")) {
                        var error = $root.perfetto.protos.AndroidStartupMetric.Slice.verify(message.toPostFork);
                        if (error)
                            return "toPostFork." + error;
                    }
                    if (message.toActivityThreadMain != null && message.hasOwnProperty("toActivityThreadMain")) {
                        var error = $root.perfetto.protos.AndroidStartupMetric.Slice.verify(message.toActivityThreadMain);
                        if (error)
                            return "toActivityThreadMain." + error;
                    }
                    if (message.toBindApplication != null && message.hasOwnProperty("toBindApplication")) {
                        var error = $root.perfetto.protos.AndroidStartupMetric.Slice.verify(message.toBindApplication);
                        if (error)
                            return "toBindApplication." + error;
                    }
                    if (message.timePostFork != null && message.hasOwnProperty("timePostFork")) {
                        var error = $root.perfetto.protos.AndroidStartupMetric.Slice.verify(message.timePostFork);
                        if (error)
                            return "timePostFork." + error;
                    }
                    if (message.timeDexOpen != null && message.hasOwnProperty("timeDexOpen")) {
                        var error = $root.perfetto.protos.AndroidStartupMetric.Slice.verify(message.timeDexOpen);
                        if (error)
                            return "timeDexOpen." + error;
                    }
                    if (message.timeVerifyClass != null && message.hasOwnProperty("timeVerifyClass")) {
                        var error = $root.perfetto.protos.AndroidStartupMetric.Slice.verify(message.timeVerifyClass);
                        if (error)
                            return "timeVerifyClass." + error;
                    }
                    if (message.jitCompiledMethods != null && message.hasOwnProperty("jitCompiledMethods"))
                        if (!$util.isInteger(message.jitCompiledMethods))
                            return "jitCompiledMethods: integer expected";
                    if (message.timeJitThreadPoolOnCpu != null && message.hasOwnProperty("timeJitThreadPoolOnCpu")) {
                        var error = $root.perfetto.protos.AndroidStartupMetric.Slice.verify(message.timeJitThreadPoolOnCpu);
                        if (error)
                            return "timeJitThreadPoolOnCpu." + error;
                    }
                    if (message.timeGcTotal != null && message.hasOwnProperty("timeGcTotal")) {
                        var error = $root.perfetto.protos.AndroidStartupMetric.Slice.verify(message.timeGcTotal);
                        if (error)
                            return "timeGcTotal." + error;
                    }
                    if (message.timeGcOnCpu != null && message.hasOwnProperty("timeGcOnCpu")) {
                        var error = $root.perfetto.protos.AndroidStartupMetric.Slice.verify(message.timeGcOnCpu);
                        if (error)
                            return "timeGcOnCpu." + error;
                    }
                    return null;
                };

                /**
                 * Creates a ToFirstFrame message from a plain object. Also converts values to their respective internal types.
                 * @function fromObject
                 * @memberof perfetto.protos.AndroidStartupMetric.ToFirstFrame
                 * @static
                 * @param {Object.<string,*>} object Plain object
                 * @returns {perfetto.protos.AndroidStartupMetric.ToFirstFrame} ToFirstFrame
                 */
                ToFirstFrame.fromObject = function fromObject(object) {
                    if (object instanceof $root.perfetto.protos.AndroidStartupMetric.ToFirstFrame)
                        return object;
                    var message = new $root.perfetto.protos.AndroidStartupMetric.ToFirstFrame();
                    if (object.durNs != null)
                        if ($util.Long)
                            (message.durNs = $util.Long.fromValue(object.durNs)).unsigned = false;
                        else if (typeof object.durNs === "string")
                            message.durNs = parseInt(object.durNs, 10);
                        else if (typeof object.durNs === "number")
                            message.durNs = object.durNs;
                        else if (typeof object.durNs === "object")
                            message.durNs = new $util.LongBits(object.durNs.low >>> 0, object.durNs.high >>> 0).toNumber();
                    if (object.durMs != null)
                        message.durMs = Number(object.durMs);
                    if (object.mainThreadByTaskState != null) {
                        if (typeof object.mainThreadByTaskState !== "object")
                            throw TypeError(".perfetto.protos.AndroidStartupMetric.ToFirstFrame.mainThreadByTaskState: object expected");
                        message.mainThreadByTaskState = $root.perfetto.protos.AndroidStartupMetric.TaskStateBreakdown.fromObject(object.mainThreadByTaskState);
                    }
                    if (object.mcyclesByCoreType != null) {
                        if (typeof object.mcyclesByCoreType !== "object")
                            throw TypeError(".perfetto.protos.AndroidStartupMetric.ToFirstFrame.mcyclesByCoreType: object expected");
                        message.mcyclesByCoreType = $root.perfetto.protos.AndroidStartupMetric.McyclesByCoreType.fromObject(object.mcyclesByCoreType);
                    }
                    if (object.otherProcessesSpawnedCount != null)
                        message.otherProcessesSpawnedCount = object.otherProcessesSpawnedCount >>> 0;
                    if (object.timeActivityManager != null) {
                        if (typeof object.timeActivityManager !== "object")
                            throw TypeError(".perfetto.protos.AndroidStartupMetric.ToFirstFrame.timeActivityManager: object expected");
                        message.timeActivityManager = $root.perfetto.protos.AndroidStartupMetric.Slice.fromObject(object.timeActivityManager);
                    }
                    if (object.timeActivityThreadMain != null) {
                        if (typeof object.timeActivityThreadMain !== "object")
                            throw TypeError(".perfetto.protos.AndroidStartupMetric.ToFirstFrame.timeActivityThreadMain: object expected");
                        message.timeActivityThreadMain = $root.perfetto.protos.AndroidStartupMetric.Slice.fromObject(object.timeActivityThreadMain);
                    }
                    if (object.timeBindApplication != null) {
                        if (typeof object.timeBindApplication !== "object")
                            throw TypeError(".perfetto.protos.AndroidStartupMetric.ToFirstFrame.timeBindApplication: object expected");
                        message.timeBindApplication = $root.perfetto.protos.AndroidStartupMetric.Slice.fromObject(object.timeBindApplication);
                    }
                    if (object.timeActivityStart != null) {
                        if (typeof object.timeActivityStart !== "object")
                            throw TypeError(".perfetto.protos.AndroidStartupMetric.ToFirstFrame.timeActivityStart: object expected");
                        message.timeActivityStart = $root.perfetto.protos.AndroidStartupMetric.Slice.fromObject(object.timeActivityStart);
                    }
                    if (object.timeActivityResume != null) {
                        if (typeof object.timeActivityResume !== "object")
                            throw TypeError(".perfetto.protos.AndroidStartupMetric.ToFirstFrame.timeActivityResume: object expected");
                        message.timeActivityResume = $root.perfetto.protos.AndroidStartupMetric.Slice.fromObject(object.timeActivityResume);
                    }
                    if (object.timeActivityRestart != null) {
                        if (typeof object.timeActivityRestart !== "object")
                            throw TypeError(".perfetto.protos.AndroidStartupMetric.ToFirstFrame.timeActivityRestart: object expected");
                        message.timeActivityRestart = $root.perfetto.protos.AndroidStartupMetric.Slice.fromObject(object.timeActivityRestart);
                    }
                    if (object.timeChoreographer != null) {
                        if (typeof object.timeChoreographer !== "object")
                            throw TypeError(".perfetto.protos.AndroidStartupMetric.ToFirstFrame.timeChoreographer: object expected");
                        message.timeChoreographer = $root.perfetto.protos.AndroidStartupMetric.Slice.fromObject(object.timeChoreographer);
                    }
                    if (object.timeInflate != null) {
                        if (typeof object.timeInflate !== "object")
                            throw TypeError(".perfetto.protos.AndroidStartupMetric.ToFirstFrame.timeInflate: object expected");
                        message.timeInflate = $root.perfetto.protos.AndroidStartupMetric.Slice.fromObject(object.timeInflate);
                    }
                    if (object.timeGetResources != null) {
                        if (typeof object.timeGetResources !== "object")
                            throw TypeError(".perfetto.protos.AndroidStartupMetric.ToFirstFrame.timeGetResources: object expected");
                        message.timeGetResources = $root.perfetto.protos.AndroidStartupMetric.Slice.fromObject(object.timeGetResources);
                    }
                    if (object.timeBeforeStartProcess != null) {
                        if (typeof object.timeBeforeStartProcess !== "object")
                            throw TypeError(".perfetto.protos.AndroidStartupMetric.ToFirstFrame.timeBeforeStartProcess: object expected");
                        message.timeBeforeStartProcess = $root.perfetto.protos.AndroidStartupMetric.Slice.fromObject(object.timeBeforeStartProcess);
                    }
                    if (object.timeDuringStartProcess != null) {
                        if (typeof object.timeDuringStartProcess !== "object")
                            throw TypeError(".perfetto.protos.AndroidStartupMetric.ToFirstFrame.timeDuringStartProcess: object expected");
                        message.timeDuringStartProcess = $root.perfetto.protos.AndroidStartupMetric.Slice.fromObject(object.timeDuringStartProcess);
                    }
                    if (object.toPostFork != null) {
                        if (typeof object.toPostFork !== "object")
                            throw TypeError(".perfetto.protos.AndroidStartupMetric.ToFirstFrame.toPostFork: object expected");
                        message.toPostFork = $root.perfetto.protos.AndroidStartupMetric.Slice.fromObject(object.toPostFork);
                    }
                    if (object.toActivityThreadMain != null) {
                        if (typeof object.toActivityThreadMain !== "object")
                            throw TypeError(".perfetto.protos.AndroidStartupMetric.ToFirstFrame.toActivityThreadMain: object expected");
                        message.toActivityThreadMain = $root.perfetto.protos.AndroidStartupMetric.Slice.fromObject(object.toActivityThreadMain);
                    }
                    if (object.toBindApplication != null) {
                        if (typeof object.toBindApplication !== "object")
                            throw TypeError(".perfetto.protos.AndroidStartupMetric.ToFirstFrame.toBindApplication: object expected");
                        message.toBindApplication = $root.perfetto.protos.AndroidStartupMetric.Slice.fromObject(object.toBindApplication);
                    }
                    if (object.timePostFork != null) {
                        if (typeof object.timePostFork !== "object")
                            throw TypeError(".perfetto.protos.AndroidStartupMetric.ToFirstFrame.timePostFork: object expected");
                        message.timePostFork = $root.perfetto.protos.AndroidStartupMetric.Slice.fromObject(object.timePostFork);
                    }
                    if (object.timeDexOpen != null) {
                        if (typeof object.timeDexOpen !== "object")
                            throw TypeError(".perfetto.protos.AndroidStartupMetric.ToFirstFrame.timeDexOpen: object expected");
                        message.timeDexOpen = $root.perfetto.protos.AndroidStartupMetric.Slice.fromObject(object.timeDexOpen);
                    }
                    if (object.timeVerifyClass != null) {
                        if (typeof object.timeVerifyClass !== "object")
                            throw TypeError(".perfetto.protos.AndroidStartupMetric.ToFirstFrame.timeVerifyClass: object expected");
                        message.timeVerifyClass = $root.perfetto.protos.AndroidStartupMetric.Slice.fromObject(object.timeVerifyClass);
                    }
                    if (object.jitCompiledMethods != null)
                        message.jitCompiledMethods = object.jitCompiledMethods >>> 0;
                    if (object.timeJitThreadPoolOnCpu != null) {
                        if (typeof object.timeJitThreadPoolOnCpu !== "object")
                            throw TypeError(".perfetto.protos.AndroidStartupMetric.ToFirstFrame.timeJitThreadPoolOnCpu: object expected");
                        message.timeJitThreadPoolOnCpu = $root.perfetto.protos.AndroidStartupMetric.Slice.fromObject(object.timeJitThreadPoolOnCpu);
                    }
                    if (object.timeGcTotal != null) {
                        if (typeof object.timeGcTotal !== "object")
                            throw TypeError(".perfetto.protos.AndroidStartupMetric.ToFirstFrame.timeGcTotal: object expected");
                        message.timeGcTotal = $root.perfetto.protos.AndroidStartupMetric.Slice.fromObject(object.timeGcTotal);
                    }
                    if (object.timeGcOnCpu != null) {
                        if (typeof object.timeGcOnCpu !== "object")
                            throw TypeError(".perfetto.protos.AndroidStartupMetric.ToFirstFrame.timeGcOnCpu: object expected");
                        message.timeGcOnCpu = $root.perfetto.protos.AndroidStartupMetric.Slice.fromObject(object.timeGcOnCpu);
                    }
                    return message;
                };

                /**
                 * Creates a plain object from a ToFirstFrame message. Also converts values to other types if specified.
                 * @function toObject
                 * @memberof perfetto.protos.AndroidStartupMetric.ToFirstFrame
                 * @static
                 * @param {perfetto.protos.AndroidStartupMetric.ToFirstFrame} message ToFirstFrame
                 * @param {$protobuf.IConversionOptions} [options] Conversion options
                 * @returns {Object.<string,*>} Plain object
                 */
                ToFirstFrame.toObject = function toObject(message, options) {
                    if (!options)
                        options = {};
                    var object = {};
                    if (options.defaults) {
                        if ($util.Long) {
                            var long = new $util.Long(0, 0, false);
                            object.durNs = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
                        } else
                            object.durNs = options.longs === String ? "0" : 0;
                        object.mainThreadByTaskState = null;
                        object.otherProcessesSpawnedCount = 0;
                        object.timeActivityManager = null;
                        object.timeActivityThreadMain = null;
                        object.timeBindApplication = null;
                        object.timeActivityStart = null;
                        object.timeActivityResume = null;
                        object.timeChoreographer = null;
                        object.timeBeforeStartProcess = null;
                        object.timeDuringStartProcess = null;
                        object.timePostFork = null;
                        object.durMs = 0;
                        object.toPostFork = null;
                        object.toActivityThreadMain = null;
                        object.toBindApplication = null;
                        object.timeActivityRestart = null;
                        object.timeInflate = null;
                        object.timeGetResources = null;
                        object.timeDexOpen = null;
                        object.timeVerifyClass = null;
                        object.mcyclesByCoreType = null;
                        object.jitCompiledMethods = 0;
                        object.timeJitThreadPoolOnCpu = null;
                        object.timeGcTotal = null;
                        object.timeGcOnCpu = null;
                    }
                    if (message.durNs != null && message.hasOwnProperty("durNs"))
                        if (typeof message.durNs === "number")
                            object.durNs = options.longs === String ? String(message.durNs) : message.durNs;
                        else
                            object.durNs = options.longs === String ? $util.Long.prototype.toString.call(message.durNs) : options.longs === Number ? new $util.LongBits(message.durNs.low >>> 0, message.durNs.high >>> 0).toNumber() : message.durNs;
                    if (message.mainThreadByTaskState != null && message.hasOwnProperty("mainThreadByTaskState"))
                        object.mainThreadByTaskState = $root.perfetto.protos.AndroidStartupMetric.TaskStateBreakdown.toObject(message.mainThreadByTaskState, options);
                    if (message.otherProcessesSpawnedCount != null && message.hasOwnProperty("otherProcessesSpawnedCount"))
                        object.otherProcessesSpawnedCount = message.otherProcessesSpawnedCount;
                    if (message.timeActivityManager != null && message.hasOwnProperty("timeActivityManager"))
                        object.timeActivityManager = $root.perfetto.protos.AndroidStartupMetric.Slice.toObject(message.timeActivityManager, options);
                    if (message.timeActivityThreadMain != null && message.hasOwnProperty("timeActivityThreadMain"))
                        object.timeActivityThreadMain = $root.perfetto.protos.AndroidStartupMetric.Slice.toObject(message.timeActivityThreadMain, options);
                    if (message.timeBindApplication != null && message.hasOwnProperty("timeBindApplication"))
                        object.timeBindApplication = $root.perfetto.protos.AndroidStartupMetric.Slice.toObject(message.timeBindApplication, options);
                    if (message.timeActivityStart != null && message.hasOwnProperty("timeActivityStart"))
                        object.timeActivityStart = $root.perfetto.protos.AndroidStartupMetric.Slice.toObject(message.timeActivityStart, options);
                    if (message.timeActivityResume != null && message.hasOwnProperty("timeActivityResume"))
                        object.timeActivityResume = $root.perfetto.protos.AndroidStartupMetric.Slice.toObject(message.timeActivityResume, options);
                    if (message.timeChoreographer != null && message.hasOwnProperty("timeChoreographer"))
                        object.timeChoreographer = $root.perfetto.protos.AndroidStartupMetric.Slice.toObject(message.timeChoreographer, options);
                    if (message.timeBeforeStartProcess != null && message.hasOwnProperty("timeBeforeStartProcess"))
                        object.timeBeforeStartProcess = $root.perfetto.protos.AndroidStartupMetric.Slice.toObject(message.timeBeforeStartProcess, options);
                    if (message.timeDuringStartProcess != null && message.hasOwnProperty("timeDuringStartProcess"))
                        object.timeDuringStartProcess = $root.perfetto.protos.AndroidStartupMetric.Slice.toObject(message.timeDuringStartProcess, options);
                    if (message.timePostFork != null && message.hasOwnProperty("timePostFork"))
                        object.timePostFork = $root.perfetto.protos.AndroidStartupMetric.Slice.toObject(message.timePostFork, options);
                    if (message.durMs != null && message.hasOwnProperty("durMs"))
                        object.durMs = options.json && !isFinite(message.durMs) ? String(message.durMs) : message.durMs;
                    if (message.toPostFork != null && message.hasOwnProperty("toPostFork"))
                        object.toPostFork = $root.perfetto.protos.AndroidStartupMetric.Slice.toObject(message.toPostFork, options);
                    if (message.toActivityThreadMain != null && message.hasOwnProperty("toActivityThreadMain"))
                        object.toActivityThreadMain = $root.perfetto.protos.AndroidStartupMetric.Slice.toObject(message.toActivityThreadMain, options);
                    if (message.toBindApplication != null && message.hasOwnProperty("toBindApplication"))
                        object.toBindApplication = $root.perfetto.protos.AndroidStartupMetric.Slice.toObject(message.toBindApplication, options);
                    if (message.timeActivityRestart != null && message.hasOwnProperty("timeActivityRestart"))
                        object.timeActivityRestart = $root.perfetto.protos.AndroidStartupMetric.Slice.toObject(message.timeActivityRestart, options);
                    if (message.timeInflate != null && message.hasOwnProperty("timeInflate"))
                        object.timeInflate = $root.perfetto.protos.AndroidStartupMetric.Slice.toObject(message.timeInflate, options);
                    if (message.timeGetResources != null && message.hasOwnProperty("timeGetResources"))
                        object.timeGetResources = $root.perfetto.protos.AndroidStartupMetric.Slice.toObject(message.timeGetResources, options);
                    if (message.timeDexOpen != null && message.hasOwnProperty("timeDexOpen"))
                        object.timeDexOpen = $root.perfetto.protos.AndroidStartupMetric.Slice.toObject(message.timeDexOpen, options);
                    if (message.timeVerifyClass != null && message.hasOwnProperty("timeVerifyClass"))
                        object.timeVerifyClass = $root.perfetto.protos.AndroidStartupMetric.Slice.toObject(message.timeVerifyClass, options);
                    if (message.mcyclesByCoreType != null && message.hasOwnProperty("mcyclesByCoreType"))
                        object.mcyclesByCoreType = $root.perfetto.protos.AndroidStartupMetric.McyclesByCoreType.toObject(message.mcyclesByCoreType, options);
                    if (message.jitCompiledMethods != null && message.hasOwnProperty("jitCompiledMethods"))
                        object.jitCompiledMethods = message.jitCompiledMethods;
                    if (message.timeJitThreadPoolOnCpu != null && message.hasOwnProperty("timeJitThreadPoolOnCpu"))
                        object.timeJitThreadPoolOnCpu = $root.perfetto.protos.AndroidStartupMetric.Slice.toObject(message.timeJitThreadPoolOnCpu, options);
                    if (message.timeGcTotal != null && message.hasOwnProperty("timeGcTotal"))
                        object.timeGcTotal = $root.perfetto.protos.AndroidStartupMetric.Slice.toObject(message.timeGcTotal, options);
                    if (message.timeGcOnCpu != null && message.hasOwnProperty("timeGcOnCpu"))
                        object.timeGcOnCpu = $root.perfetto.protos.AndroidStartupMetric.Slice.toObject(message.timeGcOnCpu, options);
                    return object;
                };

                /**
                 * Converts this ToFirstFrame to JSON.
                 * @function toJSON
                 * @memberof perfetto.protos.AndroidStartupMetric.ToFirstFrame
                 * @instance
                 * @returns {Object.<string,*>} JSON object
                 */
                ToFirstFrame.prototype.toJSON = function toJSON() {
                    return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
                };

                return ToFirstFrame;
            })();

            AndroidStartupMetric.HscMetrics = (function() {

                /**
                 * Properties of a HscMetrics.
                 * @memberof perfetto.protos.AndroidStartupMetric
                 * @interface IHscMetrics
                 * @property {perfetto.protos.AndroidStartupMetric.ISlice|null} [fullStartup] HscMetrics fullStartup
                 */

                /**
                 * Constructs a new HscMetrics.
                 * @memberof perfetto.protos.AndroidStartupMetric
                 * @classdesc Represents a HscMetrics.
                 * @implements IHscMetrics
                 * @constructor
                 * @param {perfetto.protos.AndroidStartupMetric.IHscMetrics=} [properties] Properties to set
                 */
                function HscMetrics(properties) {
                    if (properties)
                        for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                            if (properties[keys[i]] != null)
                                this[keys[i]] = properties[keys[i]];
                }

                /**
                 * HscMetrics fullStartup.
                 * @member {perfetto.protos.AndroidStartupMetric.ISlice|null|undefined} fullStartup
                 * @memberof perfetto.protos.AndroidStartupMetric.HscMetrics
                 * @instance
                 */
                HscMetrics.prototype.fullStartup = null;

                /**
                 * Creates a new HscMetrics instance using the specified properties.
                 * @function create
                 * @memberof perfetto.protos.AndroidStartupMetric.HscMetrics
                 * @static
                 * @param {perfetto.protos.AndroidStartupMetric.IHscMetrics=} [properties] Properties to set
                 * @returns {perfetto.protos.AndroidStartupMetric.HscMetrics} HscMetrics instance
                 */
                HscMetrics.create = function create(properties) {
                    return new HscMetrics(properties);
                };

                /**
                 * Encodes the specified HscMetrics message. Does not implicitly {@link perfetto.protos.AndroidStartupMetric.HscMetrics.verify|verify} messages.
                 * @function encode
                 * @memberof perfetto.protos.AndroidStartupMetric.HscMetrics
                 * @static
                 * @param {perfetto.protos.AndroidStartupMetric.IHscMetrics} message HscMetrics message or plain object to encode
                 * @param {$protobuf.Writer} [writer] Writer to encode to
                 * @returns {$protobuf.Writer} Writer
                 */
                HscMetrics.encode = function encode(message, writer) {
                    if (!writer)
                        writer = $Writer.create();
                    if (message.fullStartup != null && Object.hasOwnProperty.call(message, "fullStartup"))
                        $root.perfetto.protos.AndroidStartupMetric.Slice.encode(message.fullStartup, writer.uint32(/* id 1, wireType 2 =*/10).fork()).ldelim();
                    return writer;
                };

                /**
                 * Encodes the specified HscMetrics message, length delimited. Does not implicitly {@link perfetto.protos.AndroidStartupMetric.HscMetrics.verify|verify} messages.
                 * @function encodeDelimited
                 * @memberof perfetto.protos.AndroidStartupMetric.HscMetrics
                 * @static
                 * @param {perfetto.protos.AndroidStartupMetric.IHscMetrics} message HscMetrics message or plain object to encode
                 * @param {$protobuf.Writer} [writer] Writer to encode to
                 * @returns {$protobuf.Writer} Writer
                 */
                HscMetrics.encodeDelimited = function encodeDelimited(message, writer) {
                    return this.encode(message, writer).ldelim();
                };

                /**
                 * Decodes a HscMetrics message from the specified reader or buffer.
                 * @function decode
                 * @memberof perfetto.protos.AndroidStartupMetric.HscMetrics
                 * @static
                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                 * @param {number} [length] Message length if known beforehand
                 * @returns {perfetto.protos.AndroidStartupMetric.HscMetrics} HscMetrics
                 * @throws {Error} If the payload is not a reader or valid buffer
                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
                 */
                HscMetrics.decode = function decode(reader, length) {
                    if (!(reader instanceof $Reader))
                        reader = $Reader.create(reader);
                    var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.AndroidStartupMetric.HscMetrics();
                    while (reader.pos < end) {
                        var tag = reader.uint32();
                        switch (tag >>> 3) {
                        case 1:
                            message.fullStartup = $root.perfetto.protos.AndroidStartupMetric.Slice.decode(reader, reader.uint32());
                            break;
                        default:
                            reader.skipType(tag & 7);
                            break;
                        }
                    }
                    return message;
                };

                /**
                 * Decodes a HscMetrics message from the specified reader or buffer, length delimited.
                 * @function decodeDelimited
                 * @memberof perfetto.protos.AndroidStartupMetric.HscMetrics
                 * @static
                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                 * @returns {perfetto.protos.AndroidStartupMetric.HscMetrics} HscMetrics
                 * @throws {Error} If the payload is not a reader or valid buffer
                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
                 */
                HscMetrics.decodeDelimited = function decodeDelimited(reader) {
                    if (!(reader instanceof $Reader))
                        reader = new $Reader(reader);
                    return this.decode(reader, reader.uint32());
                };

                /**
                 * Verifies a HscMetrics message.
                 * @function verify
                 * @memberof perfetto.protos.AndroidStartupMetric.HscMetrics
                 * @static
                 * @param {Object.<string,*>} message Plain object to verify
                 * @returns {string|null} `null` if valid, otherwise the reason why it is not
                 */
                HscMetrics.verify = function verify(message) {
                    if (typeof message !== "object" || message === null)
                        return "object expected";
                    if (message.fullStartup != null && message.hasOwnProperty("fullStartup")) {
                        var error = $root.perfetto.protos.AndroidStartupMetric.Slice.verify(message.fullStartup);
                        if (error)
                            return "fullStartup." + error;
                    }
                    return null;
                };

                /**
                 * Creates a HscMetrics message from a plain object. Also converts values to their respective internal types.
                 * @function fromObject
                 * @memberof perfetto.protos.AndroidStartupMetric.HscMetrics
                 * @static
                 * @param {Object.<string,*>} object Plain object
                 * @returns {perfetto.protos.AndroidStartupMetric.HscMetrics} HscMetrics
                 */
                HscMetrics.fromObject = function fromObject(object) {
                    if (object instanceof $root.perfetto.protos.AndroidStartupMetric.HscMetrics)
                        return object;
                    var message = new $root.perfetto.protos.AndroidStartupMetric.HscMetrics();
                    if (object.fullStartup != null) {
                        if (typeof object.fullStartup !== "object")
                            throw TypeError(".perfetto.protos.AndroidStartupMetric.HscMetrics.fullStartup: object expected");
                        message.fullStartup = $root.perfetto.protos.AndroidStartupMetric.Slice.fromObject(object.fullStartup);
                    }
                    return message;
                };

                /**
                 * Creates a plain object from a HscMetrics message. Also converts values to other types if specified.
                 * @function toObject
                 * @memberof perfetto.protos.AndroidStartupMetric.HscMetrics
                 * @static
                 * @param {perfetto.protos.AndroidStartupMetric.HscMetrics} message HscMetrics
                 * @param {$protobuf.IConversionOptions} [options] Conversion options
                 * @returns {Object.<string,*>} Plain object
                 */
                HscMetrics.toObject = function toObject(message, options) {
                    if (!options)
                        options = {};
                    var object = {};
                    if (options.defaults)
                        object.fullStartup = null;
                    if (message.fullStartup != null && message.hasOwnProperty("fullStartup"))
                        object.fullStartup = $root.perfetto.protos.AndroidStartupMetric.Slice.toObject(message.fullStartup, options);
                    return object;
                };

                /**
                 * Converts this HscMetrics to JSON.
                 * @function toJSON
                 * @memberof perfetto.protos.AndroidStartupMetric.HscMetrics
                 * @instance
                 * @returns {Object.<string,*>} JSON object
                 */
                HscMetrics.prototype.toJSON = function toJSON() {
                    return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
                };

                return HscMetrics;
            })();

            AndroidStartupMetric.Activity = (function() {

                /**
                 * Properties of an Activity.
                 * @memberof perfetto.protos.AndroidStartupMetric
                 * @interface IActivity
                 * @property {string|null} [name] Activity name
                 * @property {string|null} [method] Activity method
                 * @property {number|null} [tsMethodStart] Activity tsMethodStart
                 */

                /**
                 * Constructs a new Activity.
                 * @memberof perfetto.protos.AndroidStartupMetric
                 * @classdesc Represents an Activity.
                 * @implements IActivity
                 * @constructor
                 * @param {perfetto.protos.AndroidStartupMetric.IActivity=} [properties] Properties to set
                 */
                function Activity(properties) {
                    if (properties)
                        for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                            if (properties[keys[i]] != null)
                                this[keys[i]] = properties[keys[i]];
                }

                /**
                 * Activity name.
                 * @member {string} name
                 * @memberof perfetto.protos.AndroidStartupMetric.Activity
                 * @instance
                 */
                Activity.prototype.name = "";

                /**
                 * Activity method.
                 * @member {string} method
                 * @memberof perfetto.protos.AndroidStartupMetric.Activity
                 * @instance
                 */
                Activity.prototype.method = "";

                /**
                 * Activity tsMethodStart.
                 * @member {number} tsMethodStart
                 * @memberof perfetto.protos.AndroidStartupMetric.Activity
                 * @instance
                 */
                Activity.prototype.tsMethodStart = $util.Long ? $util.Long.fromBits(0,0,false) : 0;

                /**
                 * Creates a new Activity instance using the specified properties.
                 * @function create
                 * @memberof perfetto.protos.AndroidStartupMetric.Activity
                 * @static
                 * @param {perfetto.protos.AndroidStartupMetric.IActivity=} [properties] Properties to set
                 * @returns {perfetto.protos.AndroidStartupMetric.Activity} Activity instance
                 */
                Activity.create = function create(properties) {
                    return new Activity(properties);
                };

                /**
                 * Encodes the specified Activity message. Does not implicitly {@link perfetto.protos.AndroidStartupMetric.Activity.verify|verify} messages.
                 * @function encode
                 * @memberof perfetto.protos.AndroidStartupMetric.Activity
                 * @static
                 * @param {perfetto.protos.AndroidStartupMetric.IActivity} message Activity message or plain object to encode
                 * @param {$protobuf.Writer} [writer] Writer to encode to
                 * @returns {$protobuf.Writer} Writer
                 */
                Activity.encode = function encode(message, writer) {
                    if (!writer)
                        writer = $Writer.create();
                    if (message.name != null && Object.hasOwnProperty.call(message, "name"))
                        writer.uint32(/* id 1, wireType 2 =*/10).string(message.name);
                    if (message.method != null && Object.hasOwnProperty.call(message, "method"))
                        writer.uint32(/* id 2, wireType 2 =*/18).string(message.method);
                    if (message.tsMethodStart != null && Object.hasOwnProperty.call(message, "tsMethodStart"))
                        writer.uint32(/* id 4, wireType 0 =*/32).int64(message.tsMethodStart);
                    return writer;
                };

                /**
                 * Encodes the specified Activity message, length delimited. Does not implicitly {@link perfetto.protos.AndroidStartupMetric.Activity.verify|verify} messages.
                 * @function encodeDelimited
                 * @memberof perfetto.protos.AndroidStartupMetric.Activity
                 * @static
                 * @param {perfetto.protos.AndroidStartupMetric.IActivity} message Activity message or plain object to encode
                 * @param {$protobuf.Writer} [writer] Writer to encode to
                 * @returns {$protobuf.Writer} Writer
                 */
                Activity.encodeDelimited = function encodeDelimited(message, writer) {
                    return this.encode(message, writer).ldelim();
                };

                /**
                 * Decodes an Activity message from the specified reader or buffer.
                 * @function decode
                 * @memberof perfetto.protos.AndroidStartupMetric.Activity
                 * @static
                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                 * @param {number} [length] Message length if known beforehand
                 * @returns {perfetto.protos.AndroidStartupMetric.Activity} Activity
                 * @throws {Error} If the payload is not a reader or valid buffer
                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
                 */
                Activity.decode = function decode(reader, length) {
                    if (!(reader instanceof $Reader))
                        reader = $Reader.create(reader);
                    var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.AndroidStartupMetric.Activity();
                    while (reader.pos < end) {
                        var tag = reader.uint32();
                        switch (tag >>> 3) {
                        case 1:
                            message.name = reader.string();
                            break;
                        case 2:
                            message.method = reader.string();
                            break;
                        case 4:
                            message.tsMethodStart = reader.int64();
                            break;
                        default:
                            reader.skipType(tag & 7);
                            break;
                        }
                    }
                    return message;
                };

                /**
                 * Decodes an Activity message from the specified reader or buffer, length delimited.
                 * @function decodeDelimited
                 * @memberof perfetto.protos.AndroidStartupMetric.Activity
                 * @static
                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                 * @returns {perfetto.protos.AndroidStartupMetric.Activity} Activity
                 * @throws {Error} If the payload is not a reader or valid buffer
                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
                 */
                Activity.decodeDelimited = function decodeDelimited(reader) {
                    if (!(reader instanceof $Reader))
                        reader = new $Reader(reader);
                    return this.decode(reader, reader.uint32());
                };

                /**
                 * Verifies an Activity message.
                 * @function verify
                 * @memberof perfetto.protos.AndroidStartupMetric.Activity
                 * @static
                 * @param {Object.<string,*>} message Plain object to verify
                 * @returns {string|null} `null` if valid, otherwise the reason why it is not
                 */
                Activity.verify = function verify(message) {
                    if (typeof message !== "object" || message === null)
                        return "object expected";
                    if (message.name != null && message.hasOwnProperty("name"))
                        if (!$util.isString(message.name))
                            return "name: string expected";
                    if (message.method != null && message.hasOwnProperty("method"))
                        if (!$util.isString(message.method))
                            return "method: string expected";
                    if (message.tsMethodStart != null && message.hasOwnProperty("tsMethodStart"))
                        if (!$util.isInteger(message.tsMethodStart) && !(message.tsMethodStart && $util.isInteger(message.tsMethodStart.low) && $util.isInteger(message.tsMethodStart.high)))
                            return "tsMethodStart: integer|Long expected";
                    return null;
                };

                /**
                 * Creates an Activity message from a plain object. Also converts values to their respective internal types.
                 * @function fromObject
                 * @memberof perfetto.protos.AndroidStartupMetric.Activity
                 * @static
                 * @param {Object.<string,*>} object Plain object
                 * @returns {perfetto.protos.AndroidStartupMetric.Activity} Activity
                 */
                Activity.fromObject = function fromObject(object) {
                    if (object instanceof $root.perfetto.protos.AndroidStartupMetric.Activity)
                        return object;
                    var message = new $root.perfetto.protos.AndroidStartupMetric.Activity();
                    if (object.name != null)
                        message.name = String(object.name);
                    if (object.method != null)
                        message.method = String(object.method);
                    if (object.tsMethodStart != null)
                        if ($util.Long)
                            (message.tsMethodStart = $util.Long.fromValue(object.tsMethodStart)).unsigned = false;
                        else if (typeof object.tsMethodStart === "string")
                            message.tsMethodStart = parseInt(object.tsMethodStart, 10);
                        else if (typeof object.tsMethodStart === "number")
                            message.tsMethodStart = object.tsMethodStart;
                        else if (typeof object.tsMethodStart === "object")
                            message.tsMethodStart = new $util.LongBits(object.tsMethodStart.low >>> 0, object.tsMethodStart.high >>> 0).toNumber();
                    return message;
                };

                /**
                 * Creates a plain object from an Activity message. Also converts values to other types if specified.
                 * @function toObject
                 * @memberof perfetto.protos.AndroidStartupMetric.Activity
                 * @static
                 * @param {perfetto.protos.AndroidStartupMetric.Activity} message Activity
                 * @param {$protobuf.IConversionOptions} [options] Conversion options
                 * @returns {Object.<string,*>} Plain object
                 */
                Activity.toObject = function toObject(message, options) {
                    if (!options)
                        options = {};
                    var object = {};
                    if (options.defaults) {
                        object.name = "";
                        object.method = "";
                        if ($util.Long) {
                            var long = new $util.Long(0, 0, false);
                            object.tsMethodStart = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
                        } else
                            object.tsMethodStart = options.longs === String ? "0" : 0;
                    }
                    if (message.name != null && message.hasOwnProperty("name"))
                        object.name = message.name;
                    if (message.method != null && message.hasOwnProperty("method"))
                        object.method = message.method;
                    if (message.tsMethodStart != null && message.hasOwnProperty("tsMethodStart"))
                        if (typeof message.tsMethodStart === "number")
                            object.tsMethodStart = options.longs === String ? String(message.tsMethodStart) : message.tsMethodStart;
                        else
                            object.tsMethodStart = options.longs === String ? $util.Long.prototype.toString.call(message.tsMethodStart) : options.longs === Number ? new $util.LongBits(message.tsMethodStart.low >>> 0, message.tsMethodStart.high >>> 0).toNumber() : message.tsMethodStart;
                    return object;
                };

                /**
                 * Converts this Activity to JSON.
                 * @function toJSON
                 * @memberof perfetto.protos.AndroidStartupMetric.Activity
                 * @instance
                 * @returns {Object.<string,*>} JSON object
                 */
                Activity.prototype.toJSON = function toJSON() {
                    return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
                };

                return Activity;
            })();

            AndroidStartupMetric.BinderTransaction = (function() {

                /**
                 * Properties of a BinderTransaction.
                 * @memberof perfetto.protos.AndroidStartupMetric
                 * @interface IBinderTransaction
                 * @property {perfetto.protos.AndroidStartupMetric.ISlice|null} [duration] BinderTransaction duration
                 * @property {string|null} [thread] BinderTransaction thread
                 */

                /**
                 * Constructs a new BinderTransaction.
                 * @memberof perfetto.protos.AndroidStartupMetric
                 * @classdesc Represents a BinderTransaction.
                 * @implements IBinderTransaction
                 * @constructor
                 * @param {perfetto.protos.AndroidStartupMetric.IBinderTransaction=} [properties] Properties to set
                 */
                function BinderTransaction(properties) {
                    if (properties)
                        for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                            if (properties[keys[i]] != null)
                                this[keys[i]] = properties[keys[i]];
                }

                /**
                 * BinderTransaction duration.
                 * @member {perfetto.protos.AndroidStartupMetric.ISlice|null|undefined} duration
                 * @memberof perfetto.protos.AndroidStartupMetric.BinderTransaction
                 * @instance
                 */
                BinderTransaction.prototype.duration = null;

                /**
                 * BinderTransaction thread.
                 * @member {string} thread
                 * @memberof perfetto.protos.AndroidStartupMetric.BinderTransaction
                 * @instance
                 */
                BinderTransaction.prototype.thread = "";

                /**
                 * Creates a new BinderTransaction instance using the specified properties.
                 * @function create
                 * @memberof perfetto.protos.AndroidStartupMetric.BinderTransaction
                 * @static
                 * @param {perfetto.protos.AndroidStartupMetric.IBinderTransaction=} [properties] Properties to set
                 * @returns {perfetto.protos.AndroidStartupMetric.BinderTransaction} BinderTransaction instance
                 */
                BinderTransaction.create = function create(properties) {
                    return new BinderTransaction(properties);
                };

                /**
                 * Encodes the specified BinderTransaction message. Does not implicitly {@link perfetto.protos.AndroidStartupMetric.BinderTransaction.verify|verify} messages.
                 * @function encode
                 * @memberof perfetto.protos.AndroidStartupMetric.BinderTransaction
                 * @static
                 * @param {perfetto.protos.AndroidStartupMetric.IBinderTransaction} message BinderTransaction message or plain object to encode
                 * @param {$protobuf.Writer} [writer] Writer to encode to
                 * @returns {$protobuf.Writer} Writer
                 */
                BinderTransaction.encode = function encode(message, writer) {
                    if (!writer)
                        writer = $Writer.create();
                    if (message.duration != null && Object.hasOwnProperty.call(message, "duration"))
                        $root.perfetto.protos.AndroidStartupMetric.Slice.encode(message.duration, writer.uint32(/* id 1, wireType 2 =*/10).fork()).ldelim();
                    if (message.thread != null && Object.hasOwnProperty.call(message, "thread"))
                        writer.uint32(/* id 2, wireType 2 =*/18).string(message.thread);
                    return writer;
                };

                /**
                 * Encodes the specified BinderTransaction message, length delimited. Does not implicitly {@link perfetto.protos.AndroidStartupMetric.BinderTransaction.verify|verify} messages.
                 * @function encodeDelimited
                 * @memberof perfetto.protos.AndroidStartupMetric.BinderTransaction
                 * @static
                 * @param {perfetto.protos.AndroidStartupMetric.IBinderTransaction} message BinderTransaction message or plain object to encode
                 * @param {$protobuf.Writer} [writer] Writer to encode to
                 * @returns {$protobuf.Writer} Writer
                 */
                BinderTransaction.encodeDelimited = function encodeDelimited(message, writer) {
                    return this.encode(message, writer).ldelim();
                };

                /**
                 * Decodes a BinderTransaction message from the specified reader or buffer.
                 * @function decode
                 * @memberof perfetto.protos.AndroidStartupMetric.BinderTransaction
                 * @static
                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                 * @param {number} [length] Message length if known beforehand
                 * @returns {perfetto.protos.AndroidStartupMetric.BinderTransaction} BinderTransaction
                 * @throws {Error} If the payload is not a reader or valid buffer
                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
                 */
                BinderTransaction.decode = function decode(reader, length) {
                    if (!(reader instanceof $Reader))
                        reader = $Reader.create(reader);
                    var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.AndroidStartupMetric.BinderTransaction();
                    while (reader.pos < end) {
                        var tag = reader.uint32();
                        switch (tag >>> 3) {
                        case 1:
                            message.duration = $root.perfetto.protos.AndroidStartupMetric.Slice.decode(reader, reader.uint32());
                            break;
                        case 2:
                            message.thread = reader.string();
                            break;
                        default:
                            reader.skipType(tag & 7);
                            break;
                        }
                    }
                    return message;
                };

                /**
                 * Decodes a BinderTransaction message from the specified reader or buffer, length delimited.
                 * @function decodeDelimited
                 * @memberof perfetto.protos.AndroidStartupMetric.BinderTransaction
                 * @static
                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                 * @returns {perfetto.protos.AndroidStartupMetric.BinderTransaction} BinderTransaction
                 * @throws {Error} If the payload is not a reader or valid buffer
                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
                 */
                BinderTransaction.decodeDelimited = function decodeDelimited(reader) {
                    if (!(reader instanceof $Reader))
                        reader = new $Reader(reader);
                    return this.decode(reader, reader.uint32());
                };

                /**
                 * Verifies a BinderTransaction message.
                 * @function verify
                 * @memberof perfetto.protos.AndroidStartupMetric.BinderTransaction
                 * @static
                 * @param {Object.<string,*>} message Plain object to verify
                 * @returns {string|null} `null` if valid, otherwise the reason why it is not
                 */
                BinderTransaction.verify = function verify(message) {
                    if (typeof message !== "object" || message === null)
                        return "object expected";
                    if (message.duration != null && message.hasOwnProperty("duration")) {
                        var error = $root.perfetto.protos.AndroidStartupMetric.Slice.verify(message.duration);
                        if (error)
                            return "duration." + error;
                    }
                    if (message.thread != null && message.hasOwnProperty("thread"))
                        if (!$util.isString(message.thread))
                            return "thread: string expected";
                    return null;
                };

                /**
                 * Creates a BinderTransaction message from a plain object. Also converts values to their respective internal types.
                 * @function fromObject
                 * @memberof perfetto.protos.AndroidStartupMetric.BinderTransaction
                 * @static
                 * @param {Object.<string,*>} object Plain object
                 * @returns {perfetto.protos.AndroidStartupMetric.BinderTransaction} BinderTransaction
                 */
                BinderTransaction.fromObject = function fromObject(object) {
                    if (object instanceof $root.perfetto.protos.AndroidStartupMetric.BinderTransaction)
                        return object;
                    var message = new $root.perfetto.protos.AndroidStartupMetric.BinderTransaction();
                    if (object.duration != null) {
                        if (typeof object.duration !== "object")
                            throw TypeError(".perfetto.protos.AndroidStartupMetric.BinderTransaction.duration: object expected");
                        message.duration = $root.perfetto.protos.AndroidStartupMetric.Slice.fromObject(object.duration);
                    }
                    if (object.thread != null)
                        message.thread = String(object.thread);
                    return message;
                };

                /**
                 * Creates a plain object from a BinderTransaction message. Also converts values to other types if specified.
                 * @function toObject
                 * @memberof perfetto.protos.AndroidStartupMetric.BinderTransaction
                 * @static
                 * @param {perfetto.protos.AndroidStartupMetric.BinderTransaction} message BinderTransaction
                 * @param {$protobuf.IConversionOptions} [options] Conversion options
                 * @returns {Object.<string,*>} Plain object
                 */
                BinderTransaction.toObject = function toObject(message, options) {
                    if (!options)
                        options = {};
                    var object = {};
                    if (options.defaults) {
                        object.duration = null;
                        object.thread = "";
                    }
                    if (message.duration != null && message.hasOwnProperty("duration"))
                        object.duration = $root.perfetto.protos.AndroidStartupMetric.Slice.toObject(message.duration, options);
                    if (message.thread != null && message.hasOwnProperty("thread"))
                        object.thread = message.thread;
                    return object;
                };

                /**
                 * Converts this BinderTransaction to JSON.
                 * @function toJSON
                 * @memberof perfetto.protos.AndroidStartupMetric.BinderTransaction
                 * @instance
                 * @returns {Object.<string,*>} JSON object
                 */
                BinderTransaction.prototype.toJSON = function toJSON() {
                    return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
                };

                return BinderTransaction;
            })();

            AndroidStartupMetric.OptimizationStatus = (function() {

                /**
                 * Properties of an OptimizationStatus.
                 * @memberof perfetto.protos.AndroidStartupMetric
                 * @interface IOptimizationStatus
                 * @property {string|null} [odexStatus] OptimizationStatus odexStatus
                 * @property {string|null} [compilationFilter] OptimizationStatus compilationFilter
                 * @property {string|null} [compilationReason] OptimizationStatus compilationReason
                 * @property {string|null} [location] OptimizationStatus location
                 */

                /**
                 * Constructs a new OptimizationStatus.
                 * @memberof perfetto.protos.AndroidStartupMetric
                 * @classdesc Represents an OptimizationStatus.
                 * @implements IOptimizationStatus
                 * @constructor
                 * @param {perfetto.protos.AndroidStartupMetric.IOptimizationStatus=} [properties] Properties to set
                 */
                function OptimizationStatus(properties) {
                    if (properties)
                        for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                            if (properties[keys[i]] != null)
                                this[keys[i]] = properties[keys[i]];
                }

                /**
                 * OptimizationStatus odexStatus.
                 * @member {string} odexStatus
                 * @memberof perfetto.protos.AndroidStartupMetric.OptimizationStatus
                 * @instance
                 */
                OptimizationStatus.prototype.odexStatus = "";

                /**
                 * OptimizationStatus compilationFilter.
                 * @member {string} compilationFilter
                 * @memberof perfetto.protos.AndroidStartupMetric.OptimizationStatus
                 * @instance
                 */
                OptimizationStatus.prototype.compilationFilter = "";

                /**
                 * OptimizationStatus compilationReason.
                 * @member {string} compilationReason
                 * @memberof perfetto.protos.AndroidStartupMetric.OptimizationStatus
                 * @instance
                 */
                OptimizationStatus.prototype.compilationReason = "";

                /**
                 * OptimizationStatus location.
                 * @member {string} location
                 * @memberof perfetto.protos.AndroidStartupMetric.OptimizationStatus
                 * @instance
                 */
                OptimizationStatus.prototype.location = "";

                /**
                 * Creates a new OptimizationStatus instance using the specified properties.
                 * @function create
                 * @memberof perfetto.protos.AndroidStartupMetric.OptimizationStatus
                 * @static
                 * @param {perfetto.protos.AndroidStartupMetric.IOptimizationStatus=} [properties] Properties to set
                 * @returns {perfetto.protos.AndroidStartupMetric.OptimizationStatus} OptimizationStatus instance
                 */
                OptimizationStatus.create = function create(properties) {
                    return new OptimizationStatus(properties);
                };

                /**
                 * Encodes the specified OptimizationStatus message. Does not implicitly {@link perfetto.protos.AndroidStartupMetric.OptimizationStatus.verify|verify} messages.
                 * @function encode
                 * @memberof perfetto.protos.AndroidStartupMetric.OptimizationStatus
                 * @static
                 * @param {perfetto.protos.AndroidStartupMetric.IOptimizationStatus} message OptimizationStatus message or plain object to encode
                 * @param {$protobuf.Writer} [writer] Writer to encode to
                 * @returns {$protobuf.Writer} Writer
                 */
                OptimizationStatus.encode = function encode(message, writer) {
                    if (!writer)
                        writer = $Writer.create();
                    if (message.odexStatus != null && Object.hasOwnProperty.call(message, "odexStatus"))
                        writer.uint32(/* id 1, wireType 2 =*/10).string(message.odexStatus);
                    if (message.compilationFilter != null && Object.hasOwnProperty.call(message, "compilationFilter"))
                        writer.uint32(/* id 2, wireType 2 =*/18).string(message.compilationFilter);
                    if (message.compilationReason != null && Object.hasOwnProperty.call(message, "compilationReason"))
                        writer.uint32(/* id 3, wireType 2 =*/26).string(message.compilationReason);
                    if (message.location != null && Object.hasOwnProperty.call(message, "location"))
                        writer.uint32(/* id 4, wireType 2 =*/34).string(message.location);
                    return writer;
                };

                /**
                 * Encodes the specified OptimizationStatus message, length delimited. Does not implicitly {@link perfetto.protos.AndroidStartupMetric.OptimizationStatus.verify|verify} messages.
                 * @function encodeDelimited
                 * @memberof perfetto.protos.AndroidStartupMetric.OptimizationStatus
                 * @static
                 * @param {perfetto.protos.AndroidStartupMetric.IOptimizationStatus} message OptimizationStatus message or plain object to encode
                 * @param {$protobuf.Writer} [writer] Writer to encode to
                 * @returns {$protobuf.Writer} Writer
                 */
                OptimizationStatus.encodeDelimited = function encodeDelimited(message, writer) {
                    return this.encode(message, writer).ldelim();
                };

                /**
                 * Decodes an OptimizationStatus message from the specified reader or buffer.
                 * @function decode
                 * @memberof perfetto.protos.AndroidStartupMetric.OptimizationStatus
                 * @static
                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                 * @param {number} [length] Message length if known beforehand
                 * @returns {perfetto.protos.AndroidStartupMetric.OptimizationStatus} OptimizationStatus
                 * @throws {Error} If the payload is not a reader or valid buffer
                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
                 */
                OptimizationStatus.decode = function decode(reader, length) {
                    if (!(reader instanceof $Reader))
                        reader = $Reader.create(reader);
                    var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.AndroidStartupMetric.OptimizationStatus();
                    while (reader.pos < end) {
                        var tag = reader.uint32();
                        switch (tag >>> 3) {
                        case 1:
                            message.odexStatus = reader.string();
                            break;
                        case 2:
                            message.compilationFilter = reader.string();
                            break;
                        case 3:
                            message.compilationReason = reader.string();
                            break;
                        case 4:
                            message.location = reader.string();
                            break;
                        default:
                            reader.skipType(tag & 7);
                            break;
                        }
                    }
                    return message;
                };

                /**
                 * Decodes an OptimizationStatus message from the specified reader or buffer, length delimited.
                 * @function decodeDelimited
                 * @memberof perfetto.protos.AndroidStartupMetric.OptimizationStatus
                 * @static
                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                 * @returns {perfetto.protos.AndroidStartupMetric.OptimizationStatus} OptimizationStatus
                 * @throws {Error} If the payload is not a reader or valid buffer
                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
                 */
                OptimizationStatus.decodeDelimited = function decodeDelimited(reader) {
                    if (!(reader instanceof $Reader))
                        reader = new $Reader(reader);
                    return this.decode(reader, reader.uint32());
                };

                /**
                 * Verifies an OptimizationStatus message.
                 * @function verify
                 * @memberof perfetto.protos.AndroidStartupMetric.OptimizationStatus
                 * @static
                 * @param {Object.<string,*>} message Plain object to verify
                 * @returns {string|null} `null` if valid, otherwise the reason why it is not
                 */
                OptimizationStatus.verify = function verify(message) {
                    if (typeof message !== "object" || message === null)
                        return "object expected";
                    if (message.odexStatus != null && message.hasOwnProperty("odexStatus"))
                        if (!$util.isString(message.odexStatus))
                            return "odexStatus: string expected";
                    if (message.compilationFilter != null && message.hasOwnProperty("compilationFilter"))
                        if (!$util.isString(message.compilationFilter))
                            return "compilationFilter: string expected";
                    if (message.compilationReason != null && message.hasOwnProperty("compilationReason"))
                        if (!$util.isString(message.compilationReason))
                            return "compilationReason: string expected";
                    if (message.location != null && message.hasOwnProperty("location"))
                        if (!$util.isString(message.location))
                            return "location: string expected";
                    return null;
                };

                /**
                 * Creates an OptimizationStatus message from a plain object. Also converts values to their respective internal types.
                 * @function fromObject
                 * @memberof perfetto.protos.AndroidStartupMetric.OptimizationStatus
                 * @static
                 * @param {Object.<string,*>} object Plain object
                 * @returns {perfetto.protos.AndroidStartupMetric.OptimizationStatus} OptimizationStatus
                 */
                OptimizationStatus.fromObject = function fromObject(object) {
                    if (object instanceof $root.perfetto.protos.AndroidStartupMetric.OptimizationStatus)
                        return object;
                    var message = new $root.perfetto.protos.AndroidStartupMetric.OptimizationStatus();
                    if (object.odexStatus != null)
                        message.odexStatus = String(object.odexStatus);
                    if (object.compilationFilter != null)
                        message.compilationFilter = String(object.compilationFilter);
                    if (object.compilationReason != null)
                        message.compilationReason = String(object.compilationReason);
                    if (object.location != null)
                        message.location = String(object.location);
                    return message;
                };

                /**
                 * Creates a plain object from an OptimizationStatus message. Also converts values to other types if specified.
                 * @function toObject
                 * @memberof perfetto.protos.AndroidStartupMetric.OptimizationStatus
                 * @static
                 * @param {perfetto.protos.AndroidStartupMetric.OptimizationStatus} message OptimizationStatus
                 * @param {$protobuf.IConversionOptions} [options] Conversion options
                 * @returns {Object.<string,*>} Plain object
                 */
                OptimizationStatus.toObject = function toObject(message, options) {
                    if (!options)
                        options = {};
                    var object = {};
                    if (options.defaults) {
                        object.odexStatus = "";
                        object.compilationFilter = "";
                        object.compilationReason = "";
                        object.location = "";
                    }
                    if (message.odexStatus != null && message.hasOwnProperty("odexStatus"))
                        object.odexStatus = message.odexStatus;
                    if (message.compilationFilter != null && message.hasOwnProperty("compilationFilter"))
                        object.compilationFilter = message.compilationFilter;
                    if (message.compilationReason != null && message.hasOwnProperty("compilationReason"))
                        object.compilationReason = message.compilationReason;
                    if (message.location != null && message.hasOwnProperty("location"))
                        object.location = message.location;
                    return object;
                };

                /**
                 * Converts this OptimizationStatus to JSON.
                 * @function toJSON
                 * @memberof perfetto.protos.AndroidStartupMetric.OptimizationStatus
                 * @instance
                 * @returns {Object.<string,*>} JSON object
                 */
                OptimizationStatus.prototype.toJSON = function toJSON() {
                    return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
                };

                return OptimizationStatus;
            })();

            AndroidStartupMetric.EventTimestamps = (function() {

                /**
                 * Properties of an EventTimestamps.
                 * @memberof perfetto.protos.AndroidStartupMetric
                 * @interface IEventTimestamps
                 * @property {number|null} [intentReceived] EventTimestamps intentReceived
                 * @property {number|null} [firstFrame] EventTimestamps firstFrame
                 */

                /**
                 * Constructs a new EventTimestamps.
                 * @memberof perfetto.protos.AndroidStartupMetric
                 * @classdesc Represents an EventTimestamps.
                 * @implements IEventTimestamps
                 * @constructor
                 * @param {perfetto.protos.AndroidStartupMetric.IEventTimestamps=} [properties] Properties to set
                 */
                function EventTimestamps(properties) {
                    if (properties)
                        for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                            if (properties[keys[i]] != null)
                                this[keys[i]] = properties[keys[i]];
                }

                /**
                 * EventTimestamps intentReceived.
                 * @member {number} intentReceived
                 * @memberof perfetto.protos.AndroidStartupMetric.EventTimestamps
                 * @instance
                 */
                EventTimestamps.prototype.intentReceived = $util.Long ? $util.Long.fromBits(0,0,false) : 0;

                /**
                 * EventTimestamps firstFrame.
                 * @member {number} firstFrame
                 * @memberof perfetto.protos.AndroidStartupMetric.EventTimestamps
                 * @instance
                 */
                EventTimestamps.prototype.firstFrame = $util.Long ? $util.Long.fromBits(0,0,false) : 0;

                /**
                 * Creates a new EventTimestamps instance using the specified properties.
                 * @function create
                 * @memberof perfetto.protos.AndroidStartupMetric.EventTimestamps
                 * @static
                 * @param {perfetto.protos.AndroidStartupMetric.IEventTimestamps=} [properties] Properties to set
                 * @returns {perfetto.protos.AndroidStartupMetric.EventTimestamps} EventTimestamps instance
                 */
                EventTimestamps.create = function create(properties) {
                    return new EventTimestamps(properties);
                };

                /**
                 * Encodes the specified EventTimestamps message. Does not implicitly {@link perfetto.protos.AndroidStartupMetric.EventTimestamps.verify|verify} messages.
                 * @function encode
                 * @memberof perfetto.protos.AndroidStartupMetric.EventTimestamps
                 * @static
                 * @param {perfetto.protos.AndroidStartupMetric.IEventTimestamps} message EventTimestamps message or plain object to encode
                 * @param {$protobuf.Writer} [writer] Writer to encode to
                 * @returns {$protobuf.Writer} Writer
                 */
                EventTimestamps.encode = function encode(message, writer) {
                    if (!writer)
                        writer = $Writer.create();
                    if (message.intentReceived != null && Object.hasOwnProperty.call(message, "intentReceived"))
                        writer.uint32(/* id 1, wireType 0 =*/8).int64(message.intentReceived);
                    if (message.firstFrame != null && Object.hasOwnProperty.call(message, "firstFrame"))
                        writer.uint32(/* id 2, wireType 0 =*/16).int64(message.firstFrame);
                    return writer;
                };

                /**
                 * Encodes the specified EventTimestamps message, length delimited. Does not implicitly {@link perfetto.protos.AndroidStartupMetric.EventTimestamps.verify|verify} messages.
                 * @function encodeDelimited
                 * @memberof perfetto.protos.AndroidStartupMetric.EventTimestamps
                 * @static
                 * @param {perfetto.protos.AndroidStartupMetric.IEventTimestamps} message EventTimestamps message or plain object to encode
                 * @param {$protobuf.Writer} [writer] Writer to encode to
                 * @returns {$protobuf.Writer} Writer
                 */
                EventTimestamps.encodeDelimited = function encodeDelimited(message, writer) {
                    return this.encode(message, writer).ldelim();
                };

                /**
                 * Decodes an EventTimestamps message from the specified reader or buffer.
                 * @function decode
                 * @memberof perfetto.protos.AndroidStartupMetric.EventTimestamps
                 * @static
                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                 * @param {number} [length] Message length if known beforehand
                 * @returns {perfetto.protos.AndroidStartupMetric.EventTimestamps} EventTimestamps
                 * @throws {Error} If the payload is not a reader or valid buffer
                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
                 */
                EventTimestamps.decode = function decode(reader, length) {
                    if (!(reader instanceof $Reader))
                        reader = $Reader.create(reader);
                    var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.AndroidStartupMetric.EventTimestamps();
                    while (reader.pos < end) {
                        var tag = reader.uint32();
                        switch (tag >>> 3) {
                        case 1:
                            message.intentReceived = reader.int64();
                            break;
                        case 2:
                            message.firstFrame = reader.int64();
                            break;
                        default:
                            reader.skipType(tag & 7);
                            break;
                        }
                    }
                    return message;
                };

                /**
                 * Decodes an EventTimestamps message from the specified reader or buffer, length delimited.
                 * @function decodeDelimited
                 * @memberof perfetto.protos.AndroidStartupMetric.EventTimestamps
                 * @static
                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                 * @returns {perfetto.protos.AndroidStartupMetric.EventTimestamps} EventTimestamps
                 * @throws {Error} If the payload is not a reader or valid buffer
                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
                 */
                EventTimestamps.decodeDelimited = function decodeDelimited(reader) {
                    if (!(reader instanceof $Reader))
                        reader = new $Reader(reader);
                    return this.decode(reader, reader.uint32());
                };

                /**
                 * Verifies an EventTimestamps message.
                 * @function verify
                 * @memberof perfetto.protos.AndroidStartupMetric.EventTimestamps
                 * @static
                 * @param {Object.<string,*>} message Plain object to verify
                 * @returns {string|null} `null` if valid, otherwise the reason why it is not
                 */
                EventTimestamps.verify = function verify(message) {
                    if (typeof message !== "object" || message === null)
                        return "object expected";
                    if (message.intentReceived != null && message.hasOwnProperty("intentReceived"))
                        if (!$util.isInteger(message.intentReceived) && !(message.intentReceived && $util.isInteger(message.intentReceived.low) && $util.isInteger(message.intentReceived.high)))
                            return "intentReceived: integer|Long expected";
                    if (message.firstFrame != null && message.hasOwnProperty("firstFrame"))
                        if (!$util.isInteger(message.firstFrame) && !(message.firstFrame && $util.isInteger(message.firstFrame.low) && $util.isInteger(message.firstFrame.high)))
                            return "firstFrame: integer|Long expected";
                    return null;
                };

                /**
                 * Creates an EventTimestamps message from a plain object. Also converts values to their respective internal types.
                 * @function fromObject
                 * @memberof perfetto.protos.AndroidStartupMetric.EventTimestamps
                 * @static
                 * @param {Object.<string,*>} object Plain object
                 * @returns {perfetto.protos.AndroidStartupMetric.EventTimestamps} EventTimestamps
                 */
                EventTimestamps.fromObject = function fromObject(object) {
                    if (object instanceof $root.perfetto.protos.AndroidStartupMetric.EventTimestamps)
                        return object;
                    var message = new $root.perfetto.protos.AndroidStartupMetric.EventTimestamps();
                    if (object.intentReceived != null)
                        if ($util.Long)
                            (message.intentReceived = $util.Long.fromValue(object.intentReceived)).unsigned = false;
                        else if (typeof object.intentReceived === "string")
                            message.intentReceived = parseInt(object.intentReceived, 10);
                        else if (typeof object.intentReceived === "number")
                            message.intentReceived = object.intentReceived;
                        else if (typeof object.intentReceived === "object")
                            message.intentReceived = new $util.LongBits(object.intentReceived.low >>> 0, object.intentReceived.high >>> 0).toNumber();
                    if (object.firstFrame != null)
                        if ($util.Long)
                            (message.firstFrame = $util.Long.fromValue(object.firstFrame)).unsigned = false;
                        else if (typeof object.firstFrame === "string")
                            message.firstFrame = parseInt(object.firstFrame, 10);
                        else if (typeof object.firstFrame === "number")
                            message.firstFrame = object.firstFrame;
                        else if (typeof object.firstFrame === "object")
                            message.firstFrame = new $util.LongBits(object.firstFrame.low >>> 0, object.firstFrame.high >>> 0).toNumber();
                    return message;
                };

                /**
                 * Creates a plain object from an EventTimestamps message. Also converts values to other types if specified.
                 * @function toObject
                 * @memberof perfetto.protos.AndroidStartupMetric.EventTimestamps
                 * @static
                 * @param {perfetto.protos.AndroidStartupMetric.EventTimestamps} message EventTimestamps
                 * @param {$protobuf.IConversionOptions} [options] Conversion options
                 * @returns {Object.<string,*>} Plain object
                 */
                EventTimestamps.toObject = function toObject(message, options) {
                    if (!options)
                        options = {};
                    var object = {};
                    if (options.defaults) {
                        if ($util.Long) {
                            var long = new $util.Long(0, 0, false);
                            object.intentReceived = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
                        } else
                            object.intentReceived = options.longs === String ? "0" : 0;
                        if ($util.Long) {
                            var long = new $util.Long(0, 0, false);
                            object.firstFrame = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
                        } else
                            object.firstFrame = options.longs === String ? "0" : 0;
                    }
                    if (message.intentReceived != null && message.hasOwnProperty("intentReceived"))
                        if (typeof message.intentReceived === "number")
                            object.intentReceived = options.longs === String ? String(message.intentReceived) : message.intentReceived;
                        else
                            object.intentReceived = options.longs === String ? $util.Long.prototype.toString.call(message.intentReceived) : options.longs === Number ? new $util.LongBits(message.intentReceived.low >>> 0, message.intentReceived.high >>> 0).toNumber() : message.intentReceived;
                    if (message.firstFrame != null && message.hasOwnProperty("firstFrame"))
                        if (typeof message.firstFrame === "number")
                            object.firstFrame = options.longs === String ? String(message.firstFrame) : message.firstFrame;
                        else
                            object.firstFrame = options.longs === String ? $util.Long.prototype.toString.call(message.firstFrame) : options.longs === Number ? new $util.LongBits(message.firstFrame.low >>> 0, message.firstFrame.high >>> 0).toNumber() : message.firstFrame;
                    return object;
                };

                /**
                 * Converts this EventTimestamps to JSON.
                 * @function toJSON
                 * @memberof perfetto.protos.AndroidStartupMetric.EventTimestamps
                 * @instance
                 * @returns {Object.<string,*>} JSON object
                 */
                EventTimestamps.prototype.toJSON = function toJSON() {
                    return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
                };

                return EventTimestamps;
            })();

            AndroidStartupMetric.Startup = (function() {

                /**
                 * Properties of a Startup.
                 * @memberof perfetto.protos.AndroidStartupMetric
                 * @interface IStartup
                 * @property {number|null} [startupId] Startup startupId
                 * @property {string|null} [packageName] Startup packageName
                 * @property {string|null} [processName] Startup processName
                 * @property {Array.<perfetto.protos.AndroidStartupMetric.IActivity>|null} [activities] Startup activities
                 * @property {Array.<perfetto.protos.AndroidStartupMetric.IBinderTransaction>|null} [longBinderTransactions] Startup longBinderTransactions
                 * @property {boolean|null} [zygoteNewProcess] Startup zygoteNewProcess
                 * @property {number|null} [activityHostingProcessCount] Startup activityHostingProcessCount
                 * @property {perfetto.protos.AndroidStartupMetric.IEventTimestamps|null} [eventTimestamps] Startup eventTimestamps
                 * @property {perfetto.protos.AndroidStartupMetric.IToFirstFrame|null} [toFirstFrame] Startup toFirstFrame
                 * @property {perfetto.protos.IAndroidProcessMetadata|null} [process] Startup process
                 * @property {perfetto.protos.AndroidStartupMetric.IHscMetrics|null} [hsc] Startup hsc
                 * @property {perfetto.protos.AndroidStartupMetric.ISlice|null} [reportFullyDrawn] Startup reportFullyDrawn
                 * @property {Array.<perfetto.protos.AndroidStartupMetric.IOptimizationStatus>|null} [optimizationStatus] Startup optimizationStatus
                 */

                /**
                 * Constructs a new Startup.
                 * @memberof perfetto.protos.AndroidStartupMetric
                 * @classdesc Represents a Startup.
                 * @implements IStartup
                 * @constructor
                 * @param {perfetto.protos.AndroidStartupMetric.IStartup=} [properties] Properties to set
                 */
                function Startup(properties) {
                    this.activities = [];
                    this.longBinderTransactions = [];
                    this.optimizationStatus = [];
                    if (properties)
                        for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                            if (properties[keys[i]] != null)
                                this[keys[i]] = properties[keys[i]];
                }

                /**
                 * Startup startupId.
                 * @member {number} startupId
                 * @memberof perfetto.protos.AndroidStartupMetric.Startup
                 * @instance
                 */
                Startup.prototype.startupId = 0;

                /**
                 * Startup packageName.
                 * @member {string} packageName
                 * @memberof perfetto.protos.AndroidStartupMetric.Startup
                 * @instance
                 */
                Startup.prototype.packageName = "";

                /**
                 * Startup processName.
                 * @member {string} processName
                 * @memberof perfetto.protos.AndroidStartupMetric.Startup
                 * @instance
                 */
                Startup.prototype.processName = "";

                /**
                 * Startup activities.
                 * @member {Array.<perfetto.protos.AndroidStartupMetric.IActivity>} activities
                 * @memberof perfetto.protos.AndroidStartupMetric.Startup
                 * @instance
                 */
                Startup.prototype.activities = $util.emptyArray;

                /**
                 * Startup longBinderTransactions.
                 * @member {Array.<perfetto.protos.AndroidStartupMetric.IBinderTransaction>} longBinderTransactions
                 * @memberof perfetto.protos.AndroidStartupMetric.Startup
                 * @instance
                 */
                Startup.prototype.longBinderTransactions = $util.emptyArray;

                /**
                 * Startup zygoteNewProcess.
                 * @member {boolean} zygoteNewProcess
                 * @memberof perfetto.protos.AndroidStartupMetric.Startup
                 * @instance
                 */
                Startup.prototype.zygoteNewProcess = false;

                /**
                 * Startup activityHostingProcessCount.
                 * @member {number} activityHostingProcessCount
                 * @memberof perfetto.protos.AndroidStartupMetric.Startup
                 * @instance
                 */
                Startup.prototype.activityHostingProcessCount = 0;

                /**
                 * Startup eventTimestamps.
                 * @member {perfetto.protos.AndroidStartupMetric.IEventTimestamps|null|undefined} eventTimestamps
                 * @memberof perfetto.protos.AndroidStartupMetric.Startup
                 * @instance
                 */
                Startup.prototype.eventTimestamps = null;

                /**
                 * Startup toFirstFrame.
                 * @member {perfetto.protos.AndroidStartupMetric.IToFirstFrame|null|undefined} toFirstFrame
                 * @memberof perfetto.protos.AndroidStartupMetric.Startup
                 * @instance
                 */
                Startup.prototype.toFirstFrame = null;

                /**
                 * Startup process.
                 * @member {perfetto.protos.IAndroidProcessMetadata|null|undefined} process
                 * @memberof perfetto.protos.AndroidStartupMetric.Startup
                 * @instance
                 */
                Startup.prototype.process = null;

                /**
                 * Startup hsc.
                 * @member {perfetto.protos.AndroidStartupMetric.IHscMetrics|null|undefined} hsc
                 * @memberof perfetto.protos.AndroidStartupMetric.Startup
                 * @instance
                 */
                Startup.prototype.hsc = null;

                /**
                 * Startup reportFullyDrawn.
                 * @member {perfetto.protos.AndroidStartupMetric.ISlice|null|undefined} reportFullyDrawn
                 * @memberof perfetto.protos.AndroidStartupMetric.Startup
                 * @instance
                 */
                Startup.prototype.reportFullyDrawn = null;

                /**
                 * Startup optimizationStatus.
                 * @member {Array.<perfetto.protos.AndroidStartupMetric.IOptimizationStatus>} optimizationStatus
                 * @memberof perfetto.protos.AndroidStartupMetric.Startup
                 * @instance
                 */
                Startup.prototype.optimizationStatus = $util.emptyArray;

                /**
                 * Creates a new Startup instance using the specified properties.
                 * @function create
                 * @memberof perfetto.protos.AndroidStartupMetric.Startup
                 * @static
                 * @param {perfetto.protos.AndroidStartupMetric.IStartup=} [properties] Properties to set
                 * @returns {perfetto.protos.AndroidStartupMetric.Startup} Startup instance
                 */
                Startup.create = function create(properties) {
                    return new Startup(properties);
                };

                /**
                 * Encodes the specified Startup message. Does not implicitly {@link perfetto.protos.AndroidStartupMetric.Startup.verify|verify} messages.
                 * @function encode
                 * @memberof perfetto.protos.AndroidStartupMetric.Startup
                 * @static
                 * @param {perfetto.protos.AndroidStartupMetric.IStartup} message Startup message or plain object to encode
                 * @param {$protobuf.Writer} [writer] Writer to encode to
                 * @returns {$protobuf.Writer} Writer
                 */
                Startup.encode = function encode(message, writer) {
                    if (!writer)
                        writer = $Writer.create();
                    if (message.startupId != null && Object.hasOwnProperty.call(message, "startupId"))
                        writer.uint32(/* id 1, wireType 0 =*/8).uint32(message.startupId);
                    if (message.packageName != null && Object.hasOwnProperty.call(message, "packageName"))
                        writer.uint32(/* id 2, wireType 2 =*/18).string(message.packageName);
                    if (message.processName != null && Object.hasOwnProperty.call(message, "processName"))
                        writer.uint32(/* id 3, wireType 2 =*/26).string(message.processName);
                    if (message.zygoteNewProcess != null && Object.hasOwnProperty.call(message, "zygoteNewProcess"))
                        writer.uint32(/* id 4, wireType 0 =*/32).bool(message.zygoteNewProcess);
                    if (message.toFirstFrame != null && Object.hasOwnProperty.call(message, "toFirstFrame"))
                        $root.perfetto.protos.AndroidStartupMetric.ToFirstFrame.encode(message.toFirstFrame, writer.uint32(/* id 5, wireType 2 =*/42).fork()).ldelim();
                    if (message.activityHostingProcessCount != null && Object.hasOwnProperty.call(message, "activityHostingProcessCount"))
                        writer.uint32(/* id 6, wireType 0 =*/48).uint32(message.activityHostingProcessCount);
                    if (message.process != null && Object.hasOwnProperty.call(message, "process"))
                        $root.perfetto.protos.AndroidProcessMetadata.encode(message.process, writer.uint32(/* id 7, wireType 2 =*/58).fork()).ldelim();
                    if (message.hsc != null && Object.hasOwnProperty.call(message, "hsc"))
                        $root.perfetto.protos.AndroidStartupMetric.HscMetrics.encode(message.hsc, writer.uint32(/* id 8, wireType 2 =*/66).fork()).ldelim();
                    if (message.reportFullyDrawn != null && Object.hasOwnProperty.call(message, "reportFullyDrawn"))
                        $root.perfetto.protos.AndroidStartupMetric.Slice.encode(message.reportFullyDrawn, writer.uint32(/* id 9, wireType 2 =*/74).fork()).ldelim();
                    if (message.activities != null && message.activities.length)
                        for (var i = 0; i < message.activities.length; ++i)
                            $root.perfetto.protos.AndroidStartupMetric.Activity.encode(message.activities[i], writer.uint32(/* id 11, wireType 2 =*/90).fork()).ldelim();
                    if (message.optimizationStatus != null && message.optimizationStatus.length)
                        for (var i = 0; i < message.optimizationStatus.length; ++i)
                            $root.perfetto.protos.AndroidStartupMetric.OptimizationStatus.encode(message.optimizationStatus[i], writer.uint32(/* id 12, wireType 2 =*/98).fork()).ldelim();
                    if (message.eventTimestamps != null && Object.hasOwnProperty.call(message, "eventTimestamps"))
                        $root.perfetto.protos.AndroidStartupMetric.EventTimestamps.encode(message.eventTimestamps, writer.uint32(/* id 13, wireType 2 =*/106).fork()).ldelim();
                    if (message.longBinderTransactions != null && message.longBinderTransactions.length)
                        for (var i = 0; i < message.longBinderTransactions.length; ++i)
                            $root.perfetto.protos.AndroidStartupMetric.BinderTransaction.encode(message.longBinderTransactions[i], writer.uint32(/* id 14, wireType 2 =*/114).fork()).ldelim();
                    return writer;
                };

                /**
                 * Encodes the specified Startup message, length delimited. Does not implicitly {@link perfetto.protos.AndroidStartupMetric.Startup.verify|verify} messages.
                 * @function encodeDelimited
                 * @memberof perfetto.protos.AndroidStartupMetric.Startup
                 * @static
                 * @param {perfetto.protos.AndroidStartupMetric.IStartup} message Startup message or plain object to encode
                 * @param {$protobuf.Writer} [writer] Writer to encode to
                 * @returns {$protobuf.Writer} Writer
                 */
                Startup.encodeDelimited = function encodeDelimited(message, writer) {
                    return this.encode(message, writer).ldelim();
                };

                /**
                 * Decodes a Startup message from the specified reader or buffer.
                 * @function decode
                 * @memberof perfetto.protos.AndroidStartupMetric.Startup
                 * @static
                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                 * @param {number} [length] Message length if known beforehand
                 * @returns {perfetto.protos.AndroidStartupMetric.Startup} Startup
                 * @throws {Error} If the payload is not a reader or valid buffer
                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
                 */
                Startup.decode = function decode(reader, length) {
                    if (!(reader instanceof $Reader))
                        reader = $Reader.create(reader);
                    var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.AndroidStartupMetric.Startup();
                    while (reader.pos < end) {
                        var tag = reader.uint32();
                        switch (tag >>> 3) {
                        case 1:
                            message.startupId = reader.uint32();
                            break;
                        case 2:
                            message.packageName = reader.string();
                            break;
                        case 3:
                            message.processName = reader.string();
                            break;
                        case 11:
                            if (!(message.activities && message.activities.length))
                                message.activities = [];
                            message.activities.push($root.perfetto.protos.AndroidStartupMetric.Activity.decode(reader, reader.uint32()));
                            break;
                        case 14:
                            if (!(message.longBinderTransactions && message.longBinderTransactions.length))
                                message.longBinderTransactions = [];
                            message.longBinderTransactions.push($root.perfetto.protos.AndroidStartupMetric.BinderTransaction.decode(reader, reader.uint32()));
                            break;
                        case 4:
                            message.zygoteNewProcess = reader.bool();
                            break;
                        case 6:
                            message.activityHostingProcessCount = reader.uint32();
                            break;
                        case 13:
                            message.eventTimestamps = $root.perfetto.protos.AndroidStartupMetric.EventTimestamps.decode(reader, reader.uint32());
                            break;
                        case 5:
                            message.toFirstFrame = $root.perfetto.protos.AndroidStartupMetric.ToFirstFrame.decode(reader, reader.uint32());
                            break;
                        case 7:
                            message.process = $root.perfetto.protos.AndroidProcessMetadata.decode(reader, reader.uint32());
                            break;
                        case 8:
                            message.hsc = $root.perfetto.protos.AndroidStartupMetric.HscMetrics.decode(reader, reader.uint32());
                            break;
                        case 9:
                            message.reportFullyDrawn = $root.perfetto.protos.AndroidStartupMetric.Slice.decode(reader, reader.uint32());
                            break;
                        case 12:
                            if (!(message.optimizationStatus && message.optimizationStatus.length))
                                message.optimizationStatus = [];
                            message.optimizationStatus.push($root.perfetto.protos.AndroidStartupMetric.OptimizationStatus.decode(reader, reader.uint32()));
                            break;
                        default:
                            reader.skipType(tag & 7);
                            break;
                        }
                    }
                    return message;
                };

                /**
                 * Decodes a Startup message from the specified reader or buffer, length delimited.
                 * @function decodeDelimited
                 * @memberof perfetto.protos.AndroidStartupMetric.Startup
                 * @static
                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                 * @returns {perfetto.protos.AndroidStartupMetric.Startup} Startup
                 * @throws {Error} If the payload is not a reader or valid buffer
                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
                 */
                Startup.decodeDelimited = function decodeDelimited(reader) {
                    if (!(reader instanceof $Reader))
                        reader = new $Reader(reader);
                    return this.decode(reader, reader.uint32());
                };

                /**
                 * Verifies a Startup message.
                 * @function verify
                 * @memberof perfetto.protos.AndroidStartupMetric.Startup
                 * @static
                 * @param {Object.<string,*>} message Plain object to verify
                 * @returns {string|null} `null` if valid, otherwise the reason why it is not
                 */
                Startup.verify = function verify(message) {
                    if (typeof message !== "object" || message === null)
                        return "object expected";
                    if (message.startupId != null && message.hasOwnProperty("startupId"))
                        if (!$util.isInteger(message.startupId))
                            return "startupId: integer expected";
                    if (message.packageName != null && message.hasOwnProperty("packageName"))
                        if (!$util.isString(message.packageName))
                            return "packageName: string expected";
                    if (message.processName != null && message.hasOwnProperty("processName"))
                        if (!$util.isString(message.processName))
                            return "processName: string expected";
                    if (message.activities != null && message.hasOwnProperty("activities")) {
                        if (!Array.isArray(message.activities))
                            return "activities: array expected";
                        for (var i = 0; i < message.activities.length; ++i) {
                            var error = $root.perfetto.protos.AndroidStartupMetric.Activity.verify(message.activities[i]);
                            if (error)
                                return "activities." + error;
                        }
                    }
                    if (message.longBinderTransactions != null && message.hasOwnProperty("longBinderTransactions")) {
                        if (!Array.isArray(message.longBinderTransactions))
                            return "longBinderTransactions: array expected";
                        for (var i = 0; i < message.longBinderTransactions.length; ++i) {
                            var error = $root.perfetto.protos.AndroidStartupMetric.BinderTransaction.verify(message.longBinderTransactions[i]);
                            if (error)
                                return "longBinderTransactions." + error;
                        }
                    }
                    if (message.zygoteNewProcess != null && message.hasOwnProperty("zygoteNewProcess"))
                        if (typeof message.zygoteNewProcess !== "boolean")
                            return "zygoteNewProcess: boolean expected";
                    if (message.activityHostingProcessCount != null && message.hasOwnProperty("activityHostingProcessCount"))
                        if (!$util.isInteger(message.activityHostingProcessCount))
                            return "activityHostingProcessCount: integer expected";
                    if (message.eventTimestamps != null && message.hasOwnProperty("eventTimestamps")) {
                        var error = $root.perfetto.protos.AndroidStartupMetric.EventTimestamps.verify(message.eventTimestamps);
                        if (error)
                            return "eventTimestamps." + error;
                    }
                    if (message.toFirstFrame != null && message.hasOwnProperty("toFirstFrame")) {
                        var error = $root.perfetto.protos.AndroidStartupMetric.ToFirstFrame.verify(message.toFirstFrame);
                        if (error)
                            return "toFirstFrame." + error;
                    }
                    if (message.process != null && message.hasOwnProperty("process")) {
                        var error = $root.perfetto.protos.AndroidProcessMetadata.verify(message.process);
                        if (error)
                            return "process." + error;
                    }
                    if (message.hsc != null && message.hasOwnProperty("hsc")) {
                        var error = $root.perfetto.protos.AndroidStartupMetric.HscMetrics.verify(message.hsc);
                        if (error)
                            return "hsc." + error;
                    }
                    if (message.reportFullyDrawn != null && message.hasOwnProperty("reportFullyDrawn")) {
                        var error = $root.perfetto.protos.AndroidStartupMetric.Slice.verify(message.reportFullyDrawn);
                        if (error)
                            return "reportFullyDrawn." + error;
                    }
                    if (message.optimizationStatus != null && message.hasOwnProperty("optimizationStatus")) {
                        if (!Array.isArray(message.optimizationStatus))
                            return "optimizationStatus: array expected";
                        for (var i = 0; i < message.optimizationStatus.length; ++i) {
                            var error = $root.perfetto.protos.AndroidStartupMetric.OptimizationStatus.verify(message.optimizationStatus[i]);
                            if (error)
                                return "optimizationStatus." + error;
                        }
                    }
                    return null;
                };

                /**
                 * Creates a Startup message from a plain object. Also converts values to their respective internal types.
                 * @function fromObject
                 * @memberof perfetto.protos.AndroidStartupMetric.Startup
                 * @static
                 * @param {Object.<string,*>} object Plain object
                 * @returns {perfetto.protos.AndroidStartupMetric.Startup} Startup
                 */
                Startup.fromObject = function fromObject(object) {
                    if (object instanceof $root.perfetto.protos.AndroidStartupMetric.Startup)
                        return object;
                    var message = new $root.perfetto.protos.AndroidStartupMetric.Startup();
                    if (object.startupId != null)
                        message.startupId = object.startupId >>> 0;
                    if (object.packageName != null)
                        message.packageName = String(object.packageName);
                    if (object.processName != null)
                        message.processName = String(object.processName);
                    if (object.activities) {
                        if (!Array.isArray(object.activities))
                            throw TypeError(".perfetto.protos.AndroidStartupMetric.Startup.activities: array expected");
                        message.activities = [];
                        for (var i = 0; i < object.activities.length; ++i) {
                            if (typeof object.activities[i] !== "object")
                                throw TypeError(".perfetto.protos.AndroidStartupMetric.Startup.activities: object expected");
                            message.activities[i] = $root.perfetto.protos.AndroidStartupMetric.Activity.fromObject(object.activities[i]);
                        }
                    }
                    if (object.longBinderTransactions) {
                        if (!Array.isArray(object.longBinderTransactions))
                            throw TypeError(".perfetto.protos.AndroidStartupMetric.Startup.longBinderTransactions: array expected");
                        message.longBinderTransactions = [];
                        for (var i = 0; i < object.longBinderTransactions.length; ++i) {
                            if (typeof object.longBinderTransactions[i] !== "object")
                                throw TypeError(".perfetto.protos.AndroidStartupMetric.Startup.longBinderTransactions: object expected");
                            message.longBinderTransactions[i] = $root.perfetto.protos.AndroidStartupMetric.BinderTransaction.fromObject(object.longBinderTransactions[i]);
                        }
                    }
                    if (object.zygoteNewProcess != null)
                        message.zygoteNewProcess = Boolean(object.zygoteNewProcess);
                    if (object.activityHostingProcessCount != null)
                        message.activityHostingProcessCount = object.activityHostingProcessCount >>> 0;
                    if (object.eventTimestamps != null) {
                        if (typeof object.eventTimestamps !== "object")
                            throw TypeError(".perfetto.protos.AndroidStartupMetric.Startup.eventTimestamps: object expected");
                        message.eventTimestamps = $root.perfetto.protos.AndroidStartupMetric.EventTimestamps.fromObject(object.eventTimestamps);
                    }
                    if (object.toFirstFrame != null) {
                        if (typeof object.toFirstFrame !== "object")
                            throw TypeError(".perfetto.protos.AndroidStartupMetric.Startup.toFirstFrame: object expected");
                        message.toFirstFrame = $root.perfetto.protos.AndroidStartupMetric.ToFirstFrame.fromObject(object.toFirstFrame);
                    }
                    if (object.process != null) {
                        if (typeof object.process !== "object")
                            throw TypeError(".perfetto.protos.AndroidStartupMetric.Startup.process: object expected");
                        message.process = $root.perfetto.protos.AndroidProcessMetadata.fromObject(object.process);
                    }
                    if (object.hsc != null) {
                        if (typeof object.hsc !== "object")
                            throw TypeError(".perfetto.protos.AndroidStartupMetric.Startup.hsc: object expected");
                        message.hsc = $root.perfetto.protos.AndroidStartupMetric.HscMetrics.fromObject(object.hsc);
                    }
                    if (object.reportFullyDrawn != null) {
                        if (typeof object.reportFullyDrawn !== "object")
                            throw TypeError(".perfetto.protos.AndroidStartupMetric.Startup.reportFullyDrawn: object expected");
                        message.reportFullyDrawn = $root.perfetto.protos.AndroidStartupMetric.Slice.fromObject(object.reportFullyDrawn);
                    }
                    if (object.optimizationStatus) {
                        if (!Array.isArray(object.optimizationStatus))
                            throw TypeError(".perfetto.protos.AndroidStartupMetric.Startup.optimizationStatus: array expected");
                        message.optimizationStatus = [];
                        for (var i = 0; i < object.optimizationStatus.length; ++i) {
                            if (typeof object.optimizationStatus[i] !== "object")
                                throw TypeError(".perfetto.protos.AndroidStartupMetric.Startup.optimizationStatus: object expected");
                            message.optimizationStatus[i] = $root.perfetto.protos.AndroidStartupMetric.OptimizationStatus.fromObject(object.optimizationStatus[i]);
                        }
                    }
                    return message;
                };

                /**
                 * Creates a plain object from a Startup message. Also converts values to other types if specified.
                 * @function toObject
                 * @memberof perfetto.protos.AndroidStartupMetric.Startup
                 * @static
                 * @param {perfetto.protos.AndroidStartupMetric.Startup} message Startup
                 * @param {$protobuf.IConversionOptions} [options] Conversion options
                 * @returns {Object.<string,*>} Plain object
                 */
                Startup.toObject = function toObject(message, options) {
                    if (!options)
                        options = {};
                    var object = {};
                    if (options.arrays || options.defaults) {
                        object.activities = [];
                        object.optimizationStatus = [];
                        object.longBinderTransactions = [];
                    }
                    if (options.defaults) {
                        object.startupId = 0;
                        object.packageName = "";
                        object.processName = "";
                        object.zygoteNewProcess = false;
                        object.toFirstFrame = null;
                        object.activityHostingProcessCount = 0;
                        object.process = null;
                        object.hsc = null;
                        object.reportFullyDrawn = null;
                        object.eventTimestamps = null;
                    }
                    if (message.startupId != null && message.hasOwnProperty("startupId"))
                        object.startupId = message.startupId;
                    if (message.packageName != null && message.hasOwnProperty("packageName"))
                        object.packageName = message.packageName;
                    if (message.processName != null && message.hasOwnProperty("processName"))
                        object.processName = message.processName;
                    if (message.zygoteNewProcess != null && message.hasOwnProperty("zygoteNewProcess"))
                        object.zygoteNewProcess = message.zygoteNewProcess;
                    if (message.toFirstFrame != null && message.hasOwnProperty("toFirstFrame"))
                        object.toFirstFrame = $root.perfetto.protos.AndroidStartupMetric.ToFirstFrame.toObject(message.toFirstFrame, options);
                    if (message.activityHostingProcessCount != null && message.hasOwnProperty("activityHostingProcessCount"))
                        object.activityHostingProcessCount = message.activityHostingProcessCount;
                    if (message.process != null && message.hasOwnProperty("process"))
                        object.process = $root.perfetto.protos.AndroidProcessMetadata.toObject(message.process, options);
                    if (message.hsc != null && message.hasOwnProperty("hsc"))
                        object.hsc = $root.perfetto.protos.AndroidStartupMetric.HscMetrics.toObject(message.hsc, options);
                    if (message.reportFullyDrawn != null && message.hasOwnProperty("reportFullyDrawn"))
                        object.reportFullyDrawn = $root.perfetto.protos.AndroidStartupMetric.Slice.toObject(message.reportFullyDrawn, options);
                    if (message.activities && message.activities.length) {
                        object.activities = [];
                        for (var j = 0; j < message.activities.length; ++j)
                            object.activities[j] = $root.perfetto.protos.AndroidStartupMetric.Activity.toObject(message.activities[j], options);
                    }
                    if (message.optimizationStatus && message.optimizationStatus.length) {
                        object.optimizationStatus = [];
                        for (var j = 0; j < message.optimizationStatus.length; ++j)
                            object.optimizationStatus[j] = $root.perfetto.protos.AndroidStartupMetric.OptimizationStatus.toObject(message.optimizationStatus[j], options);
                    }
                    if (message.eventTimestamps != null && message.hasOwnProperty("eventTimestamps"))
                        object.eventTimestamps = $root.perfetto.protos.AndroidStartupMetric.EventTimestamps.toObject(message.eventTimestamps, options);
                    if (message.longBinderTransactions && message.longBinderTransactions.length) {
                        object.longBinderTransactions = [];
                        for (var j = 0; j < message.longBinderTransactions.length; ++j)
                            object.longBinderTransactions[j] = $root.perfetto.protos.AndroidStartupMetric.BinderTransaction.toObject(message.longBinderTransactions[j], options);
                    }
                    return object;
                };

                /**
                 * Converts this Startup to JSON.
                 * @function toJSON
                 * @memberof perfetto.protos.AndroidStartupMetric.Startup
                 * @instance
                 * @returns {Object.<string,*>} JSON object
                 */
                Startup.prototype.toJSON = function toJSON() {
                    return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
                };

                return Startup;
            })();

            return AndroidStartupMetric;
        })();

        protos.AndroidSurfaceflingerMetric = (function() {

            /**
             * Properties of an AndroidSurfaceflingerMetric.
             * @memberof perfetto.protos
             * @interface IAndroidSurfaceflingerMetric
             * @property {number|null} [missedFrames] AndroidSurfaceflingerMetric missedFrames
             * @property {number|null} [missedHwcFrames] AndroidSurfaceflingerMetric missedHwcFrames
             * @property {number|null} [missedGpuFrames] AndroidSurfaceflingerMetric missedGpuFrames
             * @property {number|null} [missedFrameRate] AndroidSurfaceflingerMetric missedFrameRate
             * @property {number|null} [missedHwcFrameRate] AndroidSurfaceflingerMetric missedHwcFrameRate
             * @property {number|null} [missedGpuFrameRate] AndroidSurfaceflingerMetric missedGpuFrameRate
             */

            /**
             * Constructs a new AndroidSurfaceflingerMetric.
             * @memberof perfetto.protos
             * @classdesc Represents an AndroidSurfaceflingerMetric.
             * @implements IAndroidSurfaceflingerMetric
             * @constructor
             * @param {perfetto.protos.IAndroidSurfaceflingerMetric=} [properties] Properties to set
             */
            function AndroidSurfaceflingerMetric(properties) {
                if (properties)
                    for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                        if (properties[keys[i]] != null)
                            this[keys[i]] = properties[keys[i]];
            }

            /**
             * AndroidSurfaceflingerMetric missedFrames.
             * @member {number} missedFrames
             * @memberof perfetto.protos.AndroidSurfaceflingerMetric
             * @instance
             */
            AndroidSurfaceflingerMetric.prototype.missedFrames = 0;

            /**
             * AndroidSurfaceflingerMetric missedHwcFrames.
             * @member {number} missedHwcFrames
             * @memberof perfetto.protos.AndroidSurfaceflingerMetric
             * @instance
             */
            AndroidSurfaceflingerMetric.prototype.missedHwcFrames = 0;

            /**
             * AndroidSurfaceflingerMetric missedGpuFrames.
             * @member {number} missedGpuFrames
             * @memberof perfetto.protos.AndroidSurfaceflingerMetric
             * @instance
             */
            AndroidSurfaceflingerMetric.prototype.missedGpuFrames = 0;

            /**
             * AndroidSurfaceflingerMetric missedFrameRate.
             * @member {number} missedFrameRate
             * @memberof perfetto.protos.AndroidSurfaceflingerMetric
             * @instance
             */
            AndroidSurfaceflingerMetric.prototype.missedFrameRate = 0;

            /**
             * AndroidSurfaceflingerMetric missedHwcFrameRate.
             * @member {number} missedHwcFrameRate
             * @memberof perfetto.protos.AndroidSurfaceflingerMetric
             * @instance
             */
            AndroidSurfaceflingerMetric.prototype.missedHwcFrameRate = 0;

            /**
             * AndroidSurfaceflingerMetric missedGpuFrameRate.
             * @member {number} missedGpuFrameRate
             * @memberof perfetto.protos.AndroidSurfaceflingerMetric
             * @instance
             */
            AndroidSurfaceflingerMetric.prototype.missedGpuFrameRate = 0;

            /**
             * Creates a new AndroidSurfaceflingerMetric instance using the specified properties.
             * @function create
             * @memberof perfetto.protos.AndroidSurfaceflingerMetric
             * @static
             * @param {perfetto.protos.IAndroidSurfaceflingerMetric=} [properties] Properties to set
             * @returns {perfetto.protos.AndroidSurfaceflingerMetric} AndroidSurfaceflingerMetric instance
             */
            AndroidSurfaceflingerMetric.create = function create(properties) {
                return new AndroidSurfaceflingerMetric(properties);
            };

            /**
             * Encodes the specified AndroidSurfaceflingerMetric message. Does not implicitly {@link perfetto.protos.AndroidSurfaceflingerMetric.verify|verify} messages.
             * @function encode
             * @memberof perfetto.protos.AndroidSurfaceflingerMetric
             * @static
             * @param {perfetto.protos.IAndroidSurfaceflingerMetric} message AndroidSurfaceflingerMetric message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            AndroidSurfaceflingerMetric.encode = function encode(message, writer) {
                if (!writer)
                    writer = $Writer.create();
                if (message.missedFrames != null && Object.hasOwnProperty.call(message, "missedFrames"))
                    writer.uint32(/* id 1, wireType 0 =*/8).uint32(message.missedFrames);
                if (message.missedHwcFrames != null && Object.hasOwnProperty.call(message, "missedHwcFrames"))
                    writer.uint32(/* id 2, wireType 0 =*/16).uint32(message.missedHwcFrames);
                if (message.missedGpuFrames != null && Object.hasOwnProperty.call(message, "missedGpuFrames"))
                    writer.uint32(/* id 3, wireType 0 =*/24).uint32(message.missedGpuFrames);
                if (message.missedFrameRate != null && Object.hasOwnProperty.call(message, "missedFrameRate"))
                    writer.uint32(/* id 4, wireType 1 =*/33).double(message.missedFrameRate);
                if (message.missedHwcFrameRate != null && Object.hasOwnProperty.call(message, "missedHwcFrameRate"))
                    writer.uint32(/* id 5, wireType 1 =*/41).double(message.missedHwcFrameRate);
                if (message.missedGpuFrameRate != null && Object.hasOwnProperty.call(message, "missedGpuFrameRate"))
                    writer.uint32(/* id 6, wireType 1 =*/49).double(message.missedGpuFrameRate);
                return writer;
            };

            /**
             * Encodes the specified AndroidSurfaceflingerMetric message, length delimited. Does not implicitly {@link perfetto.protos.AndroidSurfaceflingerMetric.verify|verify} messages.
             * @function encodeDelimited
             * @memberof perfetto.protos.AndroidSurfaceflingerMetric
             * @static
             * @param {perfetto.protos.IAndroidSurfaceflingerMetric} message AndroidSurfaceflingerMetric message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            AndroidSurfaceflingerMetric.encodeDelimited = function encodeDelimited(message, writer) {
                return this.encode(message, writer).ldelim();
            };

            /**
             * Decodes an AndroidSurfaceflingerMetric message from the specified reader or buffer.
             * @function decode
             * @memberof perfetto.protos.AndroidSurfaceflingerMetric
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @param {number} [length] Message length if known beforehand
             * @returns {perfetto.protos.AndroidSurfaceflingerMetric} AndroidSurfaceflingerMetric
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            AndroidSurfaceflingerMetric.decode = function decode(reader, length) {
                if (!(reader instanceof $Reader))
                    reader = $Reader.create(reader);
                var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.AndroidSurfaceflingerMetric();
                while (reader.pos < end) {
                    var tag = reader.uint32();
                    switch (tag >>> 3) {
                    case 1:
                        message.missedFrames = reader.uint32();
                        break;
                    case 2:
                        message.missedHwcFrames = reader.uint32();
                        break;
                    case 3:
                        message.missedGpuFrames = reader.uint32();
                        break;
                    case 4:
                        message.missedFrameRate = reader.double();
                        break;
                    case 5:
                        message.missedHwcFrameRate = reader.double();
                        break;
                    case 6:
                        message.missedGpuFrameRate = reader.double();
                        break;
                    default:
                        reader.skipType(tag & 7);
                        break;
                    }
                }
                return message;
            };

            /**
             * Decodes an AndroidSurfaceflingerMetric message from the specified reader or buffer, length delimited.
             * @function decodeDelimited
             * @memberof perfetto.protos.AndroidSurfaceflingerMetric
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @returns {perfetto.protos.AndroidSurfaceflingerMetric} AndroidSurfaceflingerMetric
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            AndroidSurfaceflingerMetric.decodeDelimited = function decodeDelimited(reader) {
                if (!(reader instanceof $Reader))
                    reader = new $Reader(reader);
                return this.decode(reader, reader.uint32());
            };

            /**
             * Verifies an AndroidSurfaceflingerMetric message.
             * @function verify
             * @memberof perfetto.protos.AndroidSurfaceflingerMetric
             * @static
             * @param {Object.<string,*>} message Plain object to verify
             * @returns {string|null} `null` if valid, otherwise the reason why it is not
             */
            AndroidSurfaceflingerMetric.verify = function verify(message) {
                if (typeof message !== "object" || message === null)
                    return "object expected";
                if (message.missedFrames != null && message.hasOwnProperty("missedFrames"))
                    if (!$util.isInteger(message.missedFrames))
                        return "missedFrames: integer expected";
                if (message.missedHwcFrames != null && message.hasOwnProperty("missedHwcFrames"))
                    if (!$util.isInteger(message.missedHwcFrames))
                        return "missedHwcFrames: integer expected";
                if (message.missedGpuFrames != null && message.hasOwnProperty("missedGpuFrames"))
                    if (!$util.isInteger(message.missedGpuFrames))
                        return "missedGpuFrames: integer expected";
                if (message.missedFrameRate != null && message.hasOwnProperty("missedFrameRate"))
                    if (typeof message.missedFrameRate !== "number")
                        return "missedFrameRate: number expected";
                if (message.missedHwcFrameRate != null && message.hasOwnProperty("missedHwcFrameRate"))
                    if (typeof message.missedHwcFrameRate !== "number")
                        return "missedHwcFrameRate: number expected";
                if (message.missedGpuFrameRate != null && message.hasOwnProperty("missedGpuFrameRate"))
                    if (typeof message.missedGpuFrameRate !== "number")
                        return "missedGpuFrameRate: number expected";
                return null;
            };

            /**
             * Creates an AndroidSurfaceflingerMetric message from a plain object. Also converts values to their respective internal types.
             * @function fromObject
             * @memberof perfetto.protos.AndroidSurfaceflingerMetric
             * @static
             * @param {Object.<string,*>} object Plain object
             * @returns {perfetto.protos.AndroidSurfaceflingerMetric} AndroidSurfaceflingerMetric
             */
            AndroidSurfaceflingerMetric.fromObject = function fromObject(object) {
                if (object instanceof $root.perfetto.protos.AndroidSurfaceflingerMetric)
                    return object;
                var message = new $root.perfetto.protos.AndroidSurfaceflingerMetric();
                if (object.missedFrames != null)
                    message.missedFrames = object.missedFrames >>> 0;
                if (object.missedHwcFrames != null)
                    message.missedHwcFrames = object.missedHwcFrames >>> 0;
                if (object.missedGpuFrames != null)
                    message.missedGpuFrames = object.missedGpuFrames >>> 0;
                if (object.missedFrameRate != null)
                    message.missedFrameRate = Number(object.missedFrameRate);
                if (object.missedHwcFrameRate != null)
                    message.missedHwcFrameRate = Number(object.missedHwcFrameRate);
                if (object.missedGpuFrameRate != null)
                    message.missedGpuFrameRate = Number(object.missedGpuFrameRate);
                return message;
            };

            /**
             * Creates a plain object from an AndroidSurfaceflingerMetric message. Also converts values to other types if specified.
             * @function toObject
             * @memberof perfetto.protos.AndroidSurfaceflingerMetric
             * @static
             * @param {perfetto.protos.AndroidSurfaceflingerMetric} message AndroidSurfaceflingerMetric
             * @param {$protobuf.IConversionOptions} [options] Conversion options
             * @returns {Object.<string,*>} Plain object
             */
            AndroidSurfaceflingerMetric.toObject = function toObject(message, options) {
                if (!options)
                    options = {};
                var object = {};
                if (options.defaults) {
                    object.missedFrames = 0;
                    object.missedHwcFrames = 0;
                    object.missedGpuFrames = 0;
                    object.missedFrameRate = 0;
                    object.missedHwcFrameRate = 0;
                    object.missedGpuFrameRate = 0;
                }
                if (message.missedFrames != null && message.hasOwnProperty("missedFrames"))
                    object.missedFrames = message.missedFrames;
                if (message.missedHwcFrames != null && message.hasOwnProperty("missedHwcFrames"))
                    object.missedHwcFrames = message.missedHwcFrames;
                if (message.missedGpuFrames != null && message.hasOwnProperty("missedGpuFrames"))
                    object.missedGpuFrames = message.missedGpuFrames;
                if (message.missedFrameRate != null && message.hasOwnProperty("missedFrameRate"))
                    object.missedFrameRate = options.json && !isFinite(message.missedFrameRate) ? String(message.missedFrameRate) : message.missedFrameRate;
                if (message.missedHwcFrameRate != null && message.hasOwnProperty("missedHwcFrameRate"))
                    object.missedHwcFrameRate = options.json && !isFinite(message.missedHwcFrameRate) ? String(message.missedHwcFrameRate) : message.missedHwcFrameRate;
                if (message.missedGpuFrameRate != null && message.hasOwnProperty("missedGpuFrameRate"))
                    object.missedGpuFrameRate = options.json && !isFinite(message.missedGpuFrameRate) ? String(message.missedGpuFrameRate) : message.missedGpuFrameRate;
                return object;
            };

            /**
             * Converts this AndroidSurfaceflingerMetric to JSON.
             * @function toJSON
             * @memberof perfetto.protos.AndroidSurfaceflingerMetric
             * @instance
             * @returns {Object.<string,*>} JSON object
             */
            AndroidSurfaceflingerMetric.prototype.toJSON = function toJSON() {
                return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
            };

            return AndroidSurfaceflingerMetric;
        })();

        protos.AndroidSysUiCujMetrics = (function() {

            /**
             * Properties of an AndroidSysUiCujMetrics.
             * @memberof perfetto.protos
             * @interface IAndroidSysUiCujMetrics
             * @property {Array.<perfetto.protos.AndroidSysUiCujMetrics.IFrame>|null} [frames] AndroidSysUiCujMetrics frames
             * @property {string|null} [cujName] AndroidSysUiCujMetrics cujName
             * @property {number|null} [cujStart] AndroidSysUiCujMetrics cujStart
             * @property {number|null} [cujDur] AndroidSysUiCujMetrics cujDur
             * @property {perfetto.protos.IAndroidProcessMetadata|null} [process] AndroidSysUiCujMetrics process
             */

            /**
             * Constructs a new AndroidSysUiCujMetrics.
             * @memberof perfetto.protos
             * @classdesc Represents an AndroidSysUiCujMetrics.
             * @implements IAndroidSysUiCujMetrics
             * @constructor
             * @param {perfetto.protos.IAndroidSysUiCujMetrics=} [properties] Properties to set
             */
            function AndroidSysUiCujMetrics(properties) {
                this.frames = [];
                if (properties)
                    for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                        if (properties[keys[i]] != null)
                            this[keys[i]] = properties[keys[i]];
            }

            /**
             * AndroidSysUiCujMetrics frames.
             * @member {Array.<perfetto.protos.AndroidSysUiCujMetrics.IFrame>} frames
             * @memberof perfetto.protos.AndroidSysUiCujMetrics
             * @instance
             */
            AndroidSysUiCujMetrics.prototype.frames = $util.emptyArray;

            /**
             * AndroidSysUiCujMetrics cujName.
             * @member {string} cujName
             * @memberof perfetto.protos.AndroidSysUiCujMetrics
             * @instance
             */
            AndroidSysUiCujMetrics.prototype.cujName = "";

            /**
             * AndroidSysUiCujMetrics cujStart.
             * @member {number} cujStart
             * @memberof perfetto.protos.AndroidSysUiCujMetrics
             * @instance
             */
            AndroidSysUiCujMetrics.prototype.cujStart = $util.Long ? $util.Long.fromBits(0,0,false) : 0;

            /**
             * AndroidSysUiCujMetrics cujDur.
             * @member {number} cujDur
             * @memberof perfetto.protos.AndroidSysUiCujMetrics
             * @instance
             */
            AndroidSysUiCujMetrics.prototype.cujDur = $util.Long ? $util.Long.fromBits(0,0,false) : 0;

            /**
             * AndroidSysUiCujMetrics process.
             * @member {perfetto.protos.IAndroidProcessMetadata|null|undefined} process
             * @memberof perfetto.protos.AndroidSysUiCujMetrics
             * @instance
             */
            AndroidSysUiCujMetrics.prototype.process = null;

            /**
             * Creates a new AndroidSysUiCujMetrics instance using the specified properties.
             * @function create
             * @memberof perfetto.protos.AndroidSysUiCujMetrics
             * @static
             * @param {perfetto.protos.IAndroidSysUiCujMetrics=} [properties] Properties to set
             * @returns {perfetto.protos.AndroidSysUiCujMetrics} AndroidSysUiCujMetrics instance
             */
            AndroidSysUiCujMetrics.create = function create(properties) {
                return new AndroidSysUiCujMetrics(properties);
            };

            /**
             * Encodes the specified AndroidSysUiCujMetrics message. Does not implicitly {@link perfetto.protos.AndroidSysUiCujMetrics.verify|verify} messages.
             * @function encode
             * @memberof perfetto.protos.AndroidSysUiCujMetrics
             * @static
             * @param {perfetto.protos.IAndroidSysUiCujMetrics} message AndroidSysUiCujMetrics message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            AndroidSysUiCujMetrics.encode = function encode(message, writer) {
                if (!writer)
                    writer = $Writer.create();
                if (message.frames != null && message.frames.length)
                    for (var i = 0; i < message.frames.length; ++i)
                        $root.perfetto.protos.AndroidSysUiCujMetrics.Frame.encode(message.frames[i], writer.uint32(/* id 1, wireType 2 =*/10).fork()).ldelim();
                if (message.cujName != null && Object.hasOwnProperty.call(message, "cujName"))
                    writer.uint32(/* id 2, wireType 2 =*/18).string(message.cujName);
                if (message.cujStart != null && Object.hasOwnProperty.call(message, "cujStart"))
                    writer.uint32(/* id 3, wireType 0 =*/24).int64(message.cujStart);
                if (message.cujDur != null && Object.hasOwnProperty.call(message, "cujDur"))
                    writer.uint32(/* id 4, wireType 0 =*/32).int64(message.cujDur);
                if (message.process != null && Object.hasOwnProperty.call(message, "process"))
                    $root.perfetto.protos.AndroidProcessMetadata.encode(message.process, writer.uint32(/* id 5, wireType 2 =*/42).fork()).ldelim();
                return writer;
            };

            /**
             * Encodes the specified AndroidSysUiCujMetrics message, length delimited. Does not implicitly {@link perfetto.protos.AndroidSysUiCujMetrics.verify|verify} messages.
             * @function encodeDelimited
             * @memberof perfetto.protos.AndroidSysUiCujMetrics
             * @static
             * @param {perfetto.protos.IAndroidSysUiCujMetrics} message AndroidSysUiCujMetrics message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            AndroidSysUiCujMetrics.encodeDelimited = function encodeDelimited(message, writer) {
                return this.encode(message, writer).ldelim();
            };

            /**
             * Decodes an AndroidSysUiCujMetrics message from the specified reader or buffer.
             * @function decode
             * @memberof perfetto.protos.AndroidSysUiCujMetrics
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @param {number} [length] Message length if known beforehand
             * @returns {perfetto.protos.AndroidSysUiCujMetrics} AndroidSysUiCujMetrics
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            AndroidSysUiCujMetrics.decode = function decode(reader, length) {
                if (!(reader instanceof $Reader))
                    reader = $Reader.create(reader);
                var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.AndroidSysUiCujMetrics();
                while (reader.pos < end) {
                    var tag = reader.uint32();
                    switch (tag >>> 3) {
                    case 1:
                        if (!(message.frames && message.frames.length))
                            message.frames = [];
                        message.frames.push($root.perfetto.protos.AndroidSysUiCujMetrics.Frame.decode(reader, reader.uint32()));
                        break;
                    case 2:
                        message.cujName = reader.string();
                        break;
                    case 3:
                        message.cujStart = reader.int64();
                        break;
                    case 4:
                        message.cujDur = reader.int64();
                        break;
                    case 5:
                        message.process = $root.perfetto.protos.AndroidProcessMetadata.decode(reader, reader.uint32());
                        break;
                    default:
                        reader.skipType(tag & 7);
                        break;
                    }
                }
                return message;
            };

            /**
             * Decodes an AndroidSysUiCujMetrics message from the specified reader or buffer, length delimited.
             * @function decodeDelimited
             * @memberof perfetto.protos.AndroidSysUiCujMetrics
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @returns {perfetto.protos.AndroidSysUiCujMetrics} AndroidSysUiCujMetrics
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            AndroidSysUiCujMetrics.decodeDelimited = function decodeDelimited(reader) {
                if (!(reader instanceof $Reader))
                    reader = new $Reader(reader);
                return this.decode(reader, reader.uint32());
            };

            /**
             * Verifies an AndroidSysUiCujMetrics message.
             * @function verify
             * @memberof perfetto.protos.AndroidSysUiCujMetrics
             * @static
             * @param {Object.<string,*>} message Plain object to verify
             * @returns {string|null} `null` if valid, otherwise the reason why it is not
             */
            AndroidSysUiCujMetrics.verify = function verify(message) {
                if (typeof message !== "object" || message === null)
                    return "object expected";
                if (message.frames != null && message.hasOwnProperty("frames")) {
                    if (!Array.isArray(message.frames))
                        return "frames: array expected";
                    for (var i = 0; i < message.frames.length; ++i) {
                        var error = $root.perfetto.protos.AndroidSysUiCujMetrics.Frame.verify(message.frames[i]);
                        if (error)
                            return "frames." + error;
                    }
                }
                if (message.cujName != null && message.hasOwnProperty("cujName"))
                    if (!$util.isString(message.cujName))
                        return "cujName: string expected";
                if (message.cujStart != null && message.hasOwnProperty("cujStart"))
                    if (!$util.isInteger(message.cujStart) && !(message.cujStart && $util.isInteger(message.cujStart.low) && $util.isInteger(message.cujStart.high)))
                        return "cujStart: integer|Long expected";
                if (message.cujDur != null && message.hasOwnProperty("cujDur"))
                    if (!$util.isInteger(message.cujDur) && !(message.cujDur && $util.isInteger(message.cujDur.low) && $util.isInteger(message.cujDur.high)))
                        return "cujDur: integer|Long expected";
                if (message.process != null && message.hasOwnProperty("process")) {
                    var error = $root.perfetto.protos.AndroidProcessMetadata.verify(message.process);
                    if (error)
                        return "process." + error;
                }
                return null;
            };

            /**
             * Creates an AndroidSysUiCujMetrics message from a plain object. Also converts values to their respective internal types.
             * @function fromObject
             * @memberof perfetto.protos.AndroidSysUiCujMetrics
             * @static
             * @param {Object.<string,*>} object Plain object
             * @returns {perfetto.protos.AndroidSysUiCujMetrics} AndroidSysUiCujMetrics
             */
            AndroidSysUiCujMetrics.fromObject = function fromObject(object) {
                if (object instanceof $root.perfetto.protos.AndroidSysUiCujMetrics)
                    return object;
                var message = new $root.perfetto.protos.AndroidSysUiCujMetrics();
                if (object.frames) {
                    if (!Array.isArray(object.frames))
                        throw TypeError(".perfetto.protos.AndroidSysUiCujMetrics.frames: array expected");
                    message.frames = [];
                    for (var i = 0; i < object.frames.length; ++i) {
                        if (typeof object.frames[i] !== "object")
                            throw TypeError(".perfetto.protos.AndroidSysUiCujMetrics.frames: object expected");
                        message.frames[i] = $root.perfetto.protos.AndroidSysUiCujMetrics.Frame.fromObject(object.frames[i]);
                    }
                }
                if (object.cujName != null)
                    message.cujName = String(object.cujName);
                if (object.cujStart != null)
                    if ($util.Long)
                        (message.cujStart = $util.Long.fromValue(object.cujStart)).unsigned = false;
                    else if (typeof object.cujStart === "string")
                        message.cujStart = parseInt(object.cujStart, 10);
                    else if (typeof object.cujStart === "number")
                        message.cujStart = object.cujStart;
                    else if (typeof object.cujStart === "object")
                        message.cujStart = new $util.LongBits(object.cujStart.low >>> 0, object.cujStart.high >>> 0).toNumber();
                if (object.cujDur != null)
                    if ($util.Long)
                        (message.cujDur = $util.Long.fromValue(object.cujDur)).unsigned = false;
                    else if (typeof object.cujDur === "string")
                        message.cujDur = parseInt(object.cujDur, 10);
                    else if (typeof object.cujDur === "number")
                        message.cujDur = object.cujDur;
                    else if (typeof object.cujDur === "object")
                        message.cujDur = new $util.LongBits(object.cujDur.low >>> 0, object.cujDur.high >>> 0).toNumber();
                if (object.process != null) {
                    if (typeof object.process !== "object")
                        throw TypeError(".perfetto.protos.AndroidSysUiCujMetrics.process: object expected");
                    message.process = $root.perfetto.protos.AndroidProcessMetadata.fromObject(object.process);
                }
                return message;
            };

            /**
             * Creates a plain object from an AndroidSysUiCujMetrics message. Also converts values to other types if specified.
             * @function toObject
             * @memberof perfetto.protos.AndroidSysUiCujMetrics
             * @static
             * @param {perfetto.protos.AndroidSysUiCujMetrics} message AndroidSysUiCujMetrics
             * @param {$protobuf.IConversionOptions} [options] Conversion options
             * @returns {Object.<string,*>} Plain object
             */
            AndroidSysUiCujMetrics.toObject = function toObject(message, options) {
                if (!options)
                    options = {};
                var object = {};
                if (options.arrays || options.defaults)
                    object.frames = [];
                if (options.defaults) {
                    object.cujName = "";
                    if ($util.Long) {
                        var long = new $util.Long(0, 0, false);
                        object.cujStart = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
                    } else
                        object.cujStart = options.longs === String ? "0" : 0;
                    if ($util.Long) {
                        var long = new $util.Long(0, 0, false);
                        object.cujDur = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
                    } else
                        object.cujDur = options.longs === String ? "0" : 0;
                    object.process = null;
                }
                if (message.frames && message.frames.length) {
                    object.frames = [];
                    for (var j = 0; j < message.frames.length; ++j)
                        object.frames[j] = $root.perfetto.protos.AndroidSysUiCujMetrics.Frame.toObject(message.frames[j], options);
                }
                if (message.cujName != null && message.hasOwnProperty("cujName"))
                    object.cujName = message.cujName;
                if (message.cujStart != null && message.hasOwnProperty("cujStart"))
                    if (typeof message.cujStart === "number")
                        object.cujStart = options.longs === String ? String(message.cujStart) : message.cujStart;
                    else
                        object.cujStart = options.longs === String ? $util.Long.prototype.toString.call(message.cujStart) : options.longs === Number ? new $util.LongBits(message.cujStart.low >>> 0, message.cujStart.high >>> 0).toNumber() : message.cujStart;
                if (message.cujDur != null && message.hasOwnProperty("cujDur"))
                    if (typeof message.cujDur === "number")
                        object.cujDur = options.longs === String ? String(message.cujDur) : message.cujDur;
                    else
                        object.cujDur = options.longs === String ? $util.Long.prototype.toString.call(message.cujDur) : options.longs === Number ? new $util.LongBits(message.cujDur.low >>> 0, message.cujDur.high >>> 0).toNumber() : message.cujDur;
                if (message.process != null && message.hasOwnProperty("process"))
                    object.process = $root.perfetto.protos.AndroidProcessMetadata.toObject(message.process, options);
                return object;
            };

            /**
             * Converts this AndroidSysUiCujMetrics to JSON.
             * @function toJSON
             * @memberof perfetto.protos.AndroidSysUiCujMetrics
             * @instance
             * @returns {Object.<string,*>} JSON object
             */
            AndroidSysUiCujMetrics.prototype.toJSON = function toJSON() {
                return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
            };

            AndroidSysUiCujMetrics.Frame = (function() {

                /**
                 * Properties of a Frame.
                 * @memberof perfetto.protos.AndroidSysUiCujMetrics
                 * @interface IFrame
                 * @property {number|null} [number] Frame number
                 * @property {number|null} [vsync] Frame vsync
                 * @property {number|null} [ts] Frame ts
                 * @property {number|null} [dur] Frame dur
                 * @property {Array.<string>|null} [jankCause] Frame jankCause
                 */

                /**
                 * Constructs a new Frame.
                 * @memberof perfetto.protos.AndroidSysUiCujMetrics
                 * @classdesc Represents a Frame.
                 * @implements IFrame
                 * @constructor
                 * @param {perfetto.protos.AndroidSysUiCujMetrics.IFrame=} [properties] Properties to set
                 */
                function Frame(properties) {
                    this.jankCause = [];
                    if (properties)
                        for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                            if (properties[keys[i]] != null)
                                this[keys[i]] = properties[keys[i]];
                }

                /**
                 * Frame number.
                 * @member {number} number
                 * @memberof perfetto.protos.AndroidSysUiCujMetrics.Frame
                 * @instance
                 */
                Frame.prototype.number = $util.Long ? $util.Long.fromBits(0,0,false) : 0;

                /**
                 * Frame vsync.
                 * @member {number} vsync
                 * @memberof perfetto.protos.AndroidSysUiCujMetrics.Frame
                 * @instance
                 */
                Frame.prototype.vsync = $util.Long ? $util.Long.fromBits(0,0,false) : 0;

                /**
                 * Frame ts.
                 * @member {number} ts
                 * @memberof perfetto.protos.AndroidSysUiCujMetrics.Frame
                 * @instance
                 */
                Frame.prototype.ts = $util.Long ? $util.Long.fromBits(0,0,false) : 0;

                /**
                 * Frame dur.
                 * @member {number} dur
                 * @memberof perfetto.protos.AndroidSysUiCujMetrics.Frame
                 * @instance
                 */
                Frame.prototype.dur = $util.Long ? $util.Long.fromBits(0,0,false) : 0;

                /**
                 * Frame jankCause.
                 * @member {Array.<string>} jankCause
                 * @memberof perfetto.protos.AndroidSysUiCujMetrics.Frame
                 * @instance
                 */
                Frame.prototype.jankCause = $util.emptyArray;

                /**
                 * Creates a new Frame instance using the specified properties.
                 * @function create
                 * @memberof perfetto.protos.AndroidSysUiCujMetrics.Frame
                 * @static
                 * @param {perfetto.protos.AndroidSysUiCujMetrics.IFrame=} [properties] Properties to set
                 * @returns {perfetto.protos.AndroidSysUiCujMetrics.Frame} Frame instance
                 */
                Frame.create = function create(properties) {
                    return new Frame(properties);
                };

                /**
                 * Encodes the specified Frame message. Does not implicitly {@link perfetto.protos.AndroidSysUiCujMetrics.Frame.verify|verify} messages.
                 * @function encode
                 * @memberof perfetto.protos.AndroidSysUiCujMetrics.Frame
                 * @static
                 * @param {perfetto.protos.AndroidSysUiCujMetrics.IFrame} message Frame message or plain object to encode
                 * @param {$protobuf.Writer} [writer] Writer to encode to
                 * @returns {$protobuf.Writer} Writer
                 */
                Frame.encode = function encode(message, writer) {
                    if (!writer)
                        writer = $Writer.create();
                    if (message.number != null && Object.hasOwnProperty.call(message, "number"))
                        writer.uint32(/* id 1, wireType 0 =*/8).int64(message.number);
                    if (message.ts != null && Object.hasOwnProperty.call(message, "ts"))
                        writer.uint32(/* id 2, wireType 0 =*/16).int64(message.ts);
                    if (message.dur != null && Object.hasOwnProperty.call(message, "dur"))
                        writer.uint32(/* id 3, wireType 0 =*/24).int64(message.dur);
                    if (message.jankCause != null && message.jankCause.length)
                        for (var i = 0; i < message.jankCause.length; ++i)
                            writer.uint32(/* id 4, wireType 2 =*/34).string(message.jankCause[i]);
                    if (message.vsync != null && Object.hasOwnProperty.call(message, "vsync"))
                        writer.uint32(/* id 5, wireType 0 =*/40).int64(message.vsync);
                    return writer;
                };

                /**
                 * Encodes the specified Frame message, length delimited. Does not implicitly {@link perfetto.protos.AndroidSysUiCujMetrics.Frame.verify|verify} messages.
                 * @function encodeDelimited
                 * @memberof perfetto.protos.AndroidSysUiCujMetrics.Frame
                 * @static
                 * @param {perfetto.protos.AndroidSysUiCujMetrics.IFrame} message Frame message or plain object to encode
                 * @param {$protobuf.Writer} [writer] Writer to encode to
                 * @returns {$protobuf.Writer} Writer
                 */
                Frame.encodeDelimited = function encodeDelimited(message, writer) {
                    return this.encode(message, writer).ldelim();
                };

                /**
                 * Decodes a Frame message from the specified reader or buffer.
                 * @function decode
                 * @memberof perfetto.protos.AndroidSysUiCujMetrics.Frame
                 * @static
                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                 * @param {number} [length] Message length if known beforehand
                 * @returns {perfetto.protos.AndroidSysUiCujMetrics.Frame} Frame
                 * @throws {Error} If the payload is not a reader or valid buffer
                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
                 */
                Frame.decode = function decode(reader, length) {
                    if (!(reader instanceof $Reader))
                        reader = $Reader.create(reader);
                    var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.AndroidSysUiCujMetrics.Frame();
                    while (reader.pos < end) {
                        var tag = reader.uint32();
                        switch (tag >>> 3) {
                        case 1:
                            message.number = reader.int64();
                            break;
                        case 5:
                            message.vsync = reader.int64();
                            break;
                        case 2:
                            message.ts = reader.int64();
                            break;
                        case 3:
                            message.dur = reader.int64();
                            break;
                        case 4:
                            if (!(message.jankCause && message.jankCause.length))
                                message.jankCause = [];
                            message.jankCause.push(reader.string());
                            break;
                        default:
                            reader.skipType(tag & 7);
                            break;
                        }
                    }
                    return message;
                };

                /**
                 * Decodes a Frame message from the specified reader or buffer, length delimited.
                 * @function decodeDelimited
                 * @memberof perfetto.protos.AndroidSysUiCujMetrics.Frame
                 * @static
                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                 * @returns {perfetto.protos.AndroidSysUiCujMetrics.Frame} Frame
                 * @throws {Error} If the payload is not a reader or valid buffer
                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
                 */
                Frame.decodeDelimited = function decodeDelimited(reader) {
                    if (!(reader instanceof $Reader))
                        reader = new $Reader(reader);
                    return this.decode(reader, reader.uint32());
                };

                /**
                 * Verifies a Frame message.
                 * @function verify
                 * @memberof perfetto.protos.AndroidSysUiCujMetrics.Frame
                 * @static
                 * @param {Object.<string,*>} message Plain object to verify
                 * @returns {string|null} `null` if valid, otherwise the reason why it is not
                 */
                Frame.verify = function verify(message) {
                    if (typeof message !== "object" || message === null)
                        return "object expected";
                    if (message.number != null && message.hasOwnProperty("number"))
                        if (!$util.isInteger(message.number) && !(message.number && $util.isInteger(message.number.low) && $util.isInteger(message.number.high)))
                            return "number: integer|Long expected";
                    if (message.vsync != null && message.hasOwnProperty("vsync"))
                        if (!$util.isInteger(message.vsync) && !(message.vsync && $util.isInteger(message.vsync.low) && $util.isInteger(message.vsync.high)))
                            return "vsync: integer|Long expected";
                    if (message.ts != null && message.hasOwnProperty("ts"))
                        if (!$util.isInteger(message.ts) && !(message.ts && $util.isInteger(message.ts.low) && $util.isInteger(message.ts.high)))
                            return "ts: integer|Long expected";
                    if (message.dur != null && message.hasOwnProperty("dur"))
                        if (!$util.isInteger(message.dur) && !(message.dur && $util.isInteger(message.dur.low) && $util.isInteger(message.dur.high)))
                            return "dur: integer|Long expected";
                    if (message.jankCause != null && message.hasOwnProperty("jankCause")) {
                        if (!Array.isArray(message.jankCause))
                            return "jankCause: array expected";
                        for (var i = 0; i < message.jankCause.length; ++i)
                            if (!$util.isString(message.jankCause[i]))
                                return "jankCause: string[] expected";
                    }
                    return null;
                };

                /**
                 * Creates a Frame message from a plain object. Also converts values to their respective internal types.
                 * @function fromObject
                 * @memberof perfetto.protos.AndroidSysUiCujMetrics.Frame
                 * @static
                 * @param {Object.<string,*>} object Plain object
                 * @returns {perfetto.protos.AndroidSysUiCujMetrics.Frame} Frame
                 */
                Frame.fromObject = function fromObject(object) {
                    if (object instanceof $root.perfetto.protos.AndroidSysUiCujMetrics.Frame)
                        return object;
                    var message = new $root.perfetto.protos.AndroidSysUiCujMetrics.Frame();
                    if (object.number != null)
                        if ($util.Long)
                            (message.number = $util.Long.fromValue(object.number)).unsigned = false;
                        else if (typeof object.number === "string")
                            message.number = parseInt(object.number, 10);
                        else if (typeof object.number === "number")
                            message.number = object.number;
                        else if (typeof object.number === "object")
                            message.number = new $util.LongBits(object.number.low >>> 0, object.number.high >>> 0).toNumber();
                    if (object.vsync != null)
                        if ($util.Long)
                            (message.vsync = $util.Long.fromValue(object.vsync)).unsigned = false;
                        else if (typeof object.vsync === "string")
                            message.vsync = parseInt(object.vsync, 10);
                        else if (typeof object.vsync === "number")
                            message.vsync = object.vsync;
                        else if (typeof object.vsync === "object")
                            message.vsync = new $util.LongBits(object.vsync.low >>> 0, object.vsync.high >>> 0).toNumber();
                    if (object.ts != null)
                        if ($util.Long)
                            (message.ts = $util.Long.fromValue(object.ts)).unsigned = false;
                        else if (typeof object.ts === "string")
                            message.ts = parseInt(object.ts, 10);
                        else if (typeof object.ts === "number")
                            message.ts = object.ts;
                        else if (typeof object.ts === "object")
                            message.ts = new $util.LongBits(object.ts.low >>> 0, object.ts.high >>> 0).toNumber();
                    if (object.dur != null)
                        if ($util.Long)
                            (message.dur = $util.Long.fromValue(object.dur)).unsigned = false;
                        else if (typeof object.dur === "string")
                            message.dur = parseInt(object.dur, 10);
                        else if (typeof object.dur === "number")
                            message.dur = object.dur;
                        else if (typeof object.dur === "object")
                            message.dur = new $util.LongBits(object.dur.low >>> 0, object.dur.high >>> 0).toNumber();
                    if (object.jankCause) {
                        if (!Array.isArray(object.jankCause))
                            throw TypeError(".perfetto.protos.AndroidSysUiCujMetrics.Frame.jankCause: array expected");
                        message.jankCause = [];
                        for (var i = 0; i < object.jankCause.length; ++i)
                            message.jankCause[i] = String(object.jankCause[i]);
                    }
                    return message;
                };

                /**
                 * Creates a plain object from a Frame message. Also converts values to other types if specified.
                 * @function toObject
                 * @memberof perfetto.protos.AndroidSysUiCujMetrics.Frame
                 * @static
                 * @param {perfetto.protos.AndroidSysUiCujMetrics.Frame} message Frame
                 * @param {$protobuf.IConversionOptions} [options] Conversion options
                 * @returns {Object.<string,*>} Plain object
                 */
                Frame.toObject = function toObject(message, options) {
                    if (!options)
                        options = {};
                    var object = {};
                    if (options.arrays || options.defaults)
                        object.jankCause = [];
                    if (options.defaults) {
                        if ($util.Long) {
                            var long = new $util.Long(0, 0, false);
                            object.number = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
                        } else
                            object.number = options.longs === String ? "0" : 0;
                        if ($util.Long) {
                            var long = new $util.Long(0, 0, false);
                            object.ts = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
                        } else
                            object.ts = options.longs === String ? "0" : 0;
                        if ($util.Long) {
                            var long = new $util.Long(0, 0, false);
                            object.dur = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
                        } else
                            object.dur = options.longs === String ? "0" : 0;
                        if ($util.Long) {
                            var long = new $util.Long(0, 0, false);
                            object.vsync = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
                        } else
                            object.vsync = options.longs === String ? "0" : 0;
                    }
                    if (message.number != null && message.hasOwnProperty("number"))
                        if (typeof message.number === "number")
                            object.number = options.longs === String ? String(message.number) : message.number;
                        else
                            object.number = options.longs === String ? $util.Long.prototype.toString.call(message.number) : options.longs === Number ? new $util.LongBits(message.number.low >>> 0, message.number.high >>> 0).toNumber() : message.number;
                    if (message.ts != null && message.hasOwnProperty("ts"))
                        if (typeof message.ts === "number")
                            object.ts = options.longs === String ? String(message.ts) : message.ts;
                        else
                            object.ts = options.longs === String ? $util.Long.prototype.toString.call(message.ts) : options.longs === Number ? new $util.LongBits(message.ts.low >>> 0, message.ts.high >>> 0).toNumber() : message.ts;
                    if (message.dur != null && message.hasOwnProperty("dur"))
                        if (typeof message.dur === "number")
                            object.dur = options.longs === String ? String(message.dur) : message.dur;
                        else
                            object.dur = options.longs === String ? $util.Long.prototype.toString.call(message.dur) : options.longs === Number ? new $util.LongBits(message.dur.low >>> 0, message.dur.high >>> 0).toNumber() : message.dur;
                    if (message.jankCause && message.jankCause.length) {
                        object.jankCause = [];
                        for (var j = 0; j < message.jankCause.length; ++j)
                            object.jankCause[j] = message.jankCause[j];
                    }
                    if (message.vsync != null && message.hasOwnProperty("vsync"))
                        if (typeof message.vsync === "number")
                            object.vsync = options.longs === String ? String(message.vsync) : message.vsync;
                        else
                            object.vsync = options.longs === String ? $util.Long.prototype.toString.call(message.vsync) : options.longs === Number ? new $util.LongBits(message.vsync.low >>> 0, message.vsync.high >>> 0).toNumber() : message.vsync;
                    return object;
                };

                /**
                 * Converts this Frame to JSON.
                 * @function toJSON
                 * @memberof perfetto.protos.AndroidSysUiCujMetrics.Frame
                 * @instance
                 * @returns {Object.<string,*>} JSON object
                 */
                Frame.prototype.toJSON = function toJSON() {
                    return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
                };

                return Frame;
            })();

            return AndroidSysUiCujMetrics;
        })();

        protos.AndroidTaskNames = (function() {

            /**
             * Properties of an AndroidTaskNames.
             * @memberof perfetto.protos
             * @interface IAndroidTaskNames
             * @property {Array.<perfetto.protos.AndroidTaskNames.IProcess>|null} [process] AndroidTaskNames process
             */

            /**
             * Constructs a new AndroidTaskNames.
             * @memberof perfetto.protos
             * @classdesc Represents an AndroidTaskNames.
             * @implements IAndroidTaskNames
             * @constructor
             * @param {perfetto.protos.IAndroidTaskNames=} [properties] Properties to set
             */
            function AndroidTaskNames(properties) {
                this.process = [];
                if (properties)
                    for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                        if (properties[keys[i]] != null)
                            this[keys[i]] = properties[keys[i]];
            }

            /**
             * AndroidTaskNames process.
             * @member {Array.<perfetto.protos.AndroidTaskNames.IProcess>} process
             * @memberof perfetto.protos.AndroidTaskNames
             * @instance
             */
            AndroidTaskNames.prototype.process = $util.emptyArray;

            /**
             * Creates a new AndroidTaskNames instance using the specified properties.
             * @function create
             * @memberof perfetto.protos.AndroidTaskNames
             * @static
             * @param {perfetto.protos.IAndroidTaskNames=} [properties] Properties to set
             * @returns {perfetto.protos.AndroidTaskNames} AndroidTaskNames instance
             */
            AndroidTaskNames.create = function create(properties) {
                return new AndroidTaskNames(properties);
            };

            /**
             * Encodes the specified AndroidTaskNames message. Does not implicitly {@link perfetto.protos.AndroidTaskNames.verify|verify} messages.
             * @function encode
             * @memberof perfetto.protos.AndroidTaskNames
             * @static
             * @param {perfetto.protos.IAndroidTaskNames} message AndroidTaskNames message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            AndroidTaskNames.encode = function encode(message, writer) {
                if (!writer)
                    writer = $Writer.create();
                if (message.process != null && message.process.length)
                    for (var i = 0; i < message.process.length; ++i)
                        $root.perfetto.protos.AndroidTaskNames.Process.encode(message.process[i], writer.uint32(/* id 1, wireType 2 =*/10).fork()).ldelim();
                return writer;
            };

            /**
             * Encodes the specified AndroidTaskNames message, length delimited. Does not implicitly {@link perfetto.protos.AndroidTaskNames.verify|verify} messages.
             * @function encodeDelimited
             * @memberof perfetto.protos.AndroidTaskNames
             * @static
             * @param {perfetto.protos.IAndroidTaskNames} message AndroidTaskNames message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            AndroidTaskNames.encodeDelimited = function encodeDelimited(message, writer) {
                return this.encode(message, writer).ldelim();
            };

            /**
             * Decodes an AndroidTaskNames message from the specified reader or buffer.
             * @function decode
             * @memberof perfetto.protos.AndroidTaskNames
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @param {number} [length] Message length if known beforehand
             * @returns {perfetto.protos.AndroidTaskNames} AndroidTaskNames
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            AndroidTaskNames.decode = function decode(reader, length) {
                if (!(reader instanceof $Reader))
                    reader = $Reader.create(reader);
                var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.AndroidTaskNames();
                while (reader.pos < end) {
                    var tag = reader.uint32();
                    switch (tag >>> 3) {
                    case 1:
                        if (!(message.process && message.process.length))
                            message.process = [];
                        message.process.push($root.perfetto.protos.AndroidTaskNames.Process.decode(reader, reader.uint32()));
                        break;
                    default:
                        reader.skipType(tag & 7);
                        break;
                    }
                }
                return message;
            };

            /**
             * Decodes an AndroidTaskNames message from the specified reader or buffer, length delimited.
             * @function decodeDelimited
             * @memberof perfetto.protos.AndroidTaskNames
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @returns {perfetto.protos.AndroidTaskNames} AndroidTaskNames
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            AndroidTaskNames.decodeDelimited = function decodeDelimited(reader) {
                if (!(reader instanceof $Reader))
                    reader = new $Reader(reader);
                return this.decode(reader, reader.uint32());
            };

            /**
             * Verifies an AndroidTaskNames message.
             * @function verify
             * @memberof perfetto.protos.AndroidTaskNames
             * @static
             * @param {Object.<string,*>} message Plain object to verify
             * @returns {string|null} `null` if valid, otherwise the reason why it is not
             */
            AndroidTaskNames.verify = function verify(message) {
                if (typeof message !== "object" || message === null)
                    return "object expected";
                if (message.process != null && message.hasOwnProperty("process")) {
                    if (!Array.isArray(message.process))
                        return "process: array expected";
                    for (var i = 0; i < message.process.length; ++i) {
                        var error = $root.perfetto.protos.AndroidTaskNames.Process.verify(message.process[i]);
                        if (error)
                            return "process." + error;
                    }
                }
                return null;
            };

            /**
             * Creates an AndroidTaskNames message from a plain object. Also converts values to their respective internal types.
             * @function fromObject
             * @memberof perfetto.protos.AndroidTaskNames
             * @static
             * @param {Object.<string,*>} object Plain object
             * @returns {perfetto.protos.AndroidTaskNames} AndroidTaskNames
             */
            AndroidTaskNames.fromObject = function fromObject(object) {
                if (object instanceof $root.perfetto.protos.AndroidTaskNames)
                    return object;
                var message = new $root.perfetto.protos.AndroidTaskNames();
                if (object.process) {
                    if (!Array.isArray(object.process))
                        throw TypeError(".perfetto.protos.AndroidTaskNames.process: array expected");
                    message.process = [];
                    for (var i = 0; i < object.process.length; ++i) {
                        if (typeof object.process[i] !== "object")
                            throw TypeError(".perfetto.protos.AndroidTaskNames.process: object expected");
                        message.process[i] = $root.perfetto.protos.AndroidTaskNames.Process.fromObject(object.process[i]);
                    }
                }
                return message;
            };

            /**
             * Creates a plain object from an AndroidTaskNames message. Also converts values to other types if specified.
             * @function toObject
             * @memberof perfetto.protos.AndroidTaskNames
             * @static
             * @param {perfetto.protos.AndroidTaskNames} message AndroidTaskNames
             * @param {$protobuf.IConversionOptions} [options] Conversion options
             * @returns {Object.<string,*>} Plain object
             */
            AndroidTaskNames.toObject = function toObject(message, options) {
                if (!options)
                    options = {};
                var object = {};
                if (options.arrays || options.defaults)
                    object.process = [];
                if (message.process && message.process.length) {
                    object.process = [];
                    for (var j = 0; j < message.process.length; ++j)
                        object.process[j] = $root.perfetto.protos.AndroidTaskNames.Process.toObject(message.process[j], options);
                }
                return object;
            };

            /**
             * Converts this AndroidTaskNames to JSON.
             * @function toJSON
             * @memberof perfetto.protos.AndroidTaskNames
             * @instance
             * @returns {Object.<string,*>} JSON object
             */
            AndroidTaskNames.prototype.toJSON = function toJSON() {
                return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
            };

            AndroidTaskNames.Process = (function() {

                /**
                 * Properties of a Process.
                 * @memberof perfetto.protos.AndroidTaskNames
                 * @interface IProcess
                 * @property {number|null} [pid] Process pid
                 * @property {string|null} [processName] Process processName
                 * @property {Array.<string>|null} [threadName] Process threadName
                 * @property {number|null} [uid] Process uid
                 * @property {Array.<string>|null} [uidPackageName] Process uidPackageName
                 */

                /**
                 * Constructs a new Process.
                 * @memberof perfetto.protos.AndroidTaskNames
                 * @classdesc Represents a Process.
                 * @implements IProcess
                 * @constructor
                 * @param {perfetto.protos.AndroidTaskNames.IProcess=} [properties] Properties to set
                 */
                function Process(properties) {
                    this.threadName = [];
                    this.uidPackageName = [];
                    if (properties)
                        for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                            if (properties[keys[i]] != null)
                                this[keys[i]] = properties[keys[i]];
                }

                /**
                 * Process pid.
                 * @member {number} pid
                 * @memberof perfetto.protos.AndroidTaskNames.Process
                 * @instance
                 */
                Process.prototype.pid = $util.Long ? $util.Long.fromBits(0,0,false) : 0;

                /**
                 * Process processName.
                 * @member {string} processName
                 * @memberof perfetto.protos.AndroidTaskNames.Process
                 * @instance
                 */
                Process.prototype.processName = "";

                /**
                 * Process threadName.
                 * @member {Array.<string>} threadName
                 * @memberof perfetto.protos.AndroidTaskNames.Process
                 * @instance
                 */
                Process.prototype.threadName = $util.emptyArray;

                /**
                 * Process uid.
                 * @member {number} uid
                 * @memberof perfetto.protos.AndroidTaskNames.Process
                 * @instance
                 */
                Process.prototype.uid = $util.Long ? $util.Long.fromBits(0,0,false) : 0;

                /**
                 * Process uidPackageName.
                 * @member {Array.<string>} uidPackageName
                 * @memberof perfetto.protos.AndroidTaskNames.Process
                 * @instance
                 */
                Process.prototype.uidPackageName = $util.emptyArray;

                /**
                 * Creates a new Process instance using the specified properties.
                 * @function create
                 * @memberof perfetto.protos.AndroidTaskNames.Process
                 * @static
                 * @param {perfetto.protos.AndroidTaskNames.IProcess=} [properties] Properties to set
                 * @returns {perfetto.protos.AndroidTaskNames.Process} Process instance
                 */
                Process.create = function create(properties) {
                    return new Process(properties);
                };

                /**
                 * Encodes the specified Process message. Does not implicitly {@link perfetto.protos.AndroidTaskNames.Process.verify|verify} messages.
                 * @function encode
                 * @memberof perfetto.protos.AndroidTaskNames.Process
                 * @static
                 * @param {perfetto.protos.AndroidTaskNames.IProcess} message Process message or plain object to encode
                 * @param {$protobuf.Writer} [writer] Writer to encode to
                 * @returns {$protobuf.Writer} Writer
                 */
                Process.encode = function encode(message, writer) {
                    if (!writer)
                        writer = $Writer.create();
                    if (message.pid != null && Object.hasOwnProperty.call(message, "pid"))
                        writer.uint32(/* id 1, wireType 0 =*/8).int64(message.pid);
                    if (message.processName != null && Object.hasOwnProperty.call(message, "processName"))
                        writer.uint32(/* id 2, wireType 2 =*/18).string(message.processName);
                    if (message.threadName != null && message.threadName.length)
                        for (var i = 0; i < message.threadName.length; ++i)
                            writer.uint32(/* id 3, wireType 2 =*/26).string(message.threadName[i]);
                    if (message.uid != null && Object.hasOwnProperty.call(message, "uid"))
                        writer.uint32(/* id 4, wireType 0 =*/32).int64(message.uid);
                    if (message.uidPackageName != null && message.uidPackageName.length)
                        for (var i = 0; i < message.uidPackageName.length; ++i)
                            writer.uint32(/* id 5, wireType 2 =*/42).string(message.uidPackageName[i]);
                    return writer;
                };

                /**
                 * Encodes the specified Process message, length delimited. Does not implicitly {@link perfetto.protos.AndroidTaskNames.Process.verify|verify} messages.
                 * @function encodeDelimited
                 * @memberof perfetto.protos.AndroidTaskNames.Process
                 * @static
                 * @param {perfetto.protos.AndroidTaskNames.IProcess} message Process message or plain object to encode
                 * @param {$protobuf.Writer} [writer] Writer to encode to
                 * @returns {$protobuf.Writer} Writer
                 */
                Process.encodeDelimited = function encodeDelimited(message, writer) {
                    return this.encode(message, writer).ldelim();
                };

                /**
                 * Decodes a Process message from the specified reader or buffer.
                 * @function decode
                 * @memberof perfetto.protos.AndroidTaskNames.Process
                 * @static
                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                 * @param {number} [length] Message length if known beforehand
                 * @returns {perfetto.protos.AndroidTaskNames.Process} Process
                 * @throws {Error} If the payload is not a reader or valid buffer
                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
                 */
                Process.decode = function decode(reader, length) {
                    if (!(reader instanceof $Reader))
                        reader = $Reader.create(reader);
                    var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.AndroidTaskNames.Process();
                    while (reader.pos < end) {
                        var tag = reader.uint32();
                        switch (tag >>> 3) {
                        case 1:
                            message.pid = reader.int64();
                            break;
                        case 2:
                            message.processName = reader.string();
                            break;
                        case 3:
                            if (!(message.threadName && message.threadName.length))
                                message.threadName = [];
                            message.threadName.push(reader.string());
                            break;
                        case 4:
                            message.uid = reader.int64();
                            break;
                        case 5:
                            if (!(message.uidPackageName && message.uidPackageName.length))
                                message.uidPackageName = [];
                            message.uidPackageName.push(reader.string());
                            break;
                        default:
                            reader.skipType(tag & 7);
                            break;
                        }
                    }
                    return message;
                };

                /**
                 * Decodes a Process message from the specified reader or buffer, length delimited.
                 * @function decodeDelimited
                 * @memberof perfetto.protos.AndroidTaskNames.Process
                 * @static
                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                 * @returns {perfetto.protos.AndroidTaskNames.Process} Process
                 * @throws {Error} If the payload is not a reader or valid buffer
                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
                 */
                Process.decodeDelimited = function decodeDelimited(reader) {
                    if (!(reader instanceof $Reader))
                        reader = new $Reader(reader);
                    return this.decode(reader, reader.uint32());
                };

                /**
                 * Verifies a Process message.
                 * @function verify
                 * @memberof perfetto.protos.AndroidTaskNames.Process
                 * @static
                 * @param {Object.<string,*>} message Plain object to verify
                 * @returns {string|null} `null` if valid, otherwise the reason why it is not
                 */
                Process.verify = function verify(message) {
                    if (typeof message !== "object" || message === null)
                        return "object expected";
                    if (message.pid != null && message.hasOwnProperty("pid"))
                        if (!$util.isInteger(message.pid) && !(message.pid && $util.isInteger(message.pid.low) && $util.isInteger(message.pid.high)))
                            return "pid: integer|Long expected";
                    if (message.processName != null && message.hasOwnProperty("processName"))
                        if (!$util.isString(message.processName))
                            return "processName: string expected";
                    if (message.threadName != null && message.hasOwnProperty("threadName")) {
                        if (!Array.isArray(message.threadName))
                            return "threadName: array expected";
                        for (var i = 0; i < message.threadName.length; ++i)
                            if (!$util.isString(message.threadName[i]))
                                return "threadName: string[] expected";
                    }
                    if (message.uid != null && message.hasOwnProperty("uid"))
                        if (!$util.isInteger(message.uid) && !(message.uid && $util.isInteger(message.uid.low) && $util.isInteger(message.uid.high)))
                            return "uid: integer|Long expected";
                    if (message.uidPackageName != null && message.hasOwnProperty("uidPackageName")) {
                        if (!Array.isArray(message.uidPackageName))
                            return "uidPackageName: array expected";
                        for (var i = 0; i < message.uidPackageName.length; ++i)
                            if (!$util.isString(message.uidPackageName[i]))
                                return "uidPackageName: string[] expected";
                    }
                    return null;
                };

                /**
                 * Creates a Process message from a plain object. Also converts values to their respective internal types.
                 * @function fromObject
                 * @memberof perfetto.protos.AndroidTaskNames.Process
                 * @static
                 * @param {Object.<string,*>} object Plain object
                 * @returns {perfetto.protos.AndroidTaskNames.Process} Process
                 */
                Process.fromObject = function fromObject(object) {
                    if (object instanceof $root.perfetto.protos.AndroidTaskNames.Process)
                        return object;
                    var message = new $root.perfetto.protos.AndroidTaskNames.Process();
                    if (object.pid != null)
                        if ($util.Long)
                            (message.pid = $util.Long.fromValue(object.pid)).unsigned = false;
                        else if (typeof object.pid === "string")
                            message.pid = parseInt(object.pid, 10);
                        else if (typeof object.pid === "number")
                            message.pid = object.pid;
                        else if (typeof object.pid === "object")
                            message.pid = new $util.LongBits(object.pid.low >>> 0, object.pid.high >>> 0).toNumber();
                    if (object.processName != null)
                        message.processName = String(object.processName);
                    if (object.threadName) {
                        if (!Array.isArray(object.threadName))
                            throw TypeError(".perfetto.protos.AndroidTaskNames.Process.threadName: array expected");
                        message.threadName = [];
                        for (var i = 0; i < object.threadName.length; ++i)
                            message.threadName[i] = String(object.threadName[i]);
                    }
                    if (object.uid != null)
                        if ($util.Long)
                            (message.uid = $util.Long.fromValue(object.uid)).unsigned = false;
                        else if (typeof object.uid === "string")
                            message.uid = parseInt(object.uid, 10);
                        else if (typeof object.uid === "number")
                            message.uid = object.uid;
                        else if (typeof object.uid === "object")
                            message.uid = new $util.LongBits(object.uid.low >>> 0, object.uid.high >>> 0).toNumber();
                    if (object.uidPackageName) {
                        if (!Array.isArray(object.uidPackageName))
                            throw TypeError(".perfetto.protos.AndroidTaskNames.Process.uidPackageName: array expected");
                        message.uidPackageName = [];
                        for (var i = 0; i < object.uidPackageName.length; ++i)
                            message.uidPackageName[i] = String(object.uidPackageName[i]);
                    }
                    return message;
                };

                /**
                 * Creates a plain object from a Process message. Also converts values to other types if specified.
                 * @function toObject
                 * @memberof perfetto.protos.AndroidTaskNames.Process
                 * @static
                 * @param {perfetto.protos.AndroidTaskNames.Process} message Process
                 * @param {$protobuf.IConversionOptions} [options] Conversion options
                 * @returns {Object.<string,*>} Plain object
                 */
                Process.toObject = function toObject(message, options) {
                    if (!options)
                        options = {};
                    var object = {};
                    if (options.arrays || options.defaults) {
                        object.threadName = [];
                        object.uidPackageName = [];
                    }
                    if (options.defaults) {
                        if ($util.Long) {
                            var long = new $util.Long(0, 0, false);
                            object.pid = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
                        } else
                            object.pid = options.longs === String ? "0" : 0;
                        object.processName = "";
                        if ($util.Long) {
                            var long = new $util.Long(0, 0, false);
                            object.uid = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
                        } else
                            object.uid = options.longs === String ? "0" : 0;
                    }
                    if (message.pid != null && message.hasOwnProperty("pid"))
                        if (typeof message.pid === "number")
                            object.pid = options.longs === String ? String(message.pid) : message.pid;
                        else
                            object.pid = options.longs === String ? $util.Long.prototype.toString.call(message.pid) : options.longs === Number ? new $util.LongBits(message.pid.low >>> 0, message.pid.high >>> 0).toNumber() : message.pid;
                    if (message.processName != null && message.hasOwnProperty("processName"))
                        object.processName = message.processName;
                    if (message.threadName && message.threadName.length) {
                        object.threadName = [];
                        for (var j = 0; j < message.threadName.length; ++j)
                            object.threadName[j] = message.threadName[j];
                    }
                    if (message.uid != null && message.hasOwnProperty("uid"))
                        if (typeof message.uid === "number")
                            object.uid = options.longs === String ? String(message.uid) : message.uid;
                        else
                            object.uid = options.longs === String ? $util.Long.prototype.toString.call(message.uid) : options.longs === Number ? new $util.LongBits(message.uid.low >>> 0, message.uid.high >>> 0).toNumber() : message.uid;
                    if (message.uidPackageName && message.uidPackageName.length) {
                        object.uidPackageName = [];
                        for (var j = 0; j < message.uidPackageName.length; ++j)
                            object.uidPackageName[j] = message.uidPackageName[j];
                    }
                    return object;
                };

                /**
                 * Converts this Process to JSON.
                 * @function toJSON
                 * @memberof perfetto.protos.AndroidTaskNames.Process
                 * @instance
                 * @returns {Object.<string,*>} JSON object
                 */
                Process.prototype.toJSON = function toJSON() {
                    return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
                };

                return Process;
            })();

            return AndroidTaskNames;
        })();

        protos.AndroidThreadTimeInStateMetric = (function() {

            /**
             * Properties of an AndroidThreadTimeInStateMetric.
             * @memberof perfetto.protos
             * @interface IAndroidThreadTimeInStateMetric
             * @property {Array.<perfetto.protos.AndroidThreadTimeInStateMetric.IProcess>|null} [processes] AndroidThreadTimeInStateMetric processes
             */

            /**
             * Constructs a new AndroidThreadTimeInStateMetric.
             * @memberof perfetto.protos
             * @classdesc Represents an AndroidThreadTimeInStateMetric.
             * @implements IAndroidThreadTimeInStateMetric
             * @constructor
             * @param {perfetto.protos.IAndroidThreadTimeInStateMetric=} [properties] Properties to set
             */
            function AndroidThreadTimeInStateMetric(properties) {
                this.processes = [];
                if (properties)
                    for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                        if (properties[keys[i]] != null)
                            this[keys[i]] = properties[keys[i]];
            }

            /**
             * AndroidThreadTimeInStateMetric processes.
             * @member {Array.<perfetto.protos.AndroidThreadTimeInStateMetric.IProcess>} processes
             * @memberof perfetto.protos.AndroidThreadTimeInStateMetric
             * @instance
             */
            AndroidThreadTimeInStateMetric.prototype.processes = $util.emptyArray;

            /**
             * Creates a new AndroidThreadTimeInStateMetric instance using the specified properties.
             * @function create
             * @memberof perfetto.protos.AndroidThreadTimeInStateMetric
             * @static
             * @param {perfetto.protos.IAndroidThreadTimeInStateMetric=} [properties] Properties to set
             * @returns {perfetto.protos.AndroidThreadTimeInStateMetric} AndroidThreadTimeInStateMetric instance
             */
            AndroidThreadTimeInStateMetric.create = function create(properties) {
                return new AndroidThreadTimeInStateMetric(properties);
            };

            /**
             * Encodes the specified AndroidThreadTimeInStateMetric message. Does not implicitly {@link perfetto.protos.AndroidThreadTimeInStateMetric.verify|verify} messages.
             * @function encode
             * @memberof perfetto.protos.AndroidThreadTimeInStateMetric
             * @static
             * @param {perfetto.protos.IAndroidThreadTimeInStateMetric} message AndroidThreadTimeInStateMetric message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            AndroidThreadTimeInStateMetric.encode = function encode(message, writer) {
                if (!writer)
                    writer = $Writer.create();
                if (message.processes != null && message.processes.length)
                    for (var i = 0; i < message.processes.length; ++i)
                        $root.perfetto.protos.AndroidThreadTimeInStateMetric.Process.encode(message.processes[i], writer.uint32(/* id 1, wireType 2 =*/10).fork()).ldelim();
                return writer;
            };

            /**
             * Encodes the specified AndroidThreadTimeInStateMetric message, length delimited. Does not implicitly {@link perfetto.protos.AndroidThreadTimeInStateMetric.verify|verify} messages.
             * @function encodeDelimited
             * @memberof perfetto.protos.AndroidThreadTimeInStateMetric
             * @static
             * @param {perfetto.protos.IAndroidThreadTimeInStateMetric} message AndroidThreadTimeInStateMetric message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            AndroidThreadTimeInStateMetric.encodeDelimited = function encodeDelimited(message, writer) {
                return this.encode(message, writer).ldelim();
            };

            /**
             * Decodes an AndroidThreadTimeInStateMetric message from the specified reader or buffer.
             * @function decode
             * @memberof perfetto.protos.AndroidThreadTimeInStateMetric
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @param {number} [length] Message length if known beforehand
             * @returns {perfetto.protos.AndroidThreadTimeInStateMetric} AndroidThreadTimeInStateMetric
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            AndroidThreadTimeInStateMetric.decode = function decode(reader, length) {
                if (!(reader instanceof $Reader))
                    reader = $Reader.create(reader);
                var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.AndroidThreadTimeInStateMetric();
                while (reader.pos < end) {
                    var tag = reader.uint32();
                    switch (tag >>> 3) {
                    case 1:
                        if (!(message.processes && message.processes.length))
                            message.processes = [];
                        message.processes.push($root.perfetto.protos.AndroidThreadTimeInStateMetric.Process.decode(reader, reader.uint32()));
                        break;
                    default:
                        reader.skipType(tag & 7);
                        break;
                    }
                }
                return message;
            };

            /**
             * Decodes an AndroidThreadTimeInStateMetric message from the specified reader or buffer, length delimited.
             * @function decodeDelimited
             * @memberof perfetto.protos.AndroidThreadTimeInStateMetric
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @returns {perfetto.protos.AndroidThreadTimeInStateMetric} AndroidThreadTimeInStateMetric
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            AndroidThreadTimeInStateMetric.decodeDelimited = function decodeDelimited(reader) {
                if (!(reader instanceof $Reader))
                    reader = new $Reader(reader);
                return this.decode(reader, reader.uint32());
            };

            /**
             * Verifies an AndroidThreadTimeInStateMetric message.
             * @function verify
             * @memberof perfetto.protos.AndroidThreadTimeInStateMetric
             * @static
             * @param {Object.<string,*>} message Plain object to verify
             * @returns {string|null} `null` if valid, otherwise the reason why it is not
             */
            AndroidThreadTimeInStateMetric.verify = function verify(message) {
                if (typeof message !== "object" || message === null)
                    return "object expected";
                if (message.processes != null && message.hasOwnProperty("processes")) {
                    if (!Array.isArray(message.processes))
                        return "processes: array expected";
                    for (var i = 0; i < message.processes.length; ++i) {
                        var error = $root.perfetto.protos.AndroidThreadTimeInStateMetric.Process.verify(message.processes[i]);
                        if (error)
                            return "processes." + error;
                    }
                }
                return null;
            };

            /**
             * Creates an AndroidThreadTimeInStateMetric message from a plain object. Also converts values to their respective internal types.
             * @function fromObject
             * @memberof perfetto.protos.AndroidThreadTimeInStateMetric
             * @static
             * @param {Object.<string,*>} object Plain object
             * @returns {perfetto.protos.AndroidThreadTimeInStateMetric} AndroidThreadTimeInStateMetric
             */
            AndroidThreadTimeInStateMetric.fromObject = function fromObject(object) {
                if (object instanceof $root.perfetto.protos.AndroidThreadTimeInStateMetric)
                    return object;
                var message = new $root.perfetto.protos.AndroidThreadTimeInStateMetric();
                if (object.processes) {
                    if (!Array.isArray(object.processes))
                        throw TypeError(".perfetto.protos.AndroidThreadTimeInStateMetric.processes: array expected");
                    message.processes = [];
                    for (var i = 0; i < object.processes.length; ++i) {
                        if (typeof object.processes[i] !== "object")
                            throw TypeError(".perfetto.protos.AndroidThreadTimeInStateMetric.processes: object expected");
                        message.processes[i] = $root.perfetto.protos.AndroidThreadTimeInStateMetric.Process.fromObject(object.processes[i]);
                    }
                }
                return message;
            };

            /**
             * Creates a plain object from an AndroidThreadTimeInStateMetric message. Also converts values to other types if specified.
             * @function toObject
             * @memberof perfetto.protos.AndroidThreadTimeInStateMetric
             * @static
             * @param {perfetto.protos.AndroidThreadTimeInStateMetric} message AndroidThreadTimeInStateMetric
             * @param {$protobuf.IConversionOptions} [options] Conversion options
             * @returns {Object.<string,*>} Plain object
             */
            AndroidThreadTimeInStateMetric.toObject = function toObject(message, options) {
                if (!options)
                    options = {};
                var object = {};
                if (options.arrays || options.defaults)
                    object.processes = [];
                if (message.processes && message.processes.length) {
                    object.processes = [];
                    for (var j = 0; j < message.processes.length; ++j)
                        object.processes[j] = $root.perfetto.protos.AndroidThreadTimeInStateMetric.Process.toObject(message.processes[j], options);
                }
                return object;
            };

            /**
             * Converts this AndroidThreadTimeInStateMetric to JSON.
             * @function toJSON
             * @memberof perfetto.protos.AndroidThreadTimeInStateMetric
             * @instance
             * @returns {Object.<string,*>} JSON object
             */
            AndroidThreadTimeInStateMetric.prototype.toJSON = function toJSON() {
                return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
            };

            AndroidThreadTimeInStateMetric.MetricsByCoreType = (function() {

                /**
                 * Properties of a MetricsByCoreType.
                 * @memberof perfetto.protos.AndroidThreadTimeInStateMetric
                 * @interface IMetricsByCoreType
                 * @property {number|null} [timeInStateCpu] MetricsByCoreType timeInStateCpu
                 * @property {string|null} [coreType] MetricsByCoreType coreType
                 * @property {number|null} [runtimeMs] MetricsByCoreType runtimeMs
                 * @property {number|null} [mcycles] MetricsByCoreType mcycles
                 * @property {number|null} [powerProfileMah] MetricsByCoreType powerProfileMah
                 */

                /**
                 * Constructs a new MetricsByCoreType.
                 * @memberof perfetto.protos.AndroidThreadTimeInStateMetric
                 * @classdesc Represents a MetricsByCoreType.
                 * @implements IMetricsByCoreType
                 * @constructor
                 * @param {perfetto.protos.AndroidThreadTimeInStateMetric.IMetricsByCoreType=} [properties] Properties to set
                 */
                function MetricsByCoreType(properties) {
                    if (properties)
                        for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                            if (properties[keys[i]] != null)
                                this[keys[i]] = properties[keys[i]];
                }

                /**
                 * MetricsByCoreType timeInStateCpu.
                 * @member {number} timeInStateCpu
                 * @memberof perfetto.protos.AndroidThreadTimeInStateMetric.MetricsByCoreType
                 * @instance
                 */
                MetricsByCoreType.prototype.timeInStateCpu = 0;

                /**
                 * MetricsByCoreType coreType.
                 * @member {string} coreType
                 * @memberof perfetto.protos.AndroidThreadTimeInStateMetric.MetricsByCoreType
                 * @instance
                 */
                MetricsByCoreType.prototype.coreType = "";

                /**
                 * MetricsByCoreType runtimeMs.
                 * @member {number} runtimeMs
                 * @memberof perfetto.protos.AndroidThreadTimeInStateMetric.MetricsByCoreType
                 * @instance
                 */
                MetricsByCoreType.prototype.runtimeMs = $util.Long ? $util.Long.fromBits(0,0,false) : 0;

                /**
                 * MetricsByCoreType mcycles.
                 * @member {number} mcycles
                 * @memberof perfetto.protos.AndroidThreadTimeInStateMetric.MetricsByCoreType
                 * @instance
                 */
                MetricsByCoreType.prototype.mcycles = $util.Long ? $util.Long.fromBits(0,0,false) : 0;

                /**
                 * MetricsByCoreType powerProfileMah.
                 * @member {number} powerProfileMah
                 * @memberof perfetto.protos.AndroidThreadTimeInStateMetric.MetricsByCoreType
                 * @instance
                 */
                MetricsByCoreType.prototype.powerProfileMah = 0;

                /**
                 * Creates a new MetricsByCoreType instance using the specified properties.
                 * @function create
                 * @memberof perfetto.protos.AndroidThreadTimeInStateMetric.MetricsByCoreType
                 * @static
                 * @param {perfetto.protos.AndroidThreadTimeInStateMetric.IMetricsByCoreType=} [properties] Properties to set
                 * @returns {perfetto.protos.AndroidThreadTimeInStateMetric.MetricsByCoreType} MetricsByCoreType instance
                 */
                MetricsByCoreType.create = function create(properties) {
                    return new MetricsByCoreType(properties);
                };

                /**
                 * Encodes the specified MetricsByCoreType message. Does not implicitly {@link perfetto.protos.AndroidThreadTimeInStateMetric.MetricsByCoreType.verify|verify} messages.
                 * @function encode
                 * @memberof perfetto.protos.AndroidThreadTimeInStateMetric.MetricsByCoreType
                 * @static
                 * @param {perfetto.protos.AndroidThreadTimeInStateMetric.IMetricsByCoreType} message MetricsByCoreType message or plain object to encode
                 * @param {$protobuf.Writer} [writer] Writer to encode to
                 * @returns {$protobuf.Writer} Writer
                 */
                MetricsByCoreType.encode = function encode(message, writer) {
                    if (!writer)
                        writer = $Writer.create();
                    if (message.coreType != null && Object.hasOwnProperty.call(message, "coreType"))
                        writer.uint32(/* id 1, wireType 2 =*/10).string(message.coreType);
                    if (message.runtimeMs != null && Object.hasOwnProperty.call(message, "runtimeMs"))
                        writer.uint32(/* id 2, wireType 0 =*/16).int64(message.runtimeMs);
                    if (message.mcycles != null && Object.hasOwnProperty.call(message, "mcycles"))
                        writer.uint32(/* id 3, wireType 0 =*/24).int64(message.mcycles);
                    if (message.powerProfileMah != null && Object.hasOwnProperty.call(message, "powerProfileMah"))
                        writer.uint32(/* id 4, wireType 1 =*/33).double(message.powerProfileMah);
                    if (message.timeInStateCpu != null && Object.hasOwnProperty.call(message, "timeInStateCpu"))
                        writer.uint32(/* id 5, wireType 0 =*/40).int32(message.timeInStateCpu);
                    return writer;
                };

                /**
                 * Encodes the specified MetricsByCoreType message, length delimited. Does not implicitly {@link perfetto.protos.AndroidThreadTimeInStateMetric.MetricsByCoreType.verify|verify} messages.
                 * @function encodeDelimited
                 * @memberof perfetto.protos.AndroidThreadTimeInStateMetric.MetricsByCoreType
                 * @static
                 * @param {perfetto.protos.AndroidThreadTimeInStateMetric.IMetricsByCoreType} message MetricsByCoreType message or plain object to encode
                 * @param {$protobuf.Writer} [writer] Writer to encode to
                 * @returns {$protobuf.Writer} Writer
                 */
                MetricsByCoreType.encodeDelimited = function encodeDelimited(message, writer) {
                    return this.encode(message, writer).ldelim();
                };

                /**
                 * Decodes a MetricsByCoreType message from the specified reader or buffer.
                 * @function decode
                 * @memberof perfetto.protos.AndroidThreadTimeInStateMetric.MetricsByCoreType
                 * @static
                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                 * @param {number} [length] Message length if known beforehand
                 * @returns {perfetto.protos.AndroidThreadTimeInStateMetric.MetricsByCoreType} MetricsByCoreType
                 * @throws {Error} If the payload is not a reader or valid buffer
                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
                 */
                MetricsByCoreType.decode = function decode(reader, length) {
                    if (!(reader instanceof $Reader))
                        reader = $Reader.create(reader);
                    var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.AndroidThreadTimeInStateMetric.MetricsByCoreType();
                    while (reader.pos < end) {
                        var tag = reader.uint32();
                        switch (tag >>> 3) {
                        case 5:
                            message.timeInStateCpu = reader.int32();
                            break;
                        case 1:
                            message.coreType = reader.string();
                            break;
                        case 2:
                            message.runtimeMs = reader.int64();
                            break;
                        case 3:
                            message.mcycles = reader.int64();
                            break;
                        case 4:
                            message.powerProfileMah = reader.double();
                            break;
                        default:
                            reader.skipType(tag & 7);
                            break;
                        }
                    }
                    return message;
                };

                /**
                 * Decodes a MetricsByCoreType message from the specified reader or buffer, length delimited.
                 * @function decodeDelimited
                 * @memberof perfetto.protos.AndroidThreadTimeInStateMetric.MetricsByCoreType
                 * @static
                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                 * @returns {perfetto.protos.AndroidThreadTimeInStateMetric.MetricsByCoreType} MetricsByCoreType
                 * @throws {Error} If the payload is not a reader or valid buffer
                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
                 */
                MetricsByCoreType.decodeDelimited = function decodeDelimited(reader) {
                    if (!(reader instanceof $Reader))
                        reader = new $Reader(reader);
                    return this.decode(reader, reader.uint32());
                };

                /**
                 * Verifies a MetricsByCoreType message.
                 * @function verify
                 * @memberof perfetto.protos.AndroidThreadTimeInStateMetric.MetricsByCoreType
                 * @static
                 * @param {Object.<string,*>} message Plain object to verify
                 * @returns {string|null} `null` if valid, otherwise the reason why it is not
                 */
                MetricsByCoreType.verify = function verify(message) {
                    if (typeof message !== "object" || message === null)
                        return "object expected";
                    if (message.timeInStateCpu != null && message.hasOwnProperty("timeInStateCpu"))
                        if (!$util.isInteger(message.timeInStateCpu))
                            return "timeInStateCpu: integer expected";
                    if (message.coreType != null && message.hasOwnProperty("coreType"))
                        if (!$util.isString(message.coreType))
                            return "coreType: string expected";
                    if (message.runtimeMs != null && message.hasOwnProperty("runtimeMs"))
                        if (!$util.isInteger(message.runtimeMs) && !(message.runtimeMs && $util.isInteger(message.runtimeMs.low) && $util.isInteger(message.runtimeMs.high)))
                            return "runtimeMs: integer|Long expected";
                    if (message.mcycles != null && message.hasOwnProperty("mcycles"))
                        if (!$util.isInteger(message.mcycles) && !(message.mcycles && $util.isInteger(message.mcycles.low) && $util.isInteger(message.mcycles.high)))
                            return "mcycles: integer|Long expected";
                    if (message.powerProfileMah != null && message.hasOwnProperty("powerProfileMah"))
                        if (typeof message.powerProfileMah !== "number")
                            return "powerProfileMah: number expected";
                    return null;
                };

                /**
                 * Creates a MetricsByCoreType message from a plain object. Also converts values to their respective internal types.
                 * @function fromObject
                 * @memberof perfetto.protos.AndroidThreadTimeInStateMetric.MetricsByCoreType
                 * @static
                 * @param {Object.<string,*>} object Plain object
                 * @returns {perfetto.protos.AndroidThreadTimeInStateMetric.MetricsByCoreType} MetricsByCoreType
                 */
                MetricsByCoreType.fromObject = function fromObject(object) {
                    if (object instanceof $root.perfetto.protos.AndroidThreadTimeInStateMetric.MetricsByCoreType)
                        return object;
                    var message = new $root.perfetto.protos.AndroidThreadTimeInStateMetric.MetricsByCoreType();
                    if (object.timeInStateCpu != null)
                        message.timeInStateCpu = object.timeInStateCpu | 0;
                    if (object.coreType != null)
                        message.coreType = String(object.coreType);
                    if (object.runtimeMs != null)
                        if ($util.Long)
                            (message.runtimeMs = $util.Long.fromValue(object.runtimeMs)).unsigned = false;
                        else if (typeof object.runtimeMs === "string")
                            message.runtimeMs = parseInt(object.runtimeMs, 10);
                        else if (typeof object.runtimeMs === "number")
                            message.runtimeMs = object.runtimeMs;
                        else if (typeof object.runtimeMs === "object")
                            message.runtimeMs = new $util.LongBits(object.runtimeMs.low >>> 0, object.runtimeMs.high >>> 0).toNumber();
                    if (object.mcycles != null)
                        if ($util.Long)
                            (message.mcycles = $util.Long.fromValue(object.mcycles)).unsigned = false;
                        else if (typeof object.mcycles === "string")
                            message.mcycles = parseInt(object.mcycles, 10);
                        else if (typeof object.mcycles === "number")
                            message.mcycles = object.mcycles;
                        else if (typeof object.mcycles === "object")
                            message.mcycles = new $util.LongBits(object.mcycles.low >>> 0, object.mcycles.high >>> 0).toNumber();
                    if (object.powerProfileMah != null)
                        message.powerProfileMah = Number(object.powerProfileMah);
                    return message;
                };

                /**
                 * Creates a plain object from a MetricsByCoreType message. Also converts values to other types if specified.
                 * @function toObject
                 * @memberof perfetto.protos.AndroidThreadTimeInStateMetric.MetricsByCoreType
                 * @static
                 * @param {perfetto.protos.AndroidThreadTimeInStateMetric.MetricsByCoreType} message MetricsByCoreType
                 * @param {$protobuf.IConversionOptions} [options] Conversion options
                 * @returns {Object.<string,*>} Plain object
                 */
                MetricsByCoreType.toObject = function toObject(message, options) {
                    if (!options)
                        options = {};
                    var object = {};
                    if (options.defaults) {
                        object.coreType = "";
                        if ($util.Long) {
                            var long = new $util.Long(0, 0, false);
                            object.runtimeMs = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
                        } else
                            object.runtimeMs = options.longs === String ? "0" : 0;
                        if ($util.Long) {
                            var long = new $util.Long(0, 0, false);
                            object.mcycles = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
                        } else
                            object.mcycles = options.longs === String ? "0" : 0;
                        object.powerProfileMah = 0;
                        object.timeInStateCpu = 0;
                    }
                    if (message.coreType != null && message.hasOwnProperty("coreType"))
                        object.coreType = message.coreType;
                    if (message.runtimeMs != null && message.hasOwnProperty("runtimeMs"))
                        if (typeof message.runtimeMs === "number")
                            object.runtimeMs = options.longs === String ? String(message.runtimeMs) : message.runtimeMs;
                        else
                            object.runtimeMs = options.longs === String ? $util.Long.prototype.toString.call(message.runtimeMs) : options.longs === Number ? new $util.LongBits(message.runtimeMs.low >>> 0, message.runtimeMs.high >>> 0).toNumber() : message.runtimeMs;
                    if (message.mcycles != null && message.hasOwnProperty("mcycles"))
                        if (typeof message.mcycles === "number")
                            object.mcycles = options.longs === String ? String(message.mcycles) : message.mcycles;
                        else
                            object.mcycles = options.longs === String ? $util.Long.prototype.toString.call(message.mcycles) : options.longs === Number ? new $util.LongBits(message.mcycles.low >>> 0, message.mcycles.high >>> 0).toNumber() : message.mcycles;
                    if (message.powerProfileMah != null && message.hasOwnProperty("powerProfileMah"))
                        object.powerProfileMah = options.json && !isFinite(message.powerProfileMah) ? String(message.powerProfileMah) : message.powerProfileMah;
                    if (message.timeInStateCpu != null && message.hasOwnProperty("timeInStateCpu"))
                        object.timeInStateCpu = message.timeInStateCpu;
                    return object;
                };

                /**
                 * Converts this MetricsByCoreType to JSON.
                 * @function toJSON
                 * @memberof perfetto.protos.AndroidThreadTimeInStateMetric.MetricsByCoreType
                 * @instance
                 * @returns {Object.<string,*>} JSON object
                 */
                MetricsByCoreType.prototype.toJSON = function toJSON() {
                    return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
                };

                return MetricsByCoreType;
            })();

            AndroidThreadTimeInStateMetric.Thread = (function() {

                /**
                 * Properties of a Thread.
                 * @memberof perfetto.protos.AndroidThreadTimeInStateMetric
                 * @interface IThread
                 * @property {string|null} [name] Thread name
                 * @property {boolean|null} [mainThread] Thread mainThread
                 * @property {Array.<perfetto.protos.AndroidThreadTimeInStateMetric.IMetricsByCoreType>|null} [metricsByCoreType] Thread metricsByCoreType
                 */

                /**
                 * Constructs a new Thread.
                 * @memberof perfetto.protos.AndroidThreadTimeInStateMetric
                 * @classdesc Represents a Thread.
                 * @implements IThread
                 * @constructor
                 * @param {perfetto.protos.AndroidThreadTimeInStateMetric.IThread=} [properties] Properties to set
                 */
                function Thread(properties) {
                    this.metricsByCoreType = [];
                    if (properties)
                        for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                            if (properties[keys[i]] != null)
                                this[keys[i]] = properties[keys[i]];
                }

                /**
                 * Thread name.
                 * @member {string} name
                 * @memberof perfetto.protos.AndroidThreadTimeInStateMetric.Thread
                 * @instance
                 */
                Thread.prototype.name = "";

                /**
                 * Thread mainThread.
                 * @member {boolean} mainThread
                 * @memberof perfetto.protos.AndroidThreadTimeInStateMetric.Thread
                 * @instance
                 */
                Thread.prototype.mainThread = false;

                /**
                 * Thread metricsByCoreType.
                 * @member {Array.<perfetto.protos.AndroidThreadTimeInStateMetric.IMetricsByCoreType>} metricsByCoreType
                 * @memberof perfetto.protos.AndroidThreadTimeInStateMetric.Thread
                 * @instance
                 */
                Thread.prototype.metricsByCoreType = $util.emptyArray;

                /**
                 * Creates a new Thread instance using the specified properties.
                 * @function create
                 * @memberof perfetto.protos.AndroidThreadTimeInStateMetric.Thread
                 * @static
                 * @param {perfetto.protos.AndroidThreadTimeInStateMetric.IThread=} [properties] Properties to set
                 * @returns {perfetto.protos.AndroidThreadTimeInStateMetric.Thread} Thread instance
                 */
                Thread.create = function create(properties) {
                    return new Thread(properties);
                };

                /**
                 * Encodes the specified Thread message. Does not implicitly {@link perfetto.protos.AndroidThreadTimeInStateMetric.Thread.verify|verify} messages.
                 * @function encode
                 * @memberof perfetto.protos.AndroidThreadTimeInStateMetric.Thread
                 * @static
                 * @param {perfetto.protos.AndroidThreadTimeInStateMetric.IThread} message Thread message or plain object to encode
                 * @param {$protobuf.Writer} [writer] Writer to encode to
                 * @returns {$protobuf.Writer} Writer
                 */
                Thread.encode = function encode(message, writer) {
                    if (!writer)
                        writer = $Writer.create();
                    if (message.name != null && Object.hasOwnProperty.call(message, "name"))
                        writer.uint32(/* id 1, wireType 2 =*/10).string(message.name);
                    if (message.metricsByCoreType != null && message.metricsByCoreType.length)
                        for (var i = 0; i < message.metricsByCoreType.length; ++i)
                            $root.perfetto.protos.AndroidThreadTimeInStateMetric.MetricsByCoreType.encode(message.metricsByCoreType[i], writer.uint32(/* id 2, wireType 2 =*/18).fork()).ldelim();
                    if (message.mainThread != null && Object.hasOwnProperty.call(message, "mainThread"))
                        writer.uint32(/* id 3, wireType 0 =*/24).bool(message.mainThread);
                    return writer;
                };

                /**
                 * Encodes the specified Thread message, length delimited. Does not implicitly {@link perfetto.protos.AndroidThreadTimeInStateMetric.Thread.verify|verify} messages.
                 * @function encodeDelimited
                 * @memberof perfetto.protos.AndroidThreadTimeInStateMetric.Thread
                 * @static
                 * @param {perfetto.protos.AndroidThreadTimeInStateMetric.IThread} message Thread message or plain object to encode
                 * @param {$protobuf.Writer} [writer] Writer to encode to
                 * @returns {$protobuf.Writer} Writer
                 */
                Thread.encodeDelimited = function encodeDelimited(message, writer) {
                    return this.encode(message, writer).ldelim();
                };

                /**
                 * Decodes a Thread message from the specified reader or buffer.
                 * @function decode
                 * @memberof perfetto.protos.AndroidThreadTimeInStateMetric.Thread
                 * @static
                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                 * @param {number} [length] Message length if known beforehand
                 * @returns {perfetto.protos.AndroidThreadTimeInStateMetric.Thread} Thread
                 * @throws {Error} If the payload is not a reader or valid buffer
                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
                 */
                Thread.decode = function decode(reader, length) {
                    if (!(reader instanceof $Reader))
                        reader = $Reader.create(reader);
                    var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.AndroidThreadTimeInStateMetric.Thread();
                    while (reader.pos < end) {
                        var tag = reader.uint32();
                        switch (tag >>> 3) {
                        case 1:
                            message.name = reader.string();
                            break;
                        case 3:
                            message.mainThread = reader.bool();
                            break;
                        case 2:
                            if (!(message.metricsByCoreType && message.metricsByCoreType.length))
                                message.metricsByCoreType = [];
                            message.metricsByCoreType.push($root.perfetto.protos.AndroidThreadTimeInStateMetric.MetricsByCoreType.decode(reader, reader.uint32()));
                            break;
                        default:
                            reader.skipType(tag & 7);
                            break;
                        }
                    }
                    return message;
                };

                /**
                 * Decodes a Thread message from the specified reader or buffer, length delimited.
                 * @function decodeDelimited
                 * @memberof perfetto.protos.AndroidThreadTimeInStateMetric.Thread
                 * @static
                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                 * @returns {perfetto.protos.AndroidThreadTimeInStateMetric.Thread} Thread
                 * @throws {Error} If the payload is not a reader or valid buffer
                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
                 */
                Thread.decodeDelimited = function decodeDelimited(reader) {
                    if (!(reader instanceof $Reader))
                        reader = new $Reader(reader);
                    return this.decode(reader, reader.uint32());
                };

                /**
                 * Verifies a Thread message.
                 * @function verify
                 * @memberof perfetto.protos.AndroidThreadTimeInStateMetric.Thread
                 * @static
                 * @param {Object.<string,*>} message Plain object to verify
                 * @returns {string|null} `null` if valid, otherwise the reason why it is not
                 */
                Thread.verify = function verify(message) {
                    if (typeof message !== "object" || message === null)
                        return "object expected";
                    if (message.name != null && message.hasOwnProperty("name"))
                        if (!$util.isString(message.name))
                            return "name: string expected";
                    if (message.mainThread != null && message.hasOwnProperty("mainThread"))
                        if (typeof message.mainThread !== "boolean")
                            return "mainThread: boolean expected";
                    if (message.metricsByCoreType != null && message.hasOwnProperty("metricsByCoreType")) {
                        if (!Array.isArray(message.metricsByCoreType))
                            return "metricsByCoreType: array expected";
                        for (var i = 0; i < message.metricsByCoreType.length; ++i) {
                            var error = $root.perfetto.protos.AndroidThreadTimeInStateMetric.MetricsByCoreType.verify(message.metricsByCoreType[i]);
                            if (error)
                                return "metricsByCoreType." + error;
                        }
                    }
                    return null;
                };

                /**
                 * Creates a Thread message from a plain object. Also converts values to their respective internal types.
                 * @function fromObject
                 * @memberof perfetto.protos.AndroidThreadTimeInStateMetric.Thread
                 * @static
                 * @param {Object.<string,*>} object Plain object
                 * @returns {perfetto.protos.AndroidThreadTimeInStateMetric.Thread} Thread
                 */
                Thread.fromObject = function fromObject(object) {
                    if (object instanceof $root.perfetto.protos.AndroidThreadTimeInStateMetric.Thread)
                        return object;
                    var message = new $root.perfetto.protos.AndroidThreadTimeInStateMetric.Thread();
                    if (object.name != null)
                        message.name = String(object.name);
                    if (object.mainThread != null)
                        message.mainThread = Boolean(object.mainThread);
                    if (object.metricsByCoreType) {
                        if (!Array.isArray(object.metricsByCoreType))
                            throw TypeError(".perfetto.protos.AndroidThreadTimeInStateMetric.Thread.metricsByCoreType: array expected");
                        message.metricsByCoreType = [];
                        for (var i = 0; i < object.metricsByCoreType.length; ++i) {
                            if (typeof object.metricsByCoreType[i] !== "object")
                                throw TypeError(".perfetto.protos.AndroidThreadTimeInStateMetric.Thread.metricsByCoreType: object expected");
                            message.metricsByCoreType[i] = $root.perfetto.protos.AndroidThreadTimeInStateMetric.MetricsByCoreType.fromObject(object.metricsByCoreType[i]);
                        }
                    }
                    return message;
                };

                /**
                 * Creates a plain object from a Thread message. Also converts values to other types if specified.
                 * @function toObject
                 * @memberof perfetto.protos.AndroidThreadTimeInStateMetric.Thread
                 * @static
                 * @param {perfetto.protos.AndroidThreadTimeInStateMetric.Thread} message Thread
                 * @param {$protobuf.IConversionOptions} [options] Conversion options
                 * @returns {Object.<string,*>} Plain object
                 */
                Thread.toObject = function toObject(message, options) {
                    if (!options)
                        options = {};
                    var object = {};
                    if (options.arrays || options.defaults)
                        object.metricsByCoreType = [];
                    if (options.defaults) {
                        object.name = "";
                        object.mainThread = false;
                    }
                    if (message.name != null && message.hasOwnProperty("name"))
                        object.name = message.name;
                    if (message.metricsByCoreType && message.metricsByCoreType.length) {
                        object.metricsByCoreType = [];
                        for (var j = 0; j < message.metricsByCoreType.length; ++j)
                            object.metricsByCoreType[j] = $root.perfetto.protos.AndroidThreadTimeInStateMetric.MetricsByCoreType.toObject(message.metricsByCoreType[j], options);
                    }
                    if (message.mainThread != null && message.hasOwnProperty("mainThread"))
                        object.mainThread = message.mainThread;
                    return object;
                };

                /**
                 * Converts this Thread to JSON.
                 * @function toJSON
                 * @memberof perfetto.protos.AndroidThreadTimeInStateMetric.Thread
                 * @instance
                 * @returns {Object.<string,*>} JSON object
                 */
                Thread.prototype.toJSON = function toJSON() {
                    return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
                };

                return Thread;
            })();

            AndroidThreadTimeInStateMetric.Process = (function() {

                /**
                 * Properties of a Process.
                 * @memberof perfetto.protos.AndroidThreadTimeInStateMetric
                 * @interface IProcess
                 * @property {perfetto.protos.IAndroidProcessMetadata|null} [metadata] Process metadata
                 * @property {Array.<perfetto.protos.AndroidThreadTimeInStateMetric.IMetricsByCoreType>|null} [metricsByCoreType] Process metricsByCoreType
                 * @property {Array.<perfetto.protos.AndroidThreadTimeInStateMetric.IThread>|null} [threads] Process threads
                 */

                /**
                 * Constructs a new Process.
                 * @memberof perfetto.protos.AndroidThreadTimeInStateMetric
                 * @classdesc Represents a Process.
                 * @implements IProcess
                 * @constructor
                 * @param {perfetto.protos.AndroidThreadTimeInStateMetric.IProcess=} [properties] Properties to set
                 */
                function Process(properties) {
                    this.metricsByCoreType = [];
                    this.threads = [];
                    if (properties)
                        for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                            if (properties[keys[i]] != null)
                                this[keys[i]] = properties[keys[i]];
                }

                /**
                 * Process metadata.
                 * @member {perfetto.protos.IAndroidProcessMetadata|null|undefined} metadata
                 * @memberof perfetto.protos.AndroidThreadTimeInStateMetric.Process
                 * @instance
                 */
                Process.prototype.metadata = null;

                /**
                 * Process metricsByCoreType.
                 * @member {Array.<perfetto.protos.AndroidThreadTimeInStateMetric.IMetricsByCoreType>} metricsByCoreType
                 * @memberof perfetto.protos.AndroidThreadTimeInStateMetric.Process
                 * @instance
                 */
                Process.prototype.metricsByCoreType = $util.emptyArray;

                /**
                 * Process threads.
                 * @member {Array.<perfetto.protos.AndroidThreadTimeInStateMetric.IThread>} threads
                 * @memberof perfetto.protos.AndroidThreadTimeInStateMetric.Process
                 * @instance
                 */
                Process.prototype.threads = $util.emptyArray;

                /**
                 * Creates a new Process instance using the specified properties.
                 * @function create
                 * @memberof perfetto.protos.AndroidThreadTimeInStateMetric.Process
                 * @static
                 * @param {perfetto.protos.AndroidThreadTimeInStateMetric.IProcess=} [properties] Properties to set
                 * @returns {perfetto.protos.AndroidThreadTimeInStateMetric.Process} Process instance
                 */
                Process.create = function create(properties) {
                    return new Process(properties);
                };

                /**
                 * Encodes the specified Process message. Does not implicitly {@link perfetto.protos.AndroidThreadTimeInStateMetric.Process.verify|verify} messages.
                 * @function encode
                 * @memberof perfetto.protos.AndroidThreadTimeInStateMetric.Process
                 * @static
                 * @param {perfetto.protos.AndroidThreadTimeInStateMetric.IProcess} message Process message or plain object to encode
                 * @param {$protobuf.Writer} [writer] Writer to encode to
                 * @returns {$protobuf.Writer} Writer
                 */
                Process.encode = function encode(message, writer) {
                    if (!writer)
                        writer = $Writer.create();
                    if (message.metadata != null && Object.hasOwnProperty.call(message, "metadata"))
                        $root.perfetto.protos.AndroidProcessMetadata.encode(message.metadata, writer.uint32(/* id 1, wireType 2 =*/10).fork()).ldelim();
                    if (message.metricsByCoreType != null && message.metricsByCoreType.length)
                        for (var i = 0; i < message.metricsByCoreType.length; ++i)
                            $root.perfetto.protos.AndroidThreadTimeInStateMetric.MetricsByCoreType.encode(message.metricsByCoreType[i], writer.uint32(/* id 2, wireType 2 =*/18).fork()).ldelim();
                    if (message.threads != null && message.threads.length)
                        for (var i = 0; i < message.threads.length; ++i)
                            $root.perfetto.protos.AndroidThreadTimeInStateMetric.Thread.encode(message.threads[i], writer.uint32(/* id 3, wireType 2 =*/26).fork()).ldelim();
                    return writer;
                };

                /**
                 * Encodes the specified Process message, length delimited. Does not implicitly {@link perfetto.protos.AndroidThreadTimeInStateMetric.Process.verify|verify} messages.
                 * @function encodeDelimited
                 * @memberof perfetto.protos.AndroidThreadTimeInStateMetric.Process
                 * @static
                 * @param {perfetto.protos.AndroidThreadTimeInStateMetric.IProcess} message Process message or plain object to encode
                 * @param {$protobuf.Writer} [writer] Writer to encode to
                 * @returns {$protobuf.Writer} Writer
                 */
                Process.encodeDelimited = function encodeDelimited(message, writer) {
                    return this.encode(message, writer).ldelim();
                };

                /**
                 * Decodes a Process message from the specified reader or buffer.
                 * @function decode
                 * @memberof perfetto.protos.AndroidThreadTimeInStateMetric.Process
                 * @static
                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                 * @param {number} [length] Message length if known beforehand
                 * @returns {perfetto.protos.AndroidThreadTimeInStateMetric.Process} Process
                 * @throws {Error} If the payload is not a reader or valid buffer
                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
                 */
                Process.decode = function decode(reader, length) {
                    if (!(reader instanceof $Reader))
                        reader = $Reader.create(reader);
                    var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.AndroidThreadTimeInStateMetric.Process();
                    while (reader.pos < end) {
                        var tag = reader.uint32();
                        switch (tag >>> 3) {
                        case 1:
                            message.metadata = $root.perfetto.protos.AndroidProcessMetadata.decode(reader, reader.uint32());
                            break;
                        case 2:
                            if (!(message.metricsByCoreType && message.metricsByCoreType.length))
                                message.metricsByCoreType = [];
                            message.metricsByCoreType.push($root.perfetto.protos.AndroidThreadTimeInStateMetric.MetricsByCoreType.decode(reader, reader.uint32()));
                            break;
                        case 3:
                            if (!(message.threads && message.threads.length))
                                message.threads = [];
                            message.threads.push($root.perfetto.protos.AndroidThreadTimeInStateMetric.Thread.decode(reader, reader.uint32()));
                            break;
                        default:
                            reader.skipType(tag & 7);
                            break;
                        }
                    }
                    return message;
                };

                /**
                 * Decodes a Process message from the specified reader or buffer, length delimited.
                 * @function decodeDelimited
                 * @memberof perfetto.protos.AndroidThreadTimeInStateMetric.Process
                 * @static
                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                 * @returns {perfetto.protos.AndroidThreadTimeInStateMetric.Process} Process
                 * @throws {Error} If the payload is not a reader or valid buffer
                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
                 */
                Process.decodeDelimited = function decodeDelimited(reader) {
                    if (!(reader instanceof $Reader))
                        reader = new $Reader(reader);
                    return this.decode(reader, reader.uint32());
                };

                /**
                 * Verifies a Process message.
                 * @function verify
                 * @memberof perfetto.protos.AndroidThreadTimeInStateMetric.Process
                 * @static
                 * @param {Object.<string,*>} message Plain object to verify
                 * @returns {string|null} `null` if valid, otherwise the reason why it is not
                 */
                Process.verify = function verify(message) {
                    if (typeof message !== "object" || message === null)
                        return "object expected";
                    if (message.metadata != null && message.hasOwnProperty("metadata")) {
                        var error = $root.perfetto.protos.AndroidProcessMetadata.verify(message.metadata);
                        if (error)
                            return "metadata." + error;
                    }
                    if (message.metricsByCoreType != null && message.hasOwnProperty("metricsByCoreType")) {
                        if (!Array.isArray(message.metricsByCoreType))
                            return "metricsByCoreType: array expected";
                        for (var i = 0; i < message.metricsByCoreType.length; ++i) {
                            var error = $root.perfetto.protos.AndroidThreadTimeInStateMetric.MetricsByCoreType.verify(message.metricsByCoreType[i]);
                            if (error)
                                return "metricsByCoreType." + error;
                        }
                    }
                    if (message.threads != null && message.hasOwnProperty("threads")) {
                        if (!Array.isArray(message.threads))
                            return "threads: array expected";
                        for (var i = 0; i < message.threads.length; ++i) {
                            var error = $root.perfetto.protos.AndroidThreadTimeInStateMetric.Thread.verify(message.threads[i]);
                            if (error)
                                return "threads." + error;
                        }
                    }
                    return null;
                };

                /**
                 * Creates a Process message from a plain object. Also converts values to their respective internal types.
                 * @function fromObject
                 * @memberof perfetto.protos.AndroidThreadTimeInStateMetric.Process
                 * @static
                 * @param {Object.<string,*>} object Plain object
                 * @returns {perfetto.protos.AndroidThreadTimeInStateMetric.Process} Process
                 */
                Process.fromObject = function fromObject(object) {
                    if (object instanceof $root.perfetto.protos.AndroidThreadTimeInStateMetric.Process)
                        return object;
                    var message = new $root.perfetto.protos.AndroidThreadTimeInStateMetric.Process();
                    if (object.metadata != null) {
                        if (typeof object.metadata !== "object")
                            throw TypeError(".perfetto.protos.AndroidThreadTimeInStateMetric.Process.metadata: object expected");
                        message.metadata = $root.perfetto.protos.AndroidProcessMetadata.fromObject(object.metadata);
                    }
                    if (object.metricsByCoreType) {
                        if (!Array.isArray(object.metricsByCoreType))
                            throw TypeError(".perfetto.protos.AndroidThreadTimeInStateMetric.Process.metricsByCoreType: array expected");
                        message.metricsByCoreType = [];
                        for (var i = 0; i < object.metricsByCoreType.length; ++i) {
                            if (typeof object.metricsByCoreType[i] !== "object")
                                throw TypeError(".perfetto.protos.AndroidThreadTimeInStateMetric.Process.metricsByCoreType: object expected");
                            message.metricsByCoreType[i] = $root.perfetto.protos.AndroidThreadTimeInStateMetric.MetricsByCoreType.fromObject(object.metricsByCoreType[i]);
                        }
                    }
                    if (object.threads) {
                        if (!Array.isArray(object.threads))
                            throw TypeError(".perfetto.protos.AndroidThreadTimeInStateMetric.Process.threads: array expected");
                        message.threads = [];
                        for (var i = 0; i < object.threads.length; ++i) {
                            if (typeof object.threads[i] !== "object")
                                throw TypeError(".perfetto.protos.AndroidThreadTimeInStateMetric.Process.threads: object expected");
                            message.threads[i] = $root.perfetto.protos.AndroidThreadTimeInStateMetric.Thread.fromObject(object.threads[i]);
                        }
                    }
                    return message;
                };

                /**
                 * Creates a plain object from a Process message. Also converts values to other types if specified.
                 * @function toObject
                 * @memberof perfetto.protos.AndroidThreadTimeInStateMetric.Process
                 * @static
                 * @param {perfetto.protos.AndroidThreadTimeInStateMetric.Process} message Process
                 * @param {$protobuf.IConversionOptions} [options] Conversion options
                 * @returns {Object.<string,*>} Plain object
                 */
                Process.toObject = function toObject(message, options) {
                    if (!options)
                        options = {};
                    var object = {};
                    if (options.arrays || options.defaults) {
                        object.metricsByCoreType = [];
                        object.threads = [];
                    }
                    if (options.defaults)
                        object.metadata = null;
                    if (message.metadata != null && message.hasOwnProperty("metadata"))
                        object.metadata = $root.perfetto.protos.AndroidProcessMetadata.toObject(message.metadata, options);
                    if (message.metricsByCoreType && message.metricsByCoreType.length) {
                        object.metricsByCoreType = [];
                        for (var j = 0; j < message.metricsByCoreType.length; ++j)
                            object.metricsByCoreType[j] = $root.perfetto.protos.AndroidThreadTimeInStateMetric.MetricsByCoreType.toObject(message.metricsByCoreType[j], options);
                    }
                    if (message.threads && message.threads.length) {
                        object.threads = [];
                        for (var j = 0; j < message.threads.length; ++j)
                            object.threads[j] = $root.perfetto.protos.AndroidThreadTimeInStateMetric.Thread.toObject(message.threads[j], options);
                    }
                    return object;
                };

                /**
                 * Converts this Process to JSON.
                 * @function toJSON
                 * @memberof perfetto.protos.AndroidThreadTimeInStateMetric.Process
                 * @instance
                 * @returns {Object.<string,*>} JSON object
                 */
                Process.prototype.toJSON = function toJSON() {
                    return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
                };

                return Process;
            })();

            return AndroidThreadTimeInStateMetric;
        })();

        protos.UnsymbolizedFrames = (function() {

            /**
             * Properties of an UnsymbolizedFrames.
             * @memberof perfetto.protos
             * @interface IUnsymbolizedFrames
             * @property {Array.<perfetto.protos.UnsymbolizedFrames.IFrame>|null} [frames] UnsymbolizedFrames frames
             */

            /**
             * Constructs a new UnsymbolizedFrames.
             * @memberof perfetto.protos
             * @classdesc Represents an UnsymbolizedFrames.
             * @implements IUnsymbolizedFrames
             * @constructor
             * @param {perfetto.protos.IUnsymbolizedFrames=} [properties] Properties to set
             */
            function UnsymbolizedFrames(properties) {
                this.frames = [];
                if (properties)
                    for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                        if (properties[keys[i]] != null)
                            this[keys[i]] = properties[keys[i]];
            }

            /**
             * UnsymbolizedFrames frames.
             * @member {Array.<perfetto.protos.UnsymbolizedFrames.IFrame>} frames
             * @memberof perfetto.protos.UnsymbolizedFrames
             * @instance
             */
            UnsymbolizedFrames.prototype.frames = $util.emptyArray;

            /**
             * Creates a new UnsymbolizedFrames instance using the specified properties.
             * @function create
             * @memberof perfetto.protos.UnsymbolizedFrames
             * @static
             * @param {perfetto.protos.IUnsymbolizedFrames=} [properties] Properties to set
             * @returns {perfetto.protos.UnsymbolizedFrames} UnsymbolizedFrames instance
             */
            UnsymbolizedFrames.create = function create(properties) {
                return new UnsymbolizedFrames(properties);
            };

            /**
             * Encodes the specified UnsymbolizedFrames message. Does not implicitly {@link perfetto.protos.UnsymbolizedFrames.verify|verify} messages.
             * @function encode
             * @memberof perfetto.protos.UnsymbolizedFrames
             * @static
             * @param {perfetto.protos.IUnsymbolizedFrames} message UnsymbolizedFrames message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            UnsymbolizedFrames.encode = function encode(message, writer) {
                if (!writer)
                    writer = $Writer.create();
                if (message.frames != null && message.frames.length)
                    for (var i = 0; i < message.frames.length; ++i)
                        $root.perfetto.protos.UnsymbolizedFrames.Frame.encode(message.frames[i], writer.uint32(/* id 1, wireType 2 =*/10).fork()).ldelim();
                return writer;
            };

            /**
             * Encodes the specified UnsymbolizedFrames message, length delimited. Does not implicitly {@link perfetto.protos.UnsymbolizedFrames.verify|verify} messages.
             * @function encodeDelimited
             * @memberof perfetto.protos.UnsymbolizedFrames
             * @static
             * @param {perfetto.protos.IUnsymbolizedFrames} message UnsymbolizedFrames message or plain object to encode
             * @param {$protobuf.Writer} [writer] Writer to encode to
             * @returns {$protobuf.Writer} Writer
             */
            UnsymbolizedFrames.encodeDelimited = function encodeDelimited(message, writer) {
                return this.encode(message, writer).ldelim();
            };

            /**
             * Decodes an UnsymbolizedFrames message from the specified reader or buffer.
             * @function decode
             * @memberof perfetto.protos.UnsymbolizedFrames
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @param {number} [length] Message length if known beforehand
             * @returns {perfetto.protos.UnsymbolizedFrames} UnsymbolizedFrames
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            UnsymbolizedFrames.decode = function decode(reader, length) {
                if (!(reader instanceof $Reader))
                    reader = $Reader.create(reader);
                var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.UnsymbolizedFrames();
                while (reader.pos < end) {
                    var tag = reader.uint32();
                    switch (tag >>> 3) {
                    case 1:
                        if (!(message.frames && message.frames.length))
                            message.frames = [];
                        message.frames.push($root.perfetto.protos.UnsymbolizedFrames.Frame.decode(reader, reader.uint32()));
                        break;
                    default:
                        reader.skipType(tag & 7);
                        break;
                    }
                }
                return message;
            };

            /**
             * Decodes an UnsymbolizedFrames message from the specified reader or buffer, length delimited.
             * @function decodeDelimited
             * @memberof perfetto.protos.UnsymbolizedFrames
             * @static
             * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
             * @returns {perfetto.protos.UnsymbolizedFrames} UnsymbolizedFrames
             * @throws {Error} If the payload is not a reader or valid buffer
             * @throws {$protobuf.util.ProtocolError} If required fields are missing
             */
            UnsymbolizedFrames.decodeDelimited = function decodeDelimited(reader) {
                if (!(reader instanceof $Reader))
                    reader = new $Reader(reader);
                return this.decode(reader, reader.uint32());
            };

            /**
             * Verifies an UnsymbolizedFrames message.
             * @function verify
             * @memberof perfetto.protos.UnsymbolizedFrames
             * @static
             * @param {Object.<string,*>} message Plain object to verify
             * @returns {string|null} `null` if valid, otherwise the reason why it is not
             */
            UnsymbolizedFrames.verify = function verify(message) {
                if (typeof message !== "object" || message === null)
                    return "object expected";
                if (message.frames != null && message.hasOwnProperty("frames")) {
                    if (!Array.isArray(message.frames))
                        return "frames: array expected";
                    for (var i = 0; i < message.frames.length; ++i) {
                        var error = $root.perfetto.protos.UnsymbolizedFrames.Frame.verify(message.frames[i]);
                        if (error)
                            return "frames." + error;
                    }
                }
                return null;
            };

            /**
             * Creates an UnsymbolizedFrames message from a plain object. Also converts values to their respective internal types.
             * @function fromObject
             * @memberof perfetto.protos.UnsymbolizedFrames
             * @static
             * @param {Object.<string,*>} object Plain object
             * @returns {perfetto.protos.UnsymbolizedFrames} UnsymbolizedFrames
             */
            UnsymbolizedFrames.fromObject = function fromObject(object) {
                if (object instanceof $root.perfetto.protos.UnsymbolizedFrames)
                    return object;
                var message = new $root.perfetto.protos.UnsymbolizedFrames();
                if (object.frames) {
                    if (!Array.isArray(object.frames))
                        throw TypeError(".perfetto.protos.UnsymbolizedFrames.frames: array expected");
                    message.frames = [];
                    for (var i = 0; i < object.frames.length; ++i) {
                        if (typeof object.frames[i] !== "object")
                            throw TypeError(".perfetto.protos.UnsymbolizedFrames.frames: object expected");
                        message.frames[i] = $root.perfetto.protos.UnsymbolizedFrames.Frame.fromObject(object.frames[i]);
                    }
                }
                return message;
            };

            /**
             * Creates a plain object from an UnsymbolizedFrames message. Also converts values to other types if specified.
             * @function toObject
             * @memberof perfetto.protos.UnsymbolizedFrames
             * @static
             * @param {perfetto.protos.UnsymbolizedFrames} message UnsymbolizedFrames
             * @param {$protobuf.IConversionOptions} [options] Conversion options
             * @returns {Object.<string,*>} Plain object
             */
            UnsymbolizedFrames.toObject = function toObject(message, options) {
                if (!options)
                    options = {};
                var object = {};
                if (options.arrays || options.defaults)
                    object.frames = [];
                if (message.frames && message.frames.length) {
                    object.frames = [];
                    for (var j = 0; j < message.frames.length; ++j)
                        object.frames[j] = $root.perfetto.protos.UnsymbolizedFrames.Frame.toObject(message.frames[j], options);
                }
                return object;
            };

            /**
             * Converts this UnsymbolizedFrames to JSON.
             * @function toJSON
             * @memberof perfetto.protos.UnsymbolizedFrames
             * @instance
             * @returns {Object.<string,*>} JSON object
             */
            UnsymbolizedFrames.prototype.toJSON = function toJSON() {
                return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
            };

            UnsymbolizedFrames.Frame = (function() {

                /**
                 * Properties of a Frame.
                 * @memberof perfetto.protos.UnsymbolizedFrames
                 * @interface IFrame
                 * @property {string|null} [module] Frame module
                 * @property {string|null} [buildId] Frame buildId
                 * @property {number|null} [address] Frame address
                 */

                /**
                 * Constructs a new Frame.
                 * @memberof perfetto.protos.UnsymbolizedFrames
                 * @classdesc Represents a Frame.
                 * @implements IFrame
                 * @constructor
                 * @param {perfetto.protos.UnsymbolizedFrames.IFrame=} [properties] Properties to set
                 */
                function Frame(properties) {
                    if (properties)
                        for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                            if (properties[keys[i]] != null)
                                this[keys[i]] = properties[keys[i]];
                }

                /**
                 * Frame module.
                 * @member {string} module
                 * @memberof perfetto.protos.UnsymbolizedFrames.Frame
                 * @instance
                 */
                Frame.prototype.module = "";

                /**
                 * Frame buildId.
                 * @member {string} buildId
                 * @memberof perfetto.protos.UnsymbolizedFrames.Frame
                 * @instance
                 */
                Frame.prototype.buildId = "";

                /**
                 * Frame address.
                 * @member {number} address
                 * @memberof perfetto.protos.UnsymbolizedFrames.Frame
                 * @instance
                 */
                Frame.prototype.address = $util.Long ? $util.Long.fromBits(0,0,false) : 0;

                /**
                 * Creates a new Frame instance using the specified properties.
                 * @function create
                 * @memberof perfetto.protos.UnsymbolizedFrames.Frame
                 * @static
                 * @param {perfetto.protos.UnsymbolizedFrames.IFrame=} [properties] Properties to set
                 * @returns {perfetto.protos.UnsymbolizedFrames.Frame} Frame instance
                 */
                Frame.create = function create(properties) {
                    return new Frame(properties);
                };

                /**
                 * Encodes the specified Frame message. Does not implicitly {@link perfetto.protos.UnsymbolizedFrames.Frame.verify|verify} messages.
                 * @function encode
                 * @memberof perfetto.protos.UnsymbolizedFrames.Frame
                 * @static
                 * @param {perfetto.protos.UnsymbolizedFrames.IFrame} message Frame message or plain object to encode
                 * @param {$protobuf.Writer} [writer] Writer to encode to
                 * @returns {$protobuf.Writer} Writer
                 */
                Frame.encode = function encode(message, writer) {
                    if (!writer)
                        writer = $Writer.create();
                    if (message.module != null && Object.hasOwnProperty.call(message, "module"))
                        writer.uint32(/* id 1, wireType 2 =*/10).string(message.module);
                    if (message.buildId != null && Object.hasOwnProperty.call(message, "buildId"))
                        writer.uint32(/* id 2, wireType 2 =*/18).string(message.buildId);
                    if (message.address != null && Object.hasOwnProperty.call(message, "address"))
                        writer.uint32(/* id 3, wireType 0 =*/24).int64(message.address);
                    return writer;
                };

                /**
                 * Encodes the specified Frame message, length delimited. Does not implicitly {@link perfetto.protos.UnsymbolizedFrames.Frame.verify|verify} messages.
                 * @function encodeDelimited
                 * @memberof perfetto.protos.UnsymbolizedFrames.Frame
                 * @static
                 * @param {perfetto.protos.UnsymbolizedFrames.IFrame} message Frame message or plain object to encode
                 * @param {$protobuf.Writer} [writer] Writer to encode to
                 * @returns {$protobuf.Writer} Writer
                 */
                Frame.encodeDelimited = function encodeDelimited(message, writer) {
                    return this.encode(message, writer).ldelim();
                };

                /**
                 * Decodes a Frame message from the specified reader or buffer.
                 * @function decode
                 * @memberof perfetto.protos.UnsymbolizedFrames.Frame
                 * @static
                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                 * @param {number} [length] Message length if known beforehand
                 * @returns {perfetto.protos.UnsymbolizedFrames.Frame} Frame
                 * @throws {Error} If the payload is not a reader or valid buffer
                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
                 */
                Frame.decode = function decode(reader, length) {
                    if (!(reader instanceof $Reader))
                        reader = $Reader.create(reader);
                    var end = length === undefined ? reader.len : reader.pos + length, message = new $root.perfetto.protos.UnsymbolizedFrames.Frame();
                    while (reader.pos < end) {
                        var tag = reader.uint32();
                        switch (tag >>> 3) {
                        case 1:
                            message.module = reader.string();
                            break;
                        case 2:
                            message.buildId = reader.string();
                            break;
                        case 3:
                            message.address = reader.int64();
                            break;
                        default:
                            reader.skipType(tag & 7);
                            break;
                        }
                    }
                    return message;
                };

                /**
                 * Decodes a Frame message from the specified reader or buffer, length delimited.
                 * @function decodeDelimited
                 * @memberof perfetto.protos.UnsymbolizedFrames.Frame
                 * @static
                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
                 * @returns {perfetto.protos.UnsymbolizedFrames.Frame} Frame
                 * @throws {Error} If the payload is not a reader or valid buffer
                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
                 */
                Frame.decodeDelimited = function decodeDelimited(reader) {
                    if (!(reader instanceof $Reader))
                        reader = new $Reader(reader);
                    return this.decode(reader, reader.uint32());
                };

                /**
                 * Verifies a Frame message.
                 * @function verify
                 * @memberof perfetto.protos.UnsymbolizedFrames.Frame
                 * @static
                 * @param {Object.<string,*>} message Plain object to verify
                 * @returns {string|null} `null` if valid, otherwise the reason why it is not
                 */
                Frame.verify = function verify(message) {
                    if (typeof message !== "object" || message === null)
                        return "object expected";
                    if (message.module != null && message.hasOwnProperty("module"))
                        if (!$util.isString(message.module))
                            return "module: string expected";
                    if (message.buildId != null && message.hasOwnProperty("buildId"))
                        if (!$util.isString(message.buildId))
                            return "buildId: string expected";
                    if (message.address != null && message.hasOwnProperty("address"))
                        if (!$util.isInteger(message.address) && !(message.address && $util.isInteger(message.address.low) && $util.isInteger(message.address.high)))
                            return "address: integer|Long expected";
                    return null;
                };

                /**
                 * Creates a Frame message from a plain object. Also converts values to their respective internal types.
                 * @function fromObject
                 * @memberof perfetto.protos.UnsymbolizedFrames.Frame
                 * @static
                 * @param {Object.<string,*>} object Plain object
                 * @returns {perfetto.protos.UnsymbolizedFrames.Frame} Frame
                 */
                Frame.fromObject = function fromObject(object) {
                    if (object instanceof $root.perfetto.protos.UnsymbolizedFrames.Frame)
                        return object;
                    var message = new $root.perfetto.protos.UnsymbolizedFrames.Frame();
                    if (object.module != null)
                        message.module = String(object.module);
                    if (object.buildId != null)
                        message.buildId = String(object.buildId);
                    if (object.address != null)
                        if ($util.Long)
                            (message.address = $util.Long.fromValue(object.address)).unsigned = false;
                        else if (typeof object.address === "string")
                            message.address = parseInt(object.address, 10);
                        else if (typeof object.address === "number")
                            message.address = object.address;
                        else if (typeof object.address === "object")
                            message.address = new $util.LongBits(object.address.low >>> 0, object.address.high >>> 0).toNumber();
                    return message;
                };

                /**
                 * Creates a plain object from a Frame message. Also converts values to other types if specified.
                 * @function toObject
                 * @memberof perfetto.protos.UnsymbolizedFrames.Frame
                 * @static
                 * @param {perfetto.protos.UnsymbolizedFrames.Frame} message Frame
                 * @param {$protobuf.IConversionOptions} [options] Conversion options
                 * @returns {Object.<string,*>} Plain object
                 */
                Frame.toObject = function toObject(message, options) {
                    if (!options)
                        options = {};
                    var object = {};
                    if (options.defaults) {
                        object.module = "";
                        object.buildId = "";
                        if ($util.Long) {
                            var long = new $util.Long(0, 0, false);
                            object.address = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
                        } else
                            object.address = options.longs === String ? "0" : 0;
                    }
                    if (message.module != null && message.hasOwnProperty("module"))
                        object.module = message.module;
                    if (message.buildId != null && message.hasOwnProperty("buildId"))
                        object.buildId = message.buildId;
                    if (message.address != null && message.hasOwnProperty("address"))
                        if (typeof message.address === "number")
                            object.address = options.longs === String ? String(message.address) : message.address;
                        else
                            object.address = options.longs === String ? $util.Long.prototype.toString.call(message.address) : options.longs === Number ? new $util.LongBits(message.address.low >>> 0, message.address.high >>> 0).toNumber() : message.address;
                    return object;
                };

                /**
                 * Converts this Frame to JSON.
                 * @function toJSON
                 * @memberof perfetto.protos.UnsymbolizedFrames.Frame
                 * @instance
                 * @returns {Object.<string,*>} JSON object
                 */
                Frame.prototype.toJSON = function toJSON() {
                    return this.constructor.toObject(this, minimal$1.util.toJSONOptions);
                };

                return Frame;
            })();

            return UnsymbolizedFrames;
        })();

        return protos;
    })();

    return perfetto;
})();

var protos = $root;

var query_iterator = createCommonjsModule(function (module, exports) {
// Copyright (C) 2020 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.
Object.defineProperty(exports, "__esModule", { value: true });
exports.singleRowUntyped = exports.singleRow = exports.slowlyCountRows = exports.iter = exports.iterUntyped = exports.findColumnIndex = exports.STR_NULL = exports.NUM_NULL = exports.STR = exports.NUM = void 0;

exports.NUM = 0;
exports.STR = 'str';
exports.NUM_NULL = 1;
exports.STR_NULL = 'str_null';
// Exported for testing
function findColumnIndex(result, name, columnType) {
    let matchingDescriptorIndex = -1;
    const disallowNulls = columnType === exports.STR || columnType === exports.NUM;
    const expectsStrings = columnType === exports.STR || columnType === exports.STR_NULL;
    const expectsNumbers = columnType === exports.NUM || columnType === exports.NUM_NULL;
    const isEmpty = +result.numRecords === 0;
    for (let i = 0; i < result.columnDescriptors.length; ++i) {
        const descriptor = result.columnDescriptors[i];
        const column = result.columns[i];
        if (descriptor.name !== name) {
            continue;
        }
        const hasDoubles = column.doubleValues && column.doubleValues.length;
        const hasLongs = column.longValues && column.longValues.length;
        const hasStrings = column.stringValues && column.stringValues.length;
        if (matchingDescriptorIndex !== -1) {
            throw new Error(`Multiple columns with the name ${name}`);
        }
        if (expectsStrings && !hasStrings && !isEmpty) {
            throw new Error(`Expected strings for column ${name} but found numbers`);
        }
        if (expectsNumbers && !hasDoubles && !hasLongs && !isEmpty) {
            throw new Error(`Expected numbers for column ${name} but found strings`);
        }
        if (disallowNulls) {
            for (let j = 0; j < +result.numRecords; ++j) {
                if (column.isNulls[j] === true) {
                    throw new Error(`Column ${name} contains nulls`);
                }
            }
        }
        matchingDescriptorIndex = i;
    }
    if (matchingDescriptorIndex === -1) {
        throw new Error(`No column with name ${name} found in result.`);
    }
    return matchingDescriptorIndex;
}
exports.findColumnIndex = findColumnIndex;
class ColumnarRowIterator {
    constructor(querySpec, queryResult) {
        const row = querySpec;
        this.row = row;
        this.i_ = 0;
        this.rowCount_ = +queryResult.numRecords;
        this.columnCount_ = 0;
        this.columnNames_ = [];
        this.columns_ = [];
        this.nullColumns_ = [];
        for (const [columnName, columnType] of Object.entries(querySpec)) {
            const index = findColumnIndex(queryResult, columnName, columnType);
            const column = queryResult.columns[index];
            this.columnCount_++;
            this.columnNames_.push(columnName);
            let values = [];
            const isNum = columnType === exports.NUM || columnType === exports.NUM_NULL;
            const isString = columnType === exports.STR || columnType === exports.STR_NULL;
            if (isNum && column.longValues &&
                column.longValues.length === this.rowCount_) {
                values = column.longValues;
            }
            if (isNum && column.doubleValues &&
                column.doubleValues.length === this.rowCount_) {
                values = column.doubleValues;
            }
            if (isString && column.stringValues &&
                column.stringValues.length === this.rowCount_) {
                values = column.stringValues;
            }
            this.columns_.push(values);
            this.nullColumns_.push(column.isNulls);
        }
        if (this.rowCount_ > 0) {
            for (let j = 0; j < this.columnCount_; ++j) {
                const name = this.columnNames_[j];
                const isNull = this.nullColumns_[j][this.i_];
                this.row[name] = isNull ? null : this.columns_[j][this.i_];
            }
        }
    }
    valid() {
        return this.i_ < this.rowCount_;
    }
    next() {
        this.i_++;
        for (let j = 0; j < this.columnCount_; ++j) {
            const name = this.columnNames_[j];
            const isNull = this.nullColumns_[j][this.i_];
            this.row[name] = isNull ? null : this.columns_[j][this.i_];
        }
    }
}
// Deliberately not exported, use iter() below to make code easy to switch
// to other queryResult formats.
function iterFromColumns(querySpec, queryResult) {
    const iter = new ColumnarRowIterator(querySpec, queryResult);
    return iter;
}
// Deliberately not exported, use iterUntyped() below to make code easy to
// switch to other queryResult formats.
function iterUntypedFromColumns(result) {
    const spec = {};
    const desc = result.columnDescriptors;
    for (let i = 0; i < desc.length; ++i) {
        const name = desc[i].name;
        if (!name) {
            continue;
        }
        spec[name] = desc[i].type === 3 ? exports.STR_NULL : exports.NUM_NULL;
    }
    const iter = new ColumnarRowIterator(spec, result);
    return iter;
}
function isColumnarQueryResult(result) {
    return result.columnDescriptors !== undefined;
}
function iterUntyped(result) {
    if (isColumnarQueryResult(result)) {
        return iterUntypedFromColumns(result);
    }
    else {
        throw new Error('Unsuported format');
    }
}
exports.iterUntyped = iterUntyped;
function iter(spec, result) {
    if (isColumnarQueryResult(result)) {
        return iterFromColumns(spec, result);
    }
    else {
        throw new Error('Unsuported format');
    }
}
exports.iter = iter;
function slowlyCountRows(result) {
    if (isColumnarQueryResult(result)) {
        // This isn't actually slow for columnar data but it might be for other
        // formats.
        return +result.numRecords;
    }
    else {
        throw new Error('Unsuported format');
    }
}
exports.slowlyCountRows = slowlyCountRows;
function singleRow(spec, result) {
    const numRows = slowlyCountRows(result);
    if (numRows === 0) {
        return undefined;
    }
    if (numRows > 1) {
        throw new Error(`Attempted to extract single row but more than ${numRows} rows found.`);
    }
    const it = iter(spec, result);
    logging.assertTrue(it.valid());
    return it.row;
}
exports.singleRow = singleRow;
function singleRowUntyped(result) {
    const numRows = slowlyCountRows(result);
    if (numRows === 0) {
        return undefined;
    }
    if (numRows > 1) {
        throw new Error(`Attempted to extract single row but more than ${numRows} rows found.`);
    }
    const it = iterUntyped(result);
    logging.assertTrue(it.valid());
    return it.row;
}
exports.singleRowUntyped = singleRowUntyped;

});

var protos_1 = createCommonjsModule(function (module, exports) {
// 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.
Object.defineProperty(exports, "__esModule", { value: true });
exports.VmstatCounters = exports.TraceConfig = exports.SysStatsConfig = exports.StatusResult = exports.StatCounters = exports.RawQueryResult = exports.RawQueryArgs = exports.ProcessStatsConfig = exports.NativeContinuousDumpConfig = exports.MeminfoCounters = exports.JavaHprofConfig = exports.JavaContinuousDumpConfig = exports.HeapprofdConfig = exports.FtraceConfig = exports.DataSourceConfig = exports.ComputeMetricResult = exports.ComputeMetricArgs = exports.ConsumerPort = exports.ChromeConfig = exports.BufferConfig = exports.BatteryCounters = exports.AndroidPowerConfig = exports.AndroidLogId = exports.AndroidLogConfig = exports.rawQueryResultIter = exports.rawQueryResultColumns = void 0;


// Aliases protos to avoid the super nested namespaces.
// See https://www.typescriptlang.org/docs/handbook/namespaces.html#aliases
var AndroidLogConfig = protos.perfetto.protos.AndroidLogConfig;
exports.AndroidLogConfig = AndroidLogConfig;
var AndroidPowerConfig = protos.perfetto.protos.AndroidPowerConfig;
exports.AndroidPowerConfig = AndroidPowerConfig;
var AndroidLogId = protos.perfetto.protos.AndroidLogId;
exports.AndroidLogId = AndroidLogId;
var BatteryCounters = protos.perfetto.protos.AndroidPowerConfig.BatteryCounters;
exports.BatteryCounters = BatteryCounters;
var BufferConfig = protos.perfetto.protos.TraceConfig.BufferConfig;
exports.BufferConfig = BufferConfig;
var ChromeConfig = protos.perfetto.protos.ChromeConfig;
exports.ChromeConfig = ChromeConfig;
var ConsumerPort = protos.perfetto.protos.ConsumerPort;
exports.ConsumerPort = ConsumerPort;
var NativeContinuousDumpConfig = protos.perfetto.protos.HeapprofdConfig.ContinuousDumpConfig;
exports.NativeContinuousDumpConfig = NativeContinuousDumpConfig;
var JavaContinuousDumpConfig = protos.perfetto.protos.JavaHprofConfig.ContinuousDumpConfig;
exports.JavaContinuousDumpConfig = JavaContinuousDumpConfig;
var DataSourceConfig = protos.perfetto.protos.DataSourceConfig;
exports.DataSourceConfig = DataSourceConfig;
var FtraceConfig = protos.perfetto.protos.FtraceConfig;
exports.FtraceConfig = FtraceConfig;
var HeapprofdConfig = protos.perfetto.protos.HeapprofdConfig;
exports.HeapprofdConfig = HeapprofdConfig;
var JavaHprofConfig = protos.perfetto.protos.JavaHprofConfig;
exports.JavaHprofConfig = JavaHprofConfig;
var MeminfoCounters = protos.perfetto.protos.MeminfoCounters;
exports.MeminfoCounters = MeminfoCounters;
var ProcessStatsConfig = protos.perfetto.protos.ProcessStatsConfig;
exports.ProcessStatsConfig = ProcessStatsConfig;
var StatCounters = protos.perfetto.protos.SysStatsConfig.StatCounters;
exports.StatCounters = StatCounters;
var SysStatsConfig = protos.perfetto.protos.SysStatsConfig;
exports.SysStatsConfig = SysStatsConfig;
var TraceConfig = protos.perfetto.protos.TraceConfig;
exports.TraceConfig = TraceConfig;
var VmstatCounters = protos.perfetto.protos.VmstatCounters;
exports.VmstatCounters = VmstatCounters;
var RawQueryArgs = protos.perfetto.protos.RawQueryArgs;
exports.RawQueryArgs = RawQueryArgs;
var RawQueryResult = protos.perfetto.protos.RawQueryResult;
exports.RawQueryResult = RawQueryResult;
var StatusResult = protos.perfetto.protos.StatusResult;
exports.StatusResult = StatusResult;
var ComputeMetricArgs = protos.perfetto.protos.ComputeMetricArgs;
exports.ComputeMetricArgs = ComputeMetricArgs;
var ComputeMetricResult = protos.perfetto.protos.ComputeMetricResult;
exports.ComputeMetricResult = ComputeMetricResult;
const COLUMN_TYPE_STR = RawQueryResult.ColumnDesc.Type.STRING;
const COLUMN_TYPE_DOUBLE = RawQueryResult.ColumnDesc.Type.DOUBLE;
const COLUMN_TYPE_LONG = RawQueryResult.ColumnDesc.Type.LONG;
function getCell(result, column, row) {
    const values = result.columns[column];
    if (values.isNulls[row])
        return null;
    switch (result.columnDescriptors[column].type) {
        case COLUMN_TYPE_LONG:
            return +values.longValues[row];
        case COLUMN_TYPE_DOUBLE:
            return +values.doubleValues[row];
        case COLUMN_TYPE_STR:
            return values.stringValues[row];
        default:
            throw new Error('Unhandled type!');
    }
}
function rawQueryResultColumns(result) {
    // Two columns can conflict on the same name, e.g.
    // select x.foo, y.foo from x join y. In that case store them using the
    // full table.column notation.
    const res = [];
    const uniqColNames = new Set();
    const colNamesToDedupe = new Set();
    for (const col of result.columnDescriptors) {
        const colName = col.name || '';
        if (uniqColNames.has(colName)) {
            colNamesToDedupe.add(colName);
        }
        uniqColNames.add(colName);
    }
    for (let i = 0; i < result.columnDescriptors.length; i++) {
        const colName = result.columnDescriptors[i].name || '';
        if (colNamesToDedupe.has(colName)) {
            res.push(`${colName}.${i + 1}`);
        }
        else {
            res.push(colName);
        }
    }
    return res;
}
exports.rawQueryResultColumns = rawQueryResultColumns;
function* rawQueryResultIter(result) {
    const columns = rawQueryResultColumns(result).map((name, i) => [name, i]);
    for (let rowNum = 0; rowNum < query_iterator.slowlyCountRows(result); rowNum++) {
        const row = {};
        for (const [name, colNum] of columns) {
            const cell = getCell(result, colNum, rowNum);
            row[name] = cell === null ? '[NULL]' : cell;
        }
        yield row;
    }
}
exports.rawQueryResultIter = rawQueryResultIter;

});

// Copyright (C) 2019 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.

const _TextDecoder = TextDecoder;
const _TextEncoder = TextEncoder;

var indexBrowser = /*#__PURE__*/Object.freeze({
__proto__: null,
_TextDecoder: _TextDecoder,
_TextEncoder: _TextEncoder
});

var adb = createCommonjsModule(function (module, exports) {
// Copyright (C) 2019 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.
Object.defineProperty(exports, "__esModule", { value: true });
exports.AdbMsgImpl = exports.AdbStreamImpl = exports.AdbOverWebUsb = exports.AdbState = exports.DEFAULT_MAX_PAYLOAD_BYTES = exports.VERSION_NO_CHECKSUM = exports.VERSION_WITH_CHECKSUM = void 0;


const textEncoder = new indexBrowser._TextEncoder();
const textDecoder = new indexBrowser._TextDecoder();
exports.VERSION_WITH_CHECKSUM = 0x01000000;
exports.VERSION_NO_CHECKSUM = 0x01000001;
exports.DEFAULT_MAX_PAYLOAD_BYTES = 256 * 1024;
var AdbState;
(function (AdbState) {
    AdbState[AdbState["DISCONNECTED"] = 0] = "DISCONNECTED";
    // Authentication steps, see AdbOverWebUsb's handleAuthentication().
    AdbState[AdbState["AUTH_STEP1"] = 1] = "AUTH_STEP1";
    AdbState[AdbState["AUTH_STEP2"] = 2] = "AUTH_STEP2";
    AdbState[AdbState["AUTH_STEP3"] = 3] = "AUTH_STEP3";
    AdbState[AdbState["CONNECTED"] = 2] = "CONNECTED";
})(AdbState = exports.AdbState || (exports.AdbState = {}));
var AuthCmd;
(function (AuthCmd) {
    AuthCmd[AuthCmd["TOKEN"] = 1] = "TOKEN";
    AuthCmd[AuthCmd["SIGNATURE"] = 2] = "SIGNATURE";
    AuthCmd[AuthCmd["RSAPUBLICKEY"] = 3] = "RSAPUBLICKEY";
})(AuthCmd || (AuthCmd = {}));
const DEVICE_NOT_SET_ERROR = 'Device not set.';
// This class is a basic TypeScript implementation of adb that only supports
// shell commands. It is used to send the start tracing command to the connected
// android device, and to automatically pull the trace after the end of the
// recording. It works through the webUSB API. A brief description of how it
// works is the following:
// - The connection with the device is initiated by findAndConnect, which shows
//   a dialog with a list of connected devices. Once one is selected the
//   authentication begins. The authentication has to pass different steps, as
//   described in the "handeAuthentication" method.
// - AdbOverWebUsb tracks the state of the authentication via a state machine
//   (see AdbState).
// - A Message handler loop is executed to keep receiving the messages.
// - All the messages received from the device are passed to "onMessage" that is
//   implemented as a state machine.
// - When a new shell is established, it becomes an AdbStream, and is kept in
//   the "streams" map. Each time a message from the device is for a specific
//   previously opened stream, the "onMessage" function will forward it to the
//   stream (identified by a number).
class AdbOverWebUsb {
    constructor() {
        this.state = AdbState.DISCONNECTED;
        this.streams = new Map();
        this.devProps = '';
        this.maxPayload = exports.DEFAULT_MAX_PAYLOAD_BYTES;
        this.onConnected = () => { };
        // Devices after Dec 2017 don't use checksum. This will be auto-detected
        // during the connection.
        this.useChecksum = true;
        this.lastStreamId = 0;
        this.usbReadEndpoint = -1;
        this.usbWriteEpEndpoint = -1;
        this.filter = {
            classCode: 255,
            subclassCode: 66,
            protocolCode: 1 // Adb protocol
        };
    }
    findDevice() {
        return tslib.__awaiter(this, void 0, void 0, function* () {
            if (!('usb' in navigator)) {
                throw new Error('WebUSB not supported by the browser (requires HTTPS)');
            }
            return navigator.usb.requestDevice({ filters: [this.filter] });
        });
    }
    getPairedDevices() {
        return tslib.__awaiter(this, void 0, void 0, function* () {
            try {
                return navigator.usb.getDevices();
            }
            catch (e) { // WebUSB not available.
                return Promise.resolve([]);
            }
        });
    }
    connect(device) {
        return tslib.__awaiter(this, void 0, void 0, function* () {
            // If we are already connected, we are also already authenticated, so we can
            // skip doing the authentication again.
            if (this.state === AdbState.CONNECTED) {
                if (this.dev === device && device.opened) {
                    this.onConnected();
                    this.onConnected = () => { };
                    return;
                }
                // Another device was connected.
                yield this.disconnect();
            }
            this.dev = device;
            this.useChecksum = true;
            this.key = yield AdbOverWebUsb.initKey();
            yield this.dev.open();
            yield this.dev.reset(); // The reset is done so that we can claim the
            // device before adb server can.
            const { configValue, usbInterfaceNumber, endpoints } = this.findInterfaceAndEndpoint();
            this.usbReadEndpoint = this.findEndpointNumber(endpoints, 'in');
            this.usbWriteEpEndpoint = this.findEndpointNumber(endpoints, 'out');
            console.assert(this.usbReadEndpoint >= 0 && this.usbWriteEpEndpoint >= 0);
            yield this.dev.selectConfiguration(configValue);
            yield this.dev.claimInterface(usbInterfaceNumber);
            yield this.startAuthentication();
            // This will start a message handler loop.
            this.receiveDeviceMessages();
            // The promise will be resolved after the handshake.
            return new Promise((resolve, _) => this.onConnected = resolve);
        });
    }
    disconnect() {
        return tslib.__awaiter(this, void 0, void 0, function* () {
            this.state = AdbState.DISCONNECTED;
            if (!this.dev)
                return;
            new Map(this.streams).forEach((stream, _id) => stream.setClosed());
            console.assert(this.streams.size === 0);
            this.dev = undefined;
        });
    }
    startAuthentication() {
        return tslib.__awaiter(this, void 0, void 0, function* () {
            // USB connected, now let's authenticate.
            const VERSION = this.useChecksum ? exports.VERSION_WITH_CHECKSUM : exports.VERSION_NO_CHECKSUM;
            this.state = AdbState.AUTH_STEP1;
            yield this.send('CNXN', VERSION, this.maxPayload, 'host:1:UsbADB');
        });
    }
    findInterfaceAndEndpoint() {
        if (!this.dev)
            throw Error(DEVICE_NOT_SET_ERROR);
        for (const config of this.dev.configurations) {
            for (const interface_ of config.interfaces) {
                for (const alt of interface_.alternates) {
                    if (alt.interfaceClass === this.filter.classCode &&
                        alt.interfaceSubclass === this.filter.subclassCode &&
                        alt.interfaceProtocol === this.filter.protocolCode) {
                        return {
                            configValue: config.configurationValue,
                            usbInterfaceNumber: interface_.interfaceNumber,
                            endpoints: alt.endpoints
                        };
                    } // if (alternate)
                } // for (interface.alternates)
            } // for (configuration.interfaces)
        } // for (configurations)
        throw Error('Cannot find interfaces and endpoints');
    }
    findEndpointNumber(endpoints, direction, type = 'bulk') {
        const ep = endpoints.find((ep) => ep.type === type && ep.direction === direction);
        if (ep)
            return ep.endpointNumber;
        throw Error(`Cannot find ${direction} endpoint`);
    }
    receiveDeviceMessages() {
        this.recv()
            .then(msg => {
            this.onMessage(msg);
            this.receiveDeviceMessages();
        })
            .catch(e => {
            // Ignore error with "DEVICE_NOT_SET_ERROR" message since it is always
            // thrown after the device disconnects.
            if (e.message !== DEVICE_NOT_SET_ERROR) {
                console.error(`Exception in recv: ${e.name}. error: ${e.message}`);
            }
            this.disconnect();
        });
    }
    onMessage(msg) {
        return tslib.__awaiter(this, void 0, void 0, function* () {
            if (!this.key)
                throw Error('ADB key not initialized');
            if (msg.cmd === 'AUTH' && msg.arg0 === AuthCmd.TOKEN) {
                this.handleAuthentication(msg);
            }
            else if (msg.cmd === 'CNXN') {
                console.assert([AdbState.AUTH_STEP2, AdbState.AUTH_STEP3].includes(this.state));
                this.state = AdbState.CONNECTED;
                this.handleConnectedMessage(msg);
            }
            else if (this.state === AdbState.CONNECTED && [
                'OKAY',
                'WRTE',
                'CLSE'
            ].indexOf(msg.cmd) >= 0) {
                const stream = this.streams.get(msg.arg1);
                if (!stream) {
                    console.warn(`Received message ${msg} for unknown stream ${msg.arg1}`);
                    return;
                }
                stream.onMessage(msg);
            }
            else {
                console.error(`Unexpected message `, msg, ` in state ${this.state}`);
            }
        });
    }
    handleAuthentication(msg) {
        return tslib.__awaiter(this, void 0, void 0, function* () {
            if (!this.key)
                throw Error('ADB key not initialized');
            console.assert(msg.cmd === 'AUTH' && msg.arg0 === AuthCmd.TOKEN);
            const token = msg.data;
            if (this.state === AdbState.AUTH_STEP1) {
                // During this step, we send back the token received signed with our
                // private key. If the device has previously received our public key, the
                // dialog will not be displayed. Otherwise we will receive another message
                // ending up in AUTH_STEP3.
                this.state = AdbState.AUTH_STEP2;
                const signedToken = yield signAdbTokenWithPrivateKey(this.key.privateKey, token);
                this.send('AUTH', AuthCmd.SIGNATURE, 0, new Uint8Array(signedToken));
                return;
            }
            console.assert(this.state === AdbState.AUTH_STEP2);
            // During this step, we send our public key. The dialog will appear, and
            // if the user chooses to remember our public key, it will be
            // saved, so that the next time we will only pass through AUTH_STEP1.
            this.state = AdbState.AUTH_STEP3;
            const encodedPubKey = yield encodePubKey(this.key.publicKey);
            this.send('AUTH', AuthCmd.RSAPUBLICKEY, 0, encodedPubKey);
        });
    }
    handleConnectedMessage(msg) {
        console.assert(msg.cmd === 'CNXN');
        this.maxPayload = msg.arg1;
        this.devProps = textDecoder.decode(msg.data);
        const deviceVersion = msg.arg0;
        if (![exports.VERSION_WITH_CHECKSUM, exports.VERSION_NO_CHECKSUM].includes(deviceVersion)) {
            console.error('Version ', msg.arg0, ' not really supported!');
        }
        this.useChecksum = deviceVersion === exports.VERSION_WITH_CHECKSUM;
        this.state = AdbState.CONNECTED;
        // This will resolve the promise returned by "onConnect"
        this.onConnected();
        this.onConnected = () => { };
    }
    shell(cmd) {
        return this.openStream('shell:' + cmd);
    }
    socket(path) {
        return this.openStream('localfilesystem:' + path);
    }
    openStream(svc) {
        const stream = new AdbStreamImpl(this, ++this.lastStreamId);
        this.streams.set(stream.localStreamId, stream);
        this.send('OPEN', stream.localStreamId, 0, svc);
        //  The stream will resolve this promise once it receives the
        //  acknowledgement message from the device.
        return new Promise((resolve, reject) => {
            stream.onConnect = () => {
                stream.onClose = () => { };
                resolve(stream);
            };
            stream.onClose = () => reject();
        });
    }
    shellOutputAsString(cmd) {
        return tslib.__awaiter(this, void 0, void 0, function* () {
            const shell = yield this.shell(cmd);
            return new Promise((resolve, _) => {
                const output = [];
                shell.onData = raw => output.push(textDecoder.decode(raw));
                shell.onClose = () => resolve(output.join());
            });
        });
    }
    send(cmd, arg0, arg1, data) {
        return tslib.__awaiter(this, void 0, void 0, function* () {
            yield this.sendMsg(AdbMsgImpl.create({ cmd, arg0, arg1, data, useChecksum: this.useChecksum }));
        });
    }
    //  The header and the message data must be sent consecutively. Using 2 awaits
    //  Another message can interleave after the first header has been sent,
    //  resulting in something like [header1] [header2] [data1] [data2];
    //  In this way we are waiting both promises to be resolved before continuing.
    sendMsg(msg) {
        return tslib.__awaiter(this, void 0, void 0, function* () {
            const sendPromises = [this.sendRaw(msg.encodeHeader())];
            if (msg.data.length > 0)
                sendPromises.push(this.sendRaw(msg.data));
            yield Promise.all(sendPromises);
        });
    }
    recv() {
        return tslib.__awaiter(this, void 0, void 0, function* () {
            const res = yield this.recvRaw(ADB_MSG_SIZE);
            console.assert(res.status === 'ok');
            const msg = AdbMsgImpl.decodeHeader(res.data);
            if (msg.dataLen > 0) {
                const resp = yield this.recvRaw(msg.dataLen);
                msg.data = new Uint8Array(resp.data.buffer, resp.data.byteOffset, resp.data.byteLength);
            }
            if (this.useChecksum) {
                console.assert(AdbOverWebUsb.checksum(msg.data) === msg.dataChecksum);
            }
            return msg;
        });
    }
    static initKey() {
        return tslib.__awaiter(this, void 0, void 0, function* () {
            const KEY_SIZE = 2048;
            const keySpec = {
                name: 'RSASSA-PKCS1-v1_5',
                modulusLength: KEY_SIZE,
                publicExponent: new Uint8Array([0x01, 0x00, 0x01]),
                hash: { name: 'SHA-1' },
            };
            const key = yield crypto.subtle.generateKey(keySpec, /*extractable=*/ true, ['sign', 'verify']);
            return key;
        });
    }
    static checksum(data) {
        let res = 0;
        for (let i = 0; i < data.byteLength; i++)
            res += data[i];
        return res & 0xFFFFFFFF;
    }
    sendRaw(buf) {
        console.assert(buf.length <= this.maxPayload);
        if (!this.dev)
            throw Error(DEVICE_NOT_SET_ERROR);
        return this.dev.transferOut(this.usbWriteEpEndpoint, buf.buffer);
    }
    recvRaw(dataLen) {
        if (!this.dev)
            throw Error(DEVICE_NOT_SET_ERROR);
        return this.dev.transferIn(this.usbReadEndpoint, dataLen);
    }
}
exports.AdbOverWebUsb = AdbOverWebUsb;
var AdbStreamState;
(function (AdbStreamState) {
    AdbStreamState[AdbStreamState["WAITING_INITIAL_OKAY"] = 0] = "WAITING_INITIAL_OKAY";
    AdbStreamState[AdbStreamState["CONNECTED"] = 1] = "CONNECTED";
    AdbStreamState[AdbStreamState["CLOSED"] = 2] = "CLOSED";
})(AdbStreamState || (AdbStreamState = {}));
// An AdbStream is instantiated after the creation of a shell to the device.
// Thanks to this, we can send commands and receive their output. Messages are
// received in the main adb class, and are forwarded to an instance of this
// class based on a stream id match. Also streams have an initialization flow:
//   1. WAITING_INITIAL_OKAY: waiting for first "OKAY" message. Once received,
//      the next state will be "CONNECTED".
//   2. CONNECTED: ready to receive or send messages.
//   3. WRITING: this is needed because we must receive an ack after sending
//      each message (so, before sending the next one). For this reason, many
//      subsequent "write" calls will result in different messages in the
//      writeQueue. After each new acknowledgement ('OKAY') a new one will be
//      sent. When the queue is empty, the state will return to CONNECTED.
//   4. CLOSED: entered when the device closes the stream or close() is called.
//      For shell commands, the stream is closed after the command completed.
class AdbStreamImpl {
    constructor(adb, localStreamId) {
        this.remoteStreamId = -1;
        this.state = AdbStreamState.WAITING_INITIAL_OKAY;
        this.writeQueue = [];
        this.sendInProgress = false;
        this.onData = (_) => { };
        this.onConnect = () => { };
        this.onClose = () => { };
        this.adb = adb;
        this.localStreamId = localStreamId;
    }
    close() {
        console.assert(this.state === AdbStreamState.CONNECTED);
        if (this.writeQueue.length > 0) {
            console.error(`Dropping ${this.writeQueue.length} queued messages due to stream closing.`);
            this.writeQueue = [];
        }
        this.adb.send('CLSE', this.localStreamId, this.remoteStreamId);
    }
    write(msg) {
        return tslib.__awaiter(this, void 0, void 0, function* () {
            const raw = (typeof msg === 'string') ? textEncoder.encode(msg) : msg;
            if (this.sendInProgress ||
                this.state === AdbStreamState.WAITING_INITIAL_OKAY) {
                this.writeQueue.push(raw);
                return;
            }
            console.assert(this.state === AdbStreamState.CONNECTED);
            this.sendInProgress = true;
            yield this.adb.send('WRTE', this.localStreamId, this.remoteStreamId, raw);
        });
    }
    setClosed() {
        this.state = AdbStreamState.CLOSED;
        this.adb.streams.delete(this.localStreamId);
        this.onClose();
    }
    onMessage(msg) {
        console.assert(msg.arg1 === this.localStreamId);
        if (this.state === AdbStreamState.WAITING_INITIAL_OKAY &&
            msg.cmd === 'OKAY') {
            this.remoteStreamId = msg.arg0;
            this.state = AdbStreamState.CONNECTED;
            this.onConnect();
            return;
        }
        if (msg.cmd === 'WRTE') {
            this.adb.send('OKAY', this.localStreamId, this.remoteStreamId);
            this.onData(msg.data);
            return;
        }
        if (msg.cmd === 'OKAY') {
            console.assert(this.sendInProgress);
            this.sendInProgress = false;
            const queuedMsg = this.writeQueue.shift();
            if (queuedMsg !== undefined)
                this.write(queuedMsg);
            return;
        }
        if (msg.cmd === 'CLSE') {
            this.setClosed();
            return;
        }
        console.error(`Unexpected stream msg ${msg.toString()} in state ${this.state}`);
    }
}
exports.AdbStreamImpl = AdbStreamImpl;
const ADB_MSG_SIZE = 6 * 4; // 6 * int32.
class AdbMsgImpl {
    constructor(cmd, arg0, arg1, dataLen, dataChecksum, useChecksum = false) {
        console.assert(cmd.length === 4);
        this.cmd = cmd;
        this.arg0 = arg0;
        this.arg1 = arg1;
        this.dataLen = dataLen;
        this.data = new Uint8Array(dataLen);
        this.dataChecksum = dataChecksum;
        this.useChecksum = useChecksum;
    }
    static create({ cmd, arg0, arg1, data, useChecksum = true }) {
        const encodedData = this.encodeData(data);
        const msg = new AdbMsgImpl(cmd, arg0, arg1, encodedData.length, 0, useChecksum);
        msg.data = encodedData;
        return msg;
    }
    get dataStr() {
        return textDecoder.decode(this.data);
    }
    toString() {
        return `${this.cmd} [${this.arg0},${this.arg1}] ${this.dataStr}`;
    }
    // A brief description of the message can be found here:
    // https://android.googlesource.com/platform/system/core/+/master/adb/protocol.txt
    //
    // struct amessage {
    //     uint32_t command;    // command identifier constant
    //     uint32_t arg0;       // first argument
    //     uint32_t arg1;       // second argument
    //     uint32_t data_length;// length of payload (0 is allowed)
    //     uint32_t data_check; // checksum of data payload
    //     uint32_t magic;      // command ^ 0xffffffff
    // };
    static decodeHeader(dv) {
        console.assert(dv.byteLength === ADB_MSG_SIZE);
        const cmd = textDecoder.decode(dv.buffer.slice(0, 4));
        const cmdNum = dv.getUint32(0, true);
        const arg0 = dv.getUint32(4, true);
        const arg1 = dv.getUint32(8, true);
        const dataLen = dv.getUint32(12, true);
        const dataChecksum = dv.getUint32(16, true);
        const cmdChecksum = dv.getUint32(20, true);
        console.assert(cmdNum === (cmdChecksum ^ 0xFFFFFFFF));
        return new AdbMsgImpl(cmd, arg0, arg1, dataLen, dataChecksum);
    }
    encodeHeader() {
        const buf = new Uint8Array(ADB_MSG_SIZE);
        const dv = new DataView(buf.buffer);
        const cmdBytes = textEncoder.encode(this.cmd);
        const rawMsg = AdbMsgImpl.encodeData(this.data);
        const checksum = this.useChecksum ? AdbOverWebUsb.checksum(rawMsg) : 0;
        for (let i = 0; i < 4; i++)
            dv.setUint8(i, cmdBytes[i]);
        dv.setUint32(4, this.arg0, true);
        dv.setUint32(8, this.arg1, true);
        dv.setUint32(12, rawMsg.byteLength, true);
        dv.setUint32(16, checksum, true);
        dv.setUint32(20, dv.getUint32(0, true) ^ 0xFFFFFFFF, true);
        return buf;
    }
    static encodeData(data) {
        if (data === undefined)
            return new Uint8Array([]);
        if (typeof data === 'string')
            return textEncoder.encode(data + '\0');
        return data;
    }
}
exports.AdbMsgImpl = AdbMsgImpl;
function base64StringToArray(s) {
    const decoded = atob(s.replace(/-/g, '+').replace(/_/g, '/'));
    return [...decoded].map(char => char.charCodeAt(0));
}
const ANDROID_PUBKEY_MODULUS_SIZE = 2048;
const MODULUS_SIZE_BYTES = ANDROID_PUBKEY_MODULUS_SIZE / 8;
// RSA Public keys are encoded in a rather unique way. It's a base64 encoded
// struct of 524 bytes in total as follows (see
// libcrypto_utils/android_pubkey.c):
//
// typedef struct RSAPublicKey {
//   // Modulus length. This must be ANDROID_PUBKEY_MODULUS_SIZE.
//   uint32_t modulus_size_words;
//
//   // Precomputed montgomery parameter: -1 / n[0] mod 2^32
//   uint32_t n0inv;
//
//   // RSA modulus as a little-endian array.
//   uint8_t modulus[ANDROID_PUBKEY_MODULUS_SIZE];
//
//   // Montgomery parameter R^2 as a little-endian array of little-endian
//   words. uint8_t rr[ANDROID_PUBKEY_MODULUS_SIZE];
//
//   // RSA modulus: 3 or 65537
//   uint32_t exponent;
// } RSAPublicKey;
//
// However, the Montgomery params (n0inv and rr) are not really used, see
// comment in android_pubkey_decode() ("Note that we don't extract the
// montgomery parameters...")
function encodePubKey(key) {
    return tslib.__awaiter(this, void 0, void 0, function* () {
        const expPubKey = yield crypto.subtle.exportKey('jwk', key);
        const nArr = base64StringToArray(expPubKey.n).reverse();
        const eArr = base64StringToArray(expPubKey.e).reverse();
        const arr = new Uint8Array(3 * 4 + 2 * MODULUS_SIZE_BYTES);
        const dv = new DataView(arr.buffer);
        dv.setUint32(0, MODULUS_SIZE_BYTES / 4, true);
        // The Mongomery params (n0inv and rr) are not computed.
        dv.setUint32(4, 0 /*n0inv*/, true);
        // Modulus
        for (let i = 0; i < MODULUS_SIZE_BYTES; i++)
            dv.setUint8(8 + i, nArr[i]);
        // rr:
        for (let i = 0; i < MODULUS_SIZE_BYTES; i++) {
            dv.setUint8(8 + MODULUS_SIZE_BYTES + i, 0 /*rr*/);
        }
        // Exponent
        for (let i = 0; i < 4; i++) {
            dv.setUint8(8 + (2 * MODULUS_SIZE_BYTES) + i, eArr[i]);
        }
        return btoa(String.fromCharCode(...new Uint8Array(dv.buffer))) +
            ' perfetto@webusb';
    });
}
// TODO(nicomazz): This token signature will be useful only when we save the
// generated keys. So far, we are not doing so. As a consequence, a dialog is
// displayed every time a tracing session is started.
// The reason why it has not already been implemented is that the standard
// crypto.subtle.sign function assumes that the input needs hashing, which is
// not the case for ADB, where the 20 bytes token is already hashed.
// A solution to this is implementing a custom private key signature with a js
// implementation of big integers. Maybe, wrapping the key like in the following
// CL can work:
// https://android-review.googlesource.com/c/platform/external/perfetto/+/1105354/18
function signAdbTokenWithPrivateKey(_privateKey, token) {
    return tslib.__awaiter(this, void 0, void 0, function* () {
        // This function is not implemented.
        return token.buffer;
    });
}

});

var validate_config = createCommonjsModule(function (module, exports) {
// Copyright (C) 2020 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.
Object.defineProperty(exports, "__esModule", { value: true });
exports.validateRecordConfig = void 0;

function validateRecordConfig(config) {
    // Remove the keys that are not in both createEmptyRecordConfig and
    // config.
    const newConfig = state.createEmptyRecordConfig();
    const ignoredKeys = [];
    // TODO(bsebastien): Also check that types of properties match.
    Object.entries(newConfig).forEach(([key, value]) => {
        if (key in config && typeof value === typeof config[key]) {
            newConfig[key] = config[key];
        }
        else {
            ignoredKeys.push(key);
        }
    });
    // Check if config has additional keys that are not in
    // createEmptyRecordConfig().
    for (const key of Object.keys(config)) {
        if (!(key in newConfig)) {
            ignoredKeys.push(key);
        }
    }
    if (ignoredKeys.length > 0) {
        // At least return an empty RecordConfig if nothing match.
        return {
            errorMessage: 'Warning: Loaded config contains incompatible keys.\n\
        It may have been created with an older version of the UI.\n\
        Ignored keys: ' +
                ignoredKeys.join(' '),
            config: newConfig,
        };
    }
    return { config: newConfig };
}
exports.validateRecordConfig = validateRecordConfig;

});

var record_config = createCommonjsModule(function (module, exports) {
// Copyright (C) 2020 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.
Object.defineProperty(exports, "__esModule", { value: true });
exports.recordConfigStore = exports.RecordConfigStore = void 0;

const LOCAL_STORAGE_RECORD_CONFIGS_KEY = 'recordConfigs';
class NamedRecordConfig {
    constructor(title, config, key) {
        this.title = title;
        this.config = this.validateData(config);
        this.key = key;
    }
    validateData(config) {
        const validConfig = validate_config.validateRecordConfig(config);
        if (validConfig.errorMessage) {
            // TODO(bsebastien): Show a warning message to the user in the UI.
            console.warn(validConfig.errorMessage);
        }
        return validConfig.config;
    }
    static isValid(jsonObject) {
        return jsonObject.title !== undefined &&
            jsonObject.config !== undefined &&
            jsonObject.key !== undefined;
    }
}
class RecordConfigStore {
    constructor() {
        this.recordConfigs = [];
        this.reloadFromLocalStorage();
    }
    save(recordConfig, title) {
        // We reload from local storage in case of concurrent
        // modifications of local storage from a different tab.
        this.reloadFromLocalStorage();
        const config = new NamedRecordConfig(title ? title : new Date().toJSON(), recordConfig, new Date().toJSON());
        this.recordConfigs.push(config);
        window.localStorage.setItem(LOCAL_STORAGE_RECORD_CONFIGS_KEY, JSON.stringify(this.recordConfigs));
    }
    delete(key) {
        // We reload from local storage in case of concurrent
        // modifications of local storage from a different tab.
        this.reloadFromLocalStorage();
        let idx = -1;
        for (let i = 0; i < this.recordConfigs.length; ++i) {
            if (this.recordConfigs[i].key === key) {
                idx = i;
                break;
            }
        }
        if (idx !== -1) {
            this.recordConfigs.splice(idx, 1);
            window.localStorage.setItem(LOCAL_STORAGE_RECORD_CONFIGS_KEY, JSON.stringify(this.recordConfigs));
        }
        else {
            // TODO(bsebastien): Show a warning message to the user in the UI.
            console.warn('The config selected doesn\'t exist any more');
        }
    }
    clearRecordConfigs() {
        this.recordConfigs = [];
        window.localStorage.setItem(LOCAL_STORAGE_RECORD_CONFIGS_KEY, JSON.stringify([]));
    }
    reloadFromLocalStorage() {
        const configsLocalStorage = window.localStorage.getItem(LOCAL_STORAGE_RECORD_CONFIGS_KEY);
        if (configsLocalStorage) {
            try {
                const validConfigLocalStorage = [];
                const parsedConfigsLocalStorage = JSON.parse(configsLocalStorage);
                // Check if it's an array.
                if (!Array.isArray(parsedConfigsLocalStorage)) {
                    this.clearRecordConfigs();
                    return;
                }
                for (let i = 0; i < parsedConfigsLocalStorage.length; ++i) {
                    if (!NamedRecordConfig.isValid(parsedConfigsLocalStorage[i])) {
                        continue;
                    }
                    validConfigLocalStorage.push(new NamedRecordConfig(parsedConfigsLocalStorage[i].title, parsedConfigsLocalStorage[i].config, parsedConfigsLocalStorage[i].key));
                }
                this.recordConfigs = validConfigLocalStorage;
                window.localStorage.setItem(LOCAL_STORAGE_RECORD_CONFIGS_KEY, JSON.stringify(validConfigLocalStorage));
            }
            catch (e) {
                this.clearRecordConfigs();
            }
        }
        else {
            this.clearRecordConfigs();
        }
    }
}
exports.RecordConfigStore = RecordConfigStore;
// This class is a singleton to avoid many instances
// conflicting as they attempt to edit localStorage.
exports.recordConfigStore = new RecordConfigStore();

});

var record_widgets = createCommonjsModule(function (module, exports) {
// Copyright (C) 2019 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.
Object.defineProperty(exports, "__esModule", { value: true });
exports.CodeSnippet = exports.Textarea = exports.Dropdown = exports.Slider = exports.Toggle = exports.Probe = void 0;






function defaultSort(a, b) {
    return a.localeCompare(b);
}
class DocsChip {
    view({ attrs }) {
        return mithril('a.inline-chip', { href: attrs.href, title: 'Open docs in new tab', target: '_blank' }, mithril('i.material-icons', 'info'), ' Docs');
    }
}
class Probe {
    view({ attrs, children }) {
        const onToggle = (enabled) => {
            const traceCfg = immer_1.produce(globals$1.globals.state.recordConfig, draft => {
                attrs.setEnabled(draft, enabled);
            });
            globals$1.globals.dispatch(actions.Actions.setRecordConfig({ config: traceCfg }));
        };
        const enabled = attrs.isEnabled(globals$1.globals.state.recordConfig);
        return mithril(`.probe${enabled ? '.enabled' : ''}`, attrs.img && mithril('img', {
            src: `${globals$1.globals.root}assets/${attrs.img}`,
            onclick: () => onToggle(!enabled),
        }), mithril('label', mithril(`input[type=checkbox]`, {
            checked: enabled,
            oninput: (e) => {
                onToggle(e.target.checked);
            },
        }), mithril('span', attrs.title)), mithril('div', mithril('div', attrs.descr), mithril('.probe-config', children)));
    }
}
exports.Probe = Probe;
class Toggle {
    view({ attrs }) {
        const onToggle = (enabled) => {
            const traceCfg = immer_1.produce(globals$1.globals.state.recordConfig, draft => {
                attrs.setEnabled(draft, enabled);
            });
            globals$1.globals.dispatch(actions.Actions.setRecordConfig({ config: traceCfg }));
        };
        const enabled = attrs.isEnabled(globals$1.globals.state.recordConfig);
        return mithril(`.toggle${enabled ? '.enabled' : ''}${attrs.cssClass || ''}`, mithril('label', mithril(`input[type=checkbox]`, {
            checked: enabled,
            oninput: (e) => {
                onToggle(e.target.checked);
            },
        }), mithril('span', attrs.title)), mithril('.descr', attrs.descr));
    }
}
exports.Toggle = Toggle;
class Slider {
    onValueChange(attrs, newVal) {
        const traceCfg = immer_1.produce(globals$1.globals.state.recordConfig, draft => {
            attrs.set(draft, newVal);
        });
        globals$1.globals.dispatch(actions.Actions.setRecordConfig({ config: traceCfg }));
    }
    onTimeValueChange(attrs, hms) {
        try {
            const date = new Date(`1970-01-01T${hms}.000Z`);
            if (isNaN(date.getTime()))
                return;
            this.onValueChange(attrs, date.getTime());
        }
        catch (_a) {
        }
    }
    onSliderChange(attrs, newIdx) {
        this.onValueChange(attrs, attrs.values[newIdx]);
    }
    view({ attrs }) {
        const id = attrs.title.replace(/[^a-z0-9]/gmi, '_').toLowerCase();
        const maxIdx = attrs.values.length - 1;
        const val = attrs.get(globals$1.globals.state.recordConfig);
        const min = attrs.min;
        const description = attrs.description;
        const disabled = attrs.disabled;
        // Find the index of the closest value in the slider.
        let idx = 0;
        for (; idx < attrs.values.length && attrs.values[idx] < val; idx++) {
        }
        let spinnerCfg = {};
        if (attrs.isTime) {
            spinnerCfg = {
                type: 'text',
                pattern: '(0[0-9]|1[0-9]|2[0-3])(:[0-5][0-9]){2}',
                value: new Date(val).toISOString().substr(11, 8),
                oninput: (e) => {
                    this.onTimeValueChange(attrs, e.target.value);
                },
            };
        }
        else {
            spinnerCfg = {
                type: 'number',
                value: val,
                oninput: (e) => {
                    this.onTimeValueChange(attrs, e.target.value);
                },
            };
        }
        return mithril('.slider' + (attrs.cssClass || ''), mithril('header', attrs.title), description ? mithril('header.descr', attrs.description) : '', attrs.icon !== undefined ? mithril('i.material-icons', attrs.icon) : [], mithril(`input[id="${id}"][type=range][min=0][max=${maxIdx}][value=${idx}]
        ${disabled ? '[disabled]' : ''}`, {
            oninput: (e) => {
                this.onSliderChange(attrs, +e.target.value);
            },
        }), mithril(`input.spinner[min=${min !== undefined ? min : 1}][for=${id}]`, spinnerCfg), mithril('.unit', attrs.unit));
    }
}
exports.Slider = Slider;
class Dropdown {
    resetScroll(dom) {
        // Chrome seems to override the scroll offset on creationa, b without this,
        // even though we call it after having marked the options as selected.
        setTimeout(() => {
            // Don't reset the scroll position if the element is still focused.
            if (dom !== document.activeElement)
                dom.scrollTop = 0;
        }, 0);
    }
    onChange(attrs, e) {
        const dom = e.target;
        const selKeys = [];
        for (let i = 0; i < dom.selectedOptions.length; i++) {
            const item = logging.assertExists(dom.selectedOptions.item(i));
            selKeys.push(item.value);
        }
        const traceCfg = immer_1.produce(globals$1.globals.state.recordConfig, draft => {
            attrs.set(draft, selKeys);
        });
        globals$1.globals.dispatch(actions.Actions.setRecordConfig({ config: traceCfg }));
    }
    view({ attrs }) {
        const options = [];
        const selItems = attrs.get(globals$1.globals.state.recordConfig);
        let numSelected = 0;
        const entries = [...attrs.options.entries()];
        const f = attrs.sort === undefined ? defaultSort : attrs.sort;
        entries.sort((a, b) => f(a[1], b[1]));
        for (const [key, label] of entries) {
            const opts = { value: key, selected: false };
            if (selItems.includes(key)) {
                opts.selected = true;
                numSelected++;
            }
            options.push(mithril('option', opts, label));
        }
        const label = `${attrs.title} ${numSelected ? `(${numSelected})` : ''}`;
        return mithril(`select.dropdown${attrs.cssClass || ''}[multiple=multiple]`, {
            onblur: (e) => this.resetScroll(e.target),
            onmouseleave: (e) => this.resetScroll(e.target),
            oninput: (e) => this.onChange(attrs, e),
            oncreate: (vnode) => this.resetScroll(vnode.dom),
        }, mithril('optgroup', { label }, options));
    }
}
exports.Dropdown = Dropdown;
class Textarea {
    onChange(attrs, dom) {
        const traceCfg = immer_1.produce(globals$1.globals.state.recordConfig, draft => {
            attrs.set(draft, dom.value);
        });
        globals$1.globals.dispatch(actions.Actions.setRecordConfig({ config: traceCfg }));
    }
    view({ attrs }) {
        return mithril('.textarea-holder', mithril('header', attrs.title, attrs.docsLink && [' ', mithril(DocsChip, { href: attrs.docsLink })]), mithril(`textarea.extra-input${attrs.cssClass || ''}`, {
            onchange: (e) => this.onChange(attrs, e.target),
            placeholder: attrs.placeholder,
            value: attrs.get(globals$1.globals.state.recordConfig)
        }));
    }
}
exports.Textarea = Textarea;
class CodeSnippet {
    view({ attrs }) {
        return mithril('.code-snippet', mithril('button', {
            title: 'Copy to clipboard',
            onclick: () => clipboard.copyToClipboard(attrs.text),
        }, mithril('i.material-icons', 'assignment')), mithril('code', attrs.text));
    }
}
exports.CodeSnippet = CodeSnippet;

});

var router$1 = createCommonjsModule(function (module, exports) {
// 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.
Object.defineProperty(exports, "__esModule", { value: true });
exports.Router = exports.ROUTE_PREFIX = void 0;


exports.ROUTE_PREFIX = '#!';
class Router {
    constructor(defaultRoute, routes, dispatch, logging) {
        this.defaultRoute = defaultRoute;
        this.routes = routes;
        this.dispatch = dispatch;
        this.logging = logging;
        if (!(defaultRoute in routes)) {
            throw Error('routes must define a component for defaultRoute.');
        }
        window.onhashchange = () => this.navigateToCurrentHash();
    }
    /**
     * Parses and returns the current route string from |window.location.hash|.
     * May return routes that are not defined in |this.routes|.
     */
    getRouteFromHash() {
        const prefixLength = exports.ROUTE_PREFIX.length;
        const hash = window.location.hash;
        // Do not try to parse route if prefix doesn't match.
        if (hash.substring(0, prefixLength) !== exports.ROUTE_PREFIX)
            return '';
        return hash.split('?')[0].substring(prefixLength);
    }
    /**
     * Sets |route| on |window.location.hash|. If |route| if not defined in
     * |this.routes|, dispatches a navigation to |this.defaultRoute|.
     */
    setRouteOnHash(route) {
        history.pushState(undefined, "", exports.ROUTE_PREFIX + route);
        this.logging.updatePath(route);
        if (!(route in this.routes)) {
            console.info(`Route ${route} not known redirecting to ${this.defaultRoute}.`);
            this.dispatch(actions.Actions.navigate({ route: this.defaultRoute }));
        }
    }
    /**
     * Dispatches navigation action to |this.getRouteFromHash()| if that is
     * defined in |this.routes|, otherwise to |this.defaultRoute|.
     */
    navigateToCurrentHash() {
        const hashRoute = this.getRouteFromHash();
        const newRoute = hashRoute in this.routes ? hashRoute : this.defaultRoute;
        this.dispatch(actions.Actions.navigate({ route: newRoute }));
        // TODO(dproy): Handle case when new route has a permalink.
    }
    /**
     * Returns the component for given |route|. If |route| is not defined, returns
     * component of |this.defaultRoute|.
     */
    resolve(route) {
        if (!route || !(route in this.routes)) {
            return this.routes[this.defaultRoute];
        }
        return this.routes[route];
    }
    static param(key) {
        const hash = window.location.hash;
        const paramStart = hash.indexOf('?');
        if (paramStart === -1)
            return undefined;
        return mithril.parseQueryString(hash.substring(paramStart))[key];
    }
}
exports.Router = Router;

});

var record_page = createCommonjsModule(function (module, exports) {
// 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.
Object.defineProperty(exports, "__esModule", { value: true });
exports.RecordPage = exports.updateAvailableAdbDevices = exports.ConfigTitleState = void 0;






const state_2 = state;






const LOCAL_STORAGE_SHOW_CONFIG = 'showConfigs';
const POLL_INTERVAL_MS = [250, 500, 1000, 2500, 5000, 30000, 60000];
const ATRACE_CATEGORIES = new Map();
ATRACE_CATEGORIES.set('adb', 'ADB');
ATRACE_CATEGORIES.set('aidl', 'AIDL calls');
ATRACE_CATEGORIES.set('am', 'Activity Manager');
ATRACE_CATEGORIES.set('audio', 'Audio');
ATRACE_CATEGORIES.set('binder_driver', 'Binder Kernel driver');
ATRACE_CATEGORIES.set('binder_lock', 'Binder global lock trace');
ATRACE_CATEGORIES.set('bionic', 'Bionic C library');
ATRACE_CATEGORIES.set('camera', 'Camera');
ATRACE_CATEGORIES.set('dalvik', 'ART & Dalvik');
ATRACE_CATEGORIES.set('database', 'Database');
ATRACE_CATEGORIES.set('gfx', 'Graphics');
ATRACE_CATEGORIES.set('hal', 'Hardware Modules');
ATRACE_CATEGORIES.set('input', 'Input');
ATRACE_CATEGORIES.set('network', 'Network');
ATRACE_CATEGORIES.set('nnapi', 'Neural Network API');
ATRACE_CATEGORIES.set('pm', 'Package Manager');
ATRACE_CATEGORIES.set('power', 'Power Management');
ATRACE_CATEGORIES.set('res', 'Resource Loading');
ATRACE_CATEGORIES.set('rro', 'Resource Overlay');
ATRACE_CATEGORIES.set('rs', 'RenderScript');
ATRACE_CATEGORIES.set('sm', 'Sync Manager');
ATRACE_CATEGORIES.set('ss', 'System Server');
ATRACE_CATEGORIES.set('vibrator', 'Vibrator');
ATRACE_CATEGORIES.set('video', 'Video');
ATRACE_CATEGORIES.set('view', 'View System');
ATRACE_CATEGORIES.set('webview', 'WebView');
ATRACE_CATEGORIES.set('wm', 'Window Manager');
const LOG_BUFFERS = new Map();
LOG_BUFFERS.set('LID_CRASH', 'Crash');
LOG_BUFFERS.set('LID_DEFAULT', 'Main');
LOG_BUFFERS.set('LID_EVENTS', 'Binary events');
LOG_BUFFERS.set('LID_KERNEL', 'Kernel');
LOG_BUFFERS.set('LID_RADIO', 'Radio');
LOG_BUFFERS.set('LID_SECURITY', 'Security');
LOG_BUFFERS.set('LID_STATS', 'Stats');
LOG_BUFFERS.set('LID_SYSTEM', 'System');
const FTRACE_CATEGORIES = new Map();
FTRACE_CATEGORIES.set('binder/*', 'binder');
FTRACE_CATEGORIES.set('block/*', 'block');
FTRACE_CATEGORIES.set('clk/*', 'clk');
FTRACE_CATEGORIES.set('ext4/*', 'ext4');
FTRACE_CATEGORIES.set('f2fs/*', 'f2fs');
FTRACE_CATEGORIES.set('i2c/*', 'i2c');
FTRACE_CATEGORIES.set('irq/*', 'irq');
FTRACE_CATEGORIES.set('kmem/*', 'kmem');
FTRACE_CATEGORIES.set('memory_bus/*', 'memory_bus');
FTRACE_CATEGORIES.set('mmc/*', 'mmc');
FTRACE_CATEGORIES.set('oom/*', 'oom');
FTRACE_CATEGORIES.set('power/*', 'power');
FTRACE_CATEGORIES.set('regulator/*', 'regulator');
FTRACE_CATEGORIES.set('sched/*', 'sched');
FTRACE_CATEGORIES.set('sync/*', 'sync');
FTRACE_CATEGORIES.set('task/*', 'task');
FTRACE_CATEGORIES.set('task/*', 'task');
FTRACE_CATEGORIES.set('vmscan/*', 'vmscan');
FTRACE_CATEGORIES.set('fastrpc/*', 'fastrpc');
function RecSettings(cssClass) {
    const S = (x) => x * 1000;
    const M = (x) => x * 1000 * 60;
    const H = (x) => x * 1000 * 60 * 60;
    const cfg = globals$1.globals.state.recordConfig;
    const recButton = (mode, title, img) => {
        const checkboxArgs = {
            checked: cfg.mode === mode,
            onchange: (e) => {
                const checked = e.target.checked;
                if (!checked)
                    return;
                const traceCfg = immer_1.produce(globals$1.globals.state.recordConfig, draft => {
                    draft.mode = mode;
                });
                globals$1.globals.dispatch(actions.Actions.setRecordConfig({ config: traceCfg }));
            },
        };
        return mithril(`label${cfg.mode === mode ? '.selected' : ''}`, mithril(`input[type=radio][name=rec_mode]`, checkboxArgs), mithril(`img[src=${globals$1.globals.root}assets/${img}]`), mithril('span', title));
    };
    return mithril(`.record-section${cssClass}`, mithril('header', 'Recording mode'), mithril('.record-mode', recButton('STOP_WHEN_FULL', 'Stop when full', 'rec_one_shot.png'), recButton('RING_BUFFER', 'Ring buffer', 'rec_ring_buf.png'), recButton('LONG_TRACE', 'Long trace', 'rec_long_trace.png')), mithril(record_widgets.Slider, {
        title: 'In-memory buffer size',
        icon: '360',
        values: [4, 8, 16, 32, 64, 128, 256, 512],
        unit: 'MB',
        set: (cfg, val) => cfg.bufferSizeMb = val,
        get: (cfg) => cfg.bufferSizeMb
    }), mithril(record_widgets.Slider, {
        title: 'Max duration',
        icon: 'timer',
        values: [S(10), S(15), S(30), S(60), M(5), M(30), H(1), H(6), H(12)],
        isTime: true,
        unit: 'h:m:s',
        set: (cfg, val) => cfg.durationMs = val,
        get: (cfg) => cfg.durationMs
    }), mithril(record_widgets.Slider, {
        title: 'Max file size',
        icon: 'save',
        cssClass: cfg.mode !== 'LONG_TRACE' ? '.hide' : '',
        values: [5, 25, 50, 100, 500, 1000, 1000 * 5, 1000 * 10],
        unit: 'MB',
        set: (cfg, val) => cfg.maxFileSizeMb = val,
        get: (cfg) => cfg.maxFileSizeMb
    }), mithril(record_widgets.Slider, {
        title: 'Flush on disk every',
        cssClass: cfg.mode !== 'LONG_TRACE' ? '.hide' : '',
        icon: 'av_timer',
        values: [100, 250, 500, 1000, 2500, 5000],
        unit: 'ms',
        set: (cfg, val) => cfg.fileWritePeriodMs = val,
        get: (cfg) => cfg.fileWritePeriodMs || 0
    }));
}
function PowerSettings(cssClass) {
    const DOC_URL = 'https://perfetto.dev/docs/data-sources/battery-counters';
    const descr = [mithril('div', mithril('span', `Polls charge counters and instantaneous power draw from
                    the battery power management IC and the power rails from
                    the PowerStats HAL (`), mithril('a', { href: DOC_URL, target: '_blank' }, 'see docs for more'), mithril('span', ')'))];
    if (globals$1.globals.isInternalUser) {
        descr.push(mithril('div', mithril('span', 'Googlers: See '), mithril('a', { href: 'http://go/power-rails-internal-doc', target: '_blank' }, 'this doc'), mithril('span', ` for instructions on how to change the refault rail selection
                  on internal devices.`)));
    }
    return mithril(`.record-section${cssClass}`, mithril(record_widgets.Probe, {
        title: 'Battery drain & power rails',
        img: 'rec_battery_counters.png',
        descr,
        setEnabled: (cfg, val) => cfg.batteryDrain = val,
        isEnabled: (cfg) => cfg.batteryDrain
    }, mithril(record_widgets.Slider, {
        title: 'Poll interval',
        cssClass: '.thin',
        values: POLL_INTERVAL_MS,
        unit: 'ms',
        set: (cfg, val) => cfg.batteryDrainPollMs = val,
        get: (cfg) => cfg.batteryDrainPollMs
    })), mithril(record_widgets.Probe, {
        title: 'Board voltages & frequencies',
        img: 'rec_board_voltage.png',
        descr: 'Tracks voltage and frequency changes from board sensors',
        setEnabled: (cfg, val) => cfg.boardSensors = val,
        isEnabled: (cfg) => cfg.boardSensors
    }));
}
function GpuSettings(cssClass) {
    return mithril(`.record-section${cssClass}`, mithril(record_widgets.Probe, {
        title: 'GPU frequency',
        img: 'rec_cpu_freq.png',
        descr: 'Records gpu frequency via ftrace',
        setEnabled: (cfg, val) => cfg.gpuFreq = val,
        isEnabled: (cfg) => cfg.gpuFreq
    }), mithril(record_widgets.Probe, {
        title: 'GPU memory',
        img: 'rec_gpu_mem_total.png',
        descr: `Allows to track per process and global total GPU memory usages.
                (Available on recent Android 12+ kernels)`,
        setEnabled: (cfg, val) => cfg.gpuMemTotal = val,
        isEnabled: (cfg) => cfg.gpuMemTotal
    }));
}
function CpuSettings(cssClass) {
    return mithril(`.record-section${cssClass}`, mithril(record_widgets.Probe, {
        title: 'Coarse CPU usage counter',
        img: 'rec_cpu_coarse.png',
        descr: `Lightweight polling of CPU usage counters via /proc/stat.
                    Allows to periodically monitor CPU usage.`,
        setEnabled: (cfg, val) => cfg.cpuCoarse = val,
        isEnabled: (cfg) => cfg.cpuCoarse
    }, mithril(record_widgets.Slider, {
        title: 'Poll interval',
        cssClass: '.thin',
        values: POLL_INTERVAL_MS,
        unit: 'ms',
        set: (cfg, val) => cfg.cpuCoarsePollMs = val,
        get: (cfg) => cfg.cpuCoarsePollMs
    })), mithril(record_widgets.Probe, {
        title: 'Scheduling details',
        img: 'rec_cpu_fine.png',
        descr: 'Enables high-detailed tracking of scheduling events',
        setEnabled: (cfg, val) => cfg.cpuSched = val,
        isEnabled: (cfg) => cfg.cpuSched
    }), mithril(record_widgets.Probe, {
        title: 'CPU frequency and idle states',
        img: 'rec_cpu_freq.png',
        descr: 'Records cpu frequency and idle state changes via ftrace',
        setEnabled: (cfg, val) => cfg.cpuFreq = val,
        isEnabled: (cfg) => cfg.cpuFreq
    }), mithril(record_widgets.Probe, {
        title: 'Syscalls',
        img: 'rec_syscalls.png',
        descr: `Tracks the enter and exit of all syscalls. On Android
                requires a userdebug or eng build.`,
        setEnabled: (cfg, val) => cfg.cpuSyscall = val,
        isEnabled: (cfg) => cfg.cpuSyscall
    }));
}
function HeapSettings(cssClass) {
    const valuesForMS = [
        0,
        1000,
        10 * 1000,
        30 * 1000,
        60 * 1000,
        5 * 60 * 1000,
        10 * 60 * 1000,
        30 * 60 * 1000,
        60 * 60 * 1000
    ];
    const valuesForShMemBuff = [
        0,
        512,
        1024,
        2 * 1024,
        4 * 1024,
        8 * 1024,
        16 * 1024,
        32 * 1024,
        64 * 1024,
        128 * 1024,
        256 * 1024,
        512 * 1024,
        1024 * 1024,
        64 * 1024 * 1024,
        128 * 1024 * 1024,
        256 * 1024 * 1024,
        512 * 1024 * 1024
    ];
    return mithril(`.${cssClass}`, mithril(record_widgets.Textarea, {
        title: 'Names or pids of the processes to track',
        docsLink: 'https://perfetto.dev/docs/data-sources/native-heap-profiler#heapprofd-targets',
        placeholder: 'One per line, e.g.:\n' +
            'system_server\n' +
            'com.google.android.apps.photos\n' +
            '1503',
        set: (cfg, val) => cfg.hpProcesses = val,
        get: (cfg) => cfg.hpProcesses
    }), mithril(record_widgets.Slider, {
        title: 'Sampling interval',
        cssClass: '.thin',
        values: [
            0, 1, 2, 4, 8, 16, 32, 64,
            128, 256, 512, 1024, 2048, 4096, 8192, 16384,
            32768, 65536, 131072, 262144, 524288, 1048576
        ],
        unit: 'B',
        min: 0,
        set: (cfg, val) => cfg.hpSamplingIntervalBytes = val,
        get: (cfg) => cfg.hpSamplingIntervalBytes
    }), mithril(record_widgets.Slider, {
        title: 'Continuous dumps interval ',
        description: 'Time between following dumps (0 = disabled)',
        cssClass: '.thin',
        values: valuesForMS,
        unit: 'ms',
        min: 0,
        set: (cfg, val) => {
            cfg.hpContinuousDumpsInterval = val;
        },
        get: (cfg) => cfg.hpContinuousDumpsInterval
    }), mithril(record_widgets.Slider, {
        title: 'Continuous dumps phase',
        description: 'Time before first dump',
        cssClass: `.thin${globals$1.globals.state.recordConfig.hpContinuousDumpsInterval === 0 ?
            '.greyed-out' :
            ''}`,
        values: valuesForMS,
        unit: 'ms',
        min: 0,
        disabled: globals$1.globals.state.recordConfig.hpContinuousDumpsInterval === 0,
        set: (cfg, val) => cfg.hpContinuousDumpsPhase = val,
        get: (cfg) => cfg.hpContinuousDumpsPhase
    }), mithril(record_widgets.Slider, {
        title: `Shared memory buffer`,
        cssClass: '.thin',
        values: valuesForShMemBuff.filter(value => value === 0 || value >= 8192 && value % 4096 === 0),
        unit: 'B',
        min: 0,
        set: (cfg, val) => cfg.hpSharedMemoryBuffer = val,
        get: (cfg) => cfg.hpSharedMemoryBuffer
    }), mithril(record_widgets.Toggle, {
        title: 'Block client',
        cssClass: '.thin',
        descr: `Slow down target application if profiler cannot keep up.`,
        setEnabled: (cfg, val) => cfg.hpBlockClient = val,
        isEnabled: (cfg) => cfg.hpBlockClient
    }), mithril(record_widgets.Toggle, {
        title: 'All custom allocators (Q+)',
        cssClass: '.thin',
        descr: `If the target application exposes custom allocators, also
sample from those.`,
        setEnabled: (cfg, val) => cfg.hpAllHeaps = val,
        isEnabled: (cfg) => cfg.hpAllHeaps
    })
    // TODO(hjd): Add advanced options.
    );
}
function JavaHeapDumpSettings(cssClass) {
    const valuesForMS = [
        0,
        1000,
        10 * 1000,
        30 * 1000,
        60 * 1000,
        5 * 60 * 1000,
        10 * 60 * 1000,
        30 * 60 * 1000,
        60 * 60 * 1000
    ];
    return mithril(`.${cssClass}`, mithril(record_widgets.Textarea, {
        title: 'Names or pids of the processes to track',
        placeholder: 'One per line, e.g.:\n' +
            'com.android.vending\n' +
            '1503',
        set: (cfg, val) => cfg.jpProcesses = val,
        get: (cfg) => cfg.jpProcesses
    }), mithril(record_widgets.Slider, {
        title: 'Continuous dumps interval ',
        description: 'Time between following dumps (0 = disabled)',
        cssClass: '.thin',
        values: valuesForMS,
        unit: 'ms',
        min: 0,
        set: (cfg, val) => {
            cfg.jpContinuousDumpsInterval = val;
        },
        get: (cfg) => cfg.jpContinuousDumpsInterval
    }), mithril(record_widgets.Slider, {
        title: 'Continuous dumps phase',
        description: 'Time before first dump',
        cssClass: `.thin${globals$1.globals.state.recordConfig.jpContinuousDumpsInterval === 0 ?
            '.greyed-out' :
            ''}`,
        values: valuesForMS,
        unit: 'ms',
        min: 0,
        disabled: globals$1.globals.state.recordConfig.jpContinuousDumpsInterval === 0,
        set: (cfg, val) => cfg.jpContinuousDumpsPhase = val,
        get: (cfg) => cfg.jpContinuousDumpsPhase
    }));
}
function MemorySettings(cssClass) {
    const meminfoOpts = new Map();
    for (const x in protos_1.MeminfoCounters) {
        if (typeof protos_1.MeminfoCounters[x] === 'number' &&
            !`${x}`.endsWith('_UNSPECIFIED')) {
            meminfoOpts.set(x, x.replace('MEMINFO_', '').toLowerCase());
        }
    }
    const vmstatOpts = new Map();
    for (const x in protos_1.VmstatCounters) {
        if (typeof protos_1.VmstatCounters[x] === 'number' &&
            !`${x}`.endsWith('_UNSPECIFIED')) {
            vmstatOpts.set(x, x.replace('VMSTAT_', '').toLowerCase());
        }
    }
    return mithril(`.record-section${cssClass}`, mithril(record_widgets.Probe, {
        title: 'Native heap profiling',
        img: 'rec_native_heap_profiler.png',
        descr: `Track native heap allocations & deallocations of an Android
               process. (Available on Android 10+)`,
        setEnabled: (cfg, val) => cfg.heapProfiling = val,
        isEnabled: (cfg) => cfg.heapProfiling
    }, HeapSettings(cssClass)), mithril(record_widgets.Probe, {
        title: 'Java heap dumps',
        img: 'rec_java_heap_dump.png',
        descr: `Dump information about the Java object graph of an
          Android app. (Available on Android 11+)`,
        setEnabled: (cfg, val) => cfg.javaHeapDump = val,
        isEnabled: (cfg) => cfg.javaHeapDump
    }, JavaHeapDumpSettings(cssClass)), mithril(record_widgets.Probe, {
        title: 'Kernel meminfo',
        img: 'rec_meminfo.png',
        descr: 'Polling of /proc/meminfo',
        setEnabled: (cfg, val) => cfg.meminfo = val,
        isEnabled: (cfg) => cfg.meminfo
    }, mithril(record_widgets.Slider, {
        title: 'Poll interval',
        cssClass: '.thin',
        values: POLL_INTERVAL_MS,
        unit: 'ms',
        set: (cfg, val) => cfg.meminfoPeriodMs = val,
        get: (cfg) => cfg.meminfoPeriodMs
    }), mithril(record_widgets.Dropdown, {
        title: 'Select counters',
        cssClass: '.multicolumn',
        options: meminfoOpts,
        set: (cfg, val) => cfg.meminfoCounters = val,
        get: (cfg) => cfg.meminfoCounters
    })), mithril(record_widgets.Probe, {
        title: 'High-frequency memory events',
        img: 'rec_mem_hifreq.png',
        descr: `Allows to track short memory spikes and transitories through
                ftrace's mm_event, rss_stat and ion events. Available only
                on recent Android Q+ kernels`,
        setEnabled: (cfg, val) => cfg.memHiFreq = val,
        isEnabled: (cfg) => cfg.memHiFreq
    }), mithril(record_widgets.Probe, {
        title: 'Low memory killer',
        img: 'rec_lmk.png',
        descr: `Record LMK events. Works both with the old in-kernel LMK
                and the newer userspace lmkd. It also tracks OOM score
                adjustments.`,
        setEnabled: (cfg, val) => cfg.memLmk = val,
        isEnabled: (cfg) => cfg.memLmk
    }), mithril(record_widgets.Probe, {
        title: 'Per process stats',
        img: 'rec_ps_stats.png',
        descr: `Periodically samples all processes in the system tracking:
                    their thread list, memory counters (RSS, swap and other
                    /proc/status counters) and oom_score_adj.`,
        setEnabled: (cfg, val) => cfg.procStats = val,
        isEnabled: (cfg) => cfg.procStats
    }, mithril(record_widgets.Slider, {
        title: 'Poll interval',
        cssClass: '.thin',
        values: POLL_INTERVAL_MS,
        unit: 'ms',
        set: (cfg, val) => cfg.procStatsPeriodMs = val,
        get: (cfg) => cfg.procStatsPeriodMs
    })), mithril(record_widgets.Probe, {
        title: 'Virtual memory stats',
        img: 'rec_vmstat.png',
        descr: `Periodically polls virtual memory stats from /proc/vmstat.
                    Allows to gather statistics about swap, eviction,
                    compression and pagecache efficiency`,
        setEnabled: (cfg, val) => cfg.vmstat = val,
        isEnabled: (cfg) => cfg.vmstat
    }, mithril(record_widgets.Slider, {
        title: 'Poll interval',
        cssClass: '.thin',
        values: POLL_INTERVAL_MS,
        unit: 'ms',
        set: (cfg, val) => cfg.vmstatPeriodMs = val,
        get: (cfg) => cfg.vmstatPeriodMs
    }), mithril(record_widgets.Dropdown, {
        title: 'Select counters',
        cssClass: '.multicolumn',
        options: vmstatOpts,
        set: (cfg, val) => cfg.vmstatCounters = val,
        get: (cfg) => cfg.vmstatCounters
    })));
}
function AndroidSettings(cssClass) {
    return mithril(`.record-section${cssClass}`, mithril(record_widgets.Probe, {
        title: 'Atrace userspace annotations',
        img: 'rec_atrace.png',
        descr: `Enables C++ / Java codebase annotations (ATRACE_BEGIN() /
                    os.Trace())`,
        setEnabled: (cfg, val) => cfg.atrace = val,
        isEnabled: (cfg) => cfg.atrace
    }, mithril(record_widgets.Dropdown, {
        title: 'Categories',
        cssClass: '.multicolumn.atrace-categories',
        options: ATRACE_CATEGORIES,
        set: (cfg, val) => cfg.atraceCats = val,
        get: (cfg) => cfg.atraceCats
    }), mithril(record_widgets.Textarea, {
        placeholder: 'Extra apps to profile, one per line, e.g.:\n' +
            'com.android.phone\n' +
            'com.android.nfc',
        set: (cfg, val) => cfg.atraceApps = val,
        get: (cfg) => cfg.atraceApps
    })), mithril(record_widgets.Probe, {
        title: 'Event log (logcat)',
        img: 'rec_logcat.png',
        descr: `Streams the event log into the trace. If no buffer filter is
                    specified, all buffers are selected.`,
        setEnabled: (cfg, val) => cfg.androidLogs = val,
        isEnabled: (cfg) => cfg.androidLogs
    }, mithril(record_widgets.Dropdown, {
        title: 'Buffers',
        cssClass: '.multicolumn',
        options: LOG_BUFFERS,
        set: (cfg, val) => cfg.androidLogBuffers = val,
        get: (cfg) => cfg.androidLogBuffers
    })), mithril(record_widgets.Probe, {
        title: 'Frame timeline',
        img: 'rec_frame_timeline.png',
        descr: `Records expected/actual frame timings from surface_flinger.
                    Requires Android 12 (S) or above.`,
        setEnabled: (cfg, val) => cfg.androidFrameTimeline = val,
        isEnabled: (cfg) => cfg.androidFrameTimeline
    }));
}
function ChromeSettings(cssClass) {
    return mithril(`.record-section${cssClass}`, mithril(record_widgets.Probe, {
        title: 'Task scheduling',
        img: null,
        descr: `Records events about task scheduling and execution on all
                  threads`,
        setEnabled: (cfg, val) => cfg.taskScheduling = val,
        isEnabled: (cfg) => cfg.taskScheduling
    }), mithril(record_widgets.Probe, {
        title: 'IPC flows',
        img: null,
        descr: `Records flow events for passing of IPC messages between
                processes.`,
        setEnabled: (cfg, val) => cfg.ipcFlows = val,
        isEnabled: (cfg) => cfg.ipcFlows
    }), mithril(record_widgets.Probe, {
        title: 'Javascript execution',
        img: null,
        descr: `Records events about Javascript execution in the renderer
                    processes.`,
        setEnabled: (cfg, val) => cfg.jsExecution = val,
        isEnabled: (cfg) => cfg.jsExecution
    }), mithril(record_widgets.Probe, {
        title: 'Web content rendering',
        img: null,
        descr: `Records events about rendering, layout, and compositing of
        web content in Blink.`,
        setEnabled: (cfg, val) => cfg.webContentRendering = val,
        isEnabled: (cfg) => cfg.webContentRendering
    }), mithril(record_widgets.Probe, {
        title: 'UI rendering & compositing',
        img: null,
        descr: `Records events about rendering of browser UI surfaces and
        compositing of surfaces.`,
        setEnabled: (cfg, val) => cfg.uiRendering = val,
        isEnabled: (cfg) => cfg.uiRendering
    }), mithril(record_widgets.Probe, {
        title: 'Input events',
        img: null,
        descr: `Records input events and their flow between processes.`,
        setEnabled: (cfg, val) => cfg.inputEvents = val,
        isEnabled: (cfg) => cfg.inputEvents
    }), mithril(record_widgets.Probe, {
        title: 'Navigation & Loading',
        img: null,
        descr: `Records network events for navigations and resources.`,
        setEnabled: (cfg, val) => cfg.navigationAndLoading = val,
        isEnabled: (cfg) => cfg.navigationAndLoading
    }), mithril(record_widgets.Probe, {
        title: 'Chrome Logs',
        img: null,
        descr: `Records Chrome log messages`,
        setEnabled: (cfg, val) => cfg.chromeLogs = val,
        isEnabled: (cfg) => cfg.chromeLogs
    }), ChromeCategoriesSelection());
}
function ChromeCategoriesSelection() {
    // If we are attempting to record via the Chrome extension, we receive the
    // list of actually supported categories via DevTools. Otherwise, we fall back
    // to an integrated list of categories from a recent version of Chrome.
    let categories = globals$1.globals.state.chromeCategories;
    if (!categories || !state.isChromeTarget(globals$1.globals.state.recordingTarget)) {
        categories = state.getBuiltinChromeCategoryList();
    }
    // Show "disabled-by-default" categories last.
    const categoriesMap = new Map();
    const disabledPrefix = 'disabled-by-default-';
    const overheadSuffix = '(high overhead)';
    categories.forEach(cat => {
        if (cat.startsWith(disabledPrefix)) {
            categoriesMap.set(cat, `${cat.replace(disabledPrefix, '')} ${overheadSuffix}`);
        }
        else {
            categoriesMap.set(cat, cat);
        }
    });
    return mithril(record_widgets.Dropdown, {
        title: 'Additional Chrome categories',
        cssClass: '.multicolumn.two-columns',
        options: categoriesMap,
        set: (cfg, val) => cfg.chromeCategoriesSelected = val,
        get: (cfg) => cfg.chromeCategoriesSelected,
        sort: (a, b) => {
            const aIsDisabled = a.includes(overheadSuffix);
            const bIsDisabled = b.includes(overheadSuffix);
            if (aIsDisabled === bIsDisabled) {
                return a.localeCompare(b);
            }
            else {
                return Number(aIsDisabled) - Number(bIsDisabled);
            }
        },
    });
}
function AdvancedSettings(cssClass) {
    const S = (x) => x * 1000;
    const M = (x) => x * 1000 * 60;
    return mithril(`.record-section${cssClass}`, mithril(record_widgets.Probe, {
        title: 'Advanced ftrace config',
        img: 'rec_ftrace.png',
        descr: `Enable individual events and tune the kernel-tracing (ftrace)
                  module. The events enabled here are in addition to those from
                  enabled by other probes.`,
        setEnabled: (cfg, val) => cfg.ftrace = val,
        isEnabled: (cfg) => cfg.ftrace
    }, mithril(record_widgets.Slider, {
        title: 'Buf size',
        cssClass: '.thin',
        values: [512, 1024, 2 * 1024, 4 * 1024, 16 * 1024, 32 * 1024],
        unit: 'KB',
        set: (cfg, val) => cfg.ftraceBufferSizeKb = val,
        get: (cfg) => cfg.ftraceBufferSizeKb
    }), mithril(record_widgets.Slider, {
        title: 'Drain rate',
        cssClass: '.thin',
        values: [100, 250, 500, 1000, 2500, 5000],
        unit: 'ms',
        set: (cfg, val) => cfg.ftraceDrainPeriodMs = val,
        get: (cfg) => cfg.ftraceDrainPeriodMs
    }), mithril(record_widgets.Dropdown, {
        title: 'Event groups',
        cssClass: '.multicolumn.ftrace-events',
        options: FTRACE_CATEGORIES,
        set: (cfg, val) => cfg.ftraceEvents = val,
        get: (cfg) => cfg.ftraceEvents
    }), mithril(record_widgets.Textarea, {
        placeholder: 'Add extra events, one per line, e.g.:\n' +
            'sched/sched_switch\n' +
            'kmem/*',
        set: (cfg, val) => cfg.ftraceExtraEvents = val,
        get: (cfg) => cfg.ftraceExtraEvents
    })), globals$1.globals.state.videoEnabled ?
        mithril(record_widgets.Probe, {
            title: 'Screen recording',
            img: null,
            descr: `Records the screen along with running a trace. Max
                  time of recording is 3 minutes (180 seconds).`,
            setEnabled: (cfg, val) => cfg.screenRecord = val,
            isEnabled: (cfg) => cfg.screenRecord,
        }, mithril(record_widgets.Slider, {
            title: 'Max duration',
            icon: 'timer',
            values: [S(10), S(15), S(30), S(60), M(2), M(3)],
            isTime: true,
            unit: 'm:s',
            set: (cfg, val) => cfg.durationMs = val,
            get: (cfg) => cfg.durationMs,
        })) :
        null);
}
function RecordHeader() {
    return mithril('.record-header', mithril('.top-part', mithril('.target-and-status', RecordingPlatformSelection(), RecordingStatusLabel(), ErrorLabel()), recordingButtons()), RecordingNotes());
}
function RecordingPlatformSelection() {
    if (globals$1.globals.state.recordingInProgress)
        return [];
    const availableAndroidDevices = globals$1.globals.state.availableAdbDevices;
    const recordingTarget = globals$1.globals.state.recordingTarget;
    const targets = [];
    for (const { os, name } of state.getDefaultRecordingTargets()) {
        targets.push(mithril('option', { value: os }, name));
    }
    for (const d of availableAndroidDevices) {
        targets.push(mithril('option', { value: d.serial }, d.name));
    }
    const selectedIndex = state.isAdbTarget(recordingTarget) ?
        targets.findIndex(node => node.attrs.value === recordingTarget.serial) :
        targets.findIndex(node => node.attrs.value === recordingTarget.os);
    return mithril('.target', mithril('label', 'Target platform:', mithril('select', {
        selectedIndex,
        onchange: (e) => {
            onTargetChange(e.target.value);
        },
        onupdate: (select) => {
            // Work around mithril bug
            // (https://github.com/MithrilJS/mithril.js/issues/2107): We may
            // update the select's options while also changing the
            // selectedIndex at the same time. The update of selectedIndex
            // may be applied before the new options are added to the select
            // element. Because the new selectedIndex may be outside of the
            // select's options at that time, we have to reselect the
            // correct index here after any new children were added.
            select.dom.selectedIndex = selectedIndex;
        }
    }, ...targets)), mithril('.chip', { onclick: addAndroidDevice }, mithril('button', 'Add ADB Device'), mithril('i.material-icons', 'add')));
}
// |target| can be the TargetOs or the android serial.
function onTargetChange(target) {
    const recordingTarget = globals$1.globals.state.availableAdbDevices.find(d => d.serial === target) ||
        state.getDefaultRecordingTargets().find(t => t.os === target) ||
        state.getDefaultRecordingTargets()[0];
    if (state.isChromeTarget(recordingTarget)) {
        globals$1.globals.dispatch(actions.Actions.setUpdateChromeCategories({ update: true }));
    }
    globals$1.globals.dispatch(actions.Actions.setRecordingTarget({ target: recordingTarget }));
    globals$1.globals.rafScheduler.scheduleFullRedraw();
}
function Instructions(cssClass) {
    return mithril(`.record-section.instructions${cssClass}`, mithril('header', 'Recording command'), localStorage.hasOwnProperty(LOCAL_STORAGE_SHOW_CONFIG) ?
        mithril('button.permalinkconfig', {
            onclick: () => {
                globals$1.globals.dispatch(actions.Actions.createPermalink({ isRecordingConfig: true }));
            },
        }, 'Share recording settings') :
        null, RecordingSnippet(), BufferUsageProgressBar(), mithril('.buttons', StopCancelButtons()), recordingLog());
}
function displayRecordConfigs() {
    return record_config.recordConfigStore.recordConfigs.map((item) => {
        return mithril('.config', [
            mithril('span.title-config', item.title),
            mithril('button', {
                class: 'config-button load',
                onclick: () => {
                    globals$1.globals.dispatch(actions.Actions.setRecordConfig({ config: item.config }));
                    globals$1.globals.rafScheduler.scheduleFullRedraw();
                }
            }, 'load'),
            mithril('button', {
                class: 'config-button delete',
                onclick: () => {
                    record_config.recordConfigStore.delete(item.key);
                    globals$1.globals.rafScheduler.scheduleFullRedraw();
                }
            }, 'delete'),
        ]);
    });
}
function getSavedConfigList() {
    if (record_config.recordConfigStore.recordConfigs.length === 0) {
        return [];
    }
    return displayRecordConfigs();
}
exports.ConfigTitleState = {
    title: '',
    getTitle: () => {
        return exports.ConfigTitleState.title;
    },
    setTitle: (value) => {
        exports.ConfigTitleState.title = value;
    },
    clearTitle: () => {
        exports.ConfigTitleState.title = '';
    }
};
function Configurations(cssClass) {
    return mithril(`.record-section${cssClass}`, mithril('header', 'Save and load configurations'), mithril('.input-config', [
        mithril('input', {
            value: exports.ConfigTitleState.title,
            placeholder: 'Title for config',
            oninput() {
                exports.ConfigTitleState.setTitle(this.value);
            }
        }),
        mithril('button', {
            class: 'config-button save',
            onclick: () => {
                record_config.recordConfigStore.save(globals$1.globals.state.recordConfig, exports.ConfigTitleState.getTitle());
                globals$1.globals.rafScheduler.scheduleFullRedraw();
                exports.ConfigTitleState.clearTitle();
            }
        }, 'Save current config')
    ]), getSavedConfigList());
}
function BufferUsageProgressBar() {
    if (!globals$1.globals.state.recordingInProgress)
        return [];
    const bufferUsage = globals$1.globals.bufferUsage ? globals$1.globals.bufferUsage : 0.0;
    // Buffer usage is not available yet on Android.
    if (bufferUsage === 0)
        return [];
    return mithril('label', 'Buffer usage: ', mithril('progress', { max: 100, value: bufferUsage * 100 }));
}
function RecordingNotes() {
    const sideloadUrl = 'https://perfetto.dev/docs/contributing/build-instructions#get-the-code';
    const linuxUrl = 'https://perfetto.dev/docs/quickstart/linux-tracing';
    const cmdlineUrl = 'https://perfetto.dev/docs/quickstart/android-tracing#perfetto-cmdline';
    const extensionURL = `https://chrome.google.com/webstore/detail/
      perfetto-ui/lfmkphfpdbjijhpomgecfikhfohaoine`;
    const notes = [];
    const msgFeatNotSupported = mithril('span', `Some probes are only supported in Perfetto versions running
      on Android Q+. `);
    const msgPerfettoNotSupported = mithril('span', `Perfetto is not supported natively before Android P. `);
    const msgSideload = mithril('span', `If you have a rooted device you can `, mithril('a', { href: sideloadUrl, target: '_blank' }, `sideload the latest version of
         Perfetto.`));
    const msgRecordingNotSupported = mithril('.note', `Recording Perfetto traces from the UI is not supported natively
     before Android Q. If you are using a P device, please select 'Android P'
     as the 'Target Platform' and `, mithril('a', { href: cmdlineUrl, target: '_blank' }, `collect the trace using ADB.`));
    const msgChrome = mithril('.note', `To trace Chrome from the Perfetto UI, you need to install our `, mithril('a', { href: extensionURL, target: '_blank' }, 'Chrome extension'), ' and then reload this page.');
    const msgLinux = mithril('.note', `Use this `, mithril('a', { href: linuxUrl, target: '_blank' }, `quickstart guide`), ` to get started with tracing on Linux.`);
    const msgLongTraces = mithril('.note', `Recording in long trace mode through the UI is not supported. Please copy
    the command and `, mithril('a', { href: cmdlineUrl, target: '_blank' }, `collect the trace using ADB.`));
    const msgZeroProbes = mithril('.note', 'It looks like you didn\'t add any probes. ' +
        'Please add at least one to get a non-empty trace.');
    if (!state.hasActiveProbes(globals$1.globals.state.recordConfig)) {
        notes.push(msgZeroProbes);
    }
    if (state.isAdbTarget(globals$1.globals.state.recordingTarget)) {
        notes.push(msgRecordingNotSupported);
    }
    switch (globals$1.globals.state.recordingTarget.os) {
        case 'Q':
            break;
        case 'P':
            notes.push(mithril('.note', msgFeatNotSupported, msgSideload));
            break;
        case 'O':
            notes.push(mithril('.note', msgPerfettoNotSupported, msgSideload));
            break;
        case 'L':
            notes.push(msgLinux);
            break;
        case 'C':
            if (!globals$1.globals.state.extensionInstalled)
                notes.push(msgChrome);
            break;
        case 'CrOS':
            if (!globals$1.globals.state.extensionInstalled)
                notes.push(msgChrome);
            break;
    }
    if (globals$1.globals.state.recordConfig.mode === 'LONG_TRACE') {
        notes.unshift(msgLongTraces);
    }
    return notes.length > 0 ? mithril('div', notes) : [];
}
function RecordingSnippet() {
    const target = globals$1.globals.state.recordingTarget;
    // We don't need commands to start tracing on chrome
    if (state.isChromeTarget(target)) {
        return globals$1.globals.state.extensionInstalled ?
            mithril('div', mithril('label', `To trace Chrome from the Perfetto UI you just have to press
         'Start Recording'.`)) :
            [];
    }
    return mithril(record_widgets.CodeSnippet, { text: getRecordCommand(target) });
}
function getRecordCommand(target) {
    const data = globals$1.globals.trackDataStore.get('config');
    const cfg = globals$1.globals.state.recordConfig;
    let time = cfg.durationMs / 1000;
    if (time > state_2.MAX_TIME) {
        time = state_2.MAX_TIME;
    }
    const pbBase64 = data ? data.pbBase64 : '';
    const pbtx = data ? data.pbtxt : '';
    let cmd = '';
    if (cfg.screenRecord) {
        // Half-second delay to ensure Perfetto starts tracing before screenrecord
        // starts recording
        cmd += `(sleep 0.5 && adb shell screenrecord --time-limit ${time}`;
        cmd += ' "/sdcard/tracescr.mp4") &\\\n';
    }
    if (state.isAndroidP(target)) {
        cmd += `echo '${pbBase64}' | \n`;
        cmd += 'base64 --decode | \n';
        cmd += 'adb shell "perfetto -c - -o /data/misc/perfetto-traces/trace"\n';
    }
    else {
        cmd +=
            state.isAndroidTarget(target) ? 'adb shell perfetto \\\n' : 'perfetto \\\n';
        cmd += '  -c - --txt \\\n';
        cmd += '  -o /data/misc/perfetto-traces/trace \\\n';
        cmd += '<<EOF\n\n';
        cmd += pbtx;
        cmd += '\nEOF\n';
    }
    return cmd;
}
function recordingButtons() {
    const state$1 = globals$1.globals.state;
    const target = state$1.recordingTarget;
    const recInProgress = state$1.recordingInProgress;
    const start = mithril(`button`, {
        class: recInProgress ? '' : 'selected',
        onclick: onStartRecordingPressed
    }, 'Start Recording');
    const buttons = [];
    if (state.isAndroidTarget(target)) {
        if (!recInProgress && state.isAdbTarget(target) &&
            globals$1.globals.state.recordConfig.mode !== 'LONG_TRACE') {
            buttons.push(start);
        }
    }
    else if (state.isChromeTarget(target) && state$1.extensionInstalled) {
        buttons.push(start);
    }
    return mithril('.button', buttons);
}
function StopCancelButtons() {
    if (!globals$1.globals.state.recordingInProgress)
        return [];
    const stop = mithril(`button.selected`, { onclick: () => globals$1.globals.dispatch(actions.Actions.stopRecording({})) }, 'Stop');
    const cancel = mithril(`button`, { onclick: () => globals$1.globals.dispatch(actions.Actions.cancelRecording({})) }, 'Cancel');
    return [stop, cancel];
}
function onStartRecordingPressed() {
    location.href = '#!/record?p=instructions';
    globals$1.globals.rafScheduler.scheduleFullRedraw();
    const target = globals$1.globals.state.recordingTarget;
    if (state.isAndroidTarget(target) || state.isChromeTarget(target)) {
        globals$1.globals.logging.logEvent('Record Trace', `Record trace (${target.os})`);
        globals$1.globals.dispatch(actions.Actions.startRecording({}));
    }
}
function RecordingStatusLabel() {
    const recordingStatus = globals$1.globals.state.recordingStatus;
    if (!recordingStatus)
        return [];
    return mithril('label', recordingStatus);
}
function ErrorLabel() {
    const lastRecordingError = globals$1.globals.state.lastRecordingError;
    if (!lastRecordingError)
        return [];
    return mithril('label.error-label', `Error:  ${lastRecordingError}`);
}
function recordingLog() {
    const logs = globals$1.globals.recordingLog;
    if (logs === undefined)
        return [];
    return mithril('.code-snippet.no-top-bar', mithril('code', logs));
}
// The connection must be done in the frontend. After it, the serial ID will
// be inserted in the state, and the worker will be able to connect to the
// correct device.
function addAndroidDevice() {
    return tslib.__awaiter(this, void 0, void 0, function* () {
        let device;
        try {
            device = yield new adb.AdbOverWebUsb().findDevice();
        }
        catch (e) {
            const err = `No device found: ${e.name}: ${e.message}`;
            console.error(err, e);
            alert(err);
            return;
        }
        if (!device.serialNumber) {
            console.error('serial number undefined');
            return;
        }
        // After the user has selected a device with the chrome UI, it will be
        // available when listing all the available device from WebUSB. Therefore,
        // we update the list of available devices.
        yield updateAvailableAdbDevices(device.serialNumber);
    });
}
function updateAvailableAdbDevices(preferredDeviceSerial) {
    return tslib.__awaiter(this, void 0, void 0, function* () {
        const devices = yield new adb.AdbOverWebUsb().getPairedDevices();
        let recordingTarget = undefined;
        const availableAdbDevices = [];
        devices.forEach(d => {
            if (d.productName && d.serialNumber) {
                // TODO(nicomazz): At this stage, we can't know the OS version, so we
                // assume it is 'Q'. This can create problems with devices with an old
                // version of perfetto. The os detection should be done after the adb
                // connection, from adb_record_controller
                availableAdbDevices.push({ name: d.productName, serial: d.serialNumber, os: 'Q' });
                if (preferredDeviceSerial && preferredDeviceSerial === d.serialNumber) {
                    recordingTarget = availableAdbDevices[availableAdbDevices.length - 1];
                }
            }
        });
        globals$1.globals.dispatch(actions.Actions.setAvailableAdbDevices({ devices: availableAdbDevices }));
        selectAndroidDeviceIfAvailable(availableAdbDevices, recordingTarget);
        globals$1.globals.rafScheduler.scheduleFullRedraw();
        return availableAdbDevices;
    });
}
exports.updateAvailableAdbDevices = updateAvailableAdbDevices;
function selectAndroidDeviceIfAvailable(availableAdbDevices, recordingTarget) {
    if (!recordingTarget) {
        recordingTarget = globals$1.globals.state.recordingTarget;
    }
    const deviceConnected = state.isAdbTarget(recordingTarget);
    const connectedDeviceDisconnected = deviceConnected &&
        availableAdbDevices.find(e => e.serial === recordingTarget.serial) ===
            undefined;
    if (availableAdbDevices.length) {
        // If there's an Android device available and the current selection isn't
        // one, select the Android device by default. If the current device isn't
        // available anymore, but another Android device is, select the other
        // Android device instead.
        if (!deviceConnected || connectedDeviceDisconnected) {
            recordingTarget = availableAdbDevices[0];
        }
        globals$1.globals.dispatch(actions.Actions.setRecordingTarget({ target: recordingTarget }));
        return;
    }
    // If the currently selected device was disconnected, reset the recording
    // target to the default one.
    if (connectedDeviceDisconnected) {
        globals$1.globals.dispatch(actions.Actions.setRecordingTarget({ target: state.getDefaultRecordingTargets()[0] }));
    }
}
function recordMenu(routePage) {
    const target = globals$1.globals.state.recordingTarget;
    const chromeProbe = mithril('a[href="#!/record?p=chrome"]', mithril(`li${routePage === 'chrome' ? '.active' : ''}`, mithril('i.material-icons', 'laptop_chromebook'), mithril('.title', 'Chrome'), mithril('.sub', 'Chrome traces')));
    const recInProgress = globals$1.globals.state.recordingInProgress;
    return mithril('.record-menu', {
        class: recInProgress ? 'disabled' : '',
        onclick: () => globals$1.globals.rafScheduler.scheduleFullRedraw()
    }, mithril('header', 'Trace config'), mithril('ul', mithril('a[href="#!/record?p=buffers"]', mithril(`li${routePage === 'buffers' ? '.active' : ''}`, mithril('i.material-icons', 'tune'), mithril('.title', 'Recording settings'), mithril('.sub', 'Buffer mode, size and duration'))), mithril('a[href="#!/record?p=instructions"]', mithril(`li${routePage === 'instructions' ? '.active' : ''}`, mithril('i.material-icons.rec', 'fiber_manual_record'), mithril('.title', 'Recording command'), mithril('.sub', 'Manually record trace'))), localStorage.hasOwnProperty(LOCAL_STORAGE_SHOW_CONFIG) ?
        mithril('a[href="#!/record?p=config"]', {
            onclick: () => {
                record_config.recordConfigStore.reloadFromLocalStorage();
            }
        }, mithril(`li${routePage === 'config' ? '.active' : ''}`, mithril('i.material-icons', 'tune'), mithril('.title', 'Saved configs'), mithril('.sub', 'Manage local configs'))) :
        null), mithril('header', 'Probes'), mithril('ul', state.isChromeTarget(target) && !state.isCrOSTarget(target) ? [chromeProbe] : [
        mithril('a[href="#!/record?p=cpu"]', mithril(`li${routePage === 'cpu' ? '.active' : ''}`, mithril('i.material-icons', 'subtitles'), mithril('.title', 'CPU'), mithril('.sub', 'CPU usage, scheduling, wakeups'))),
        mithril('a[href="#!/record?p=gpu"]', mithril(`li${routePage === 'gpu' ? '.active' : ''}`, mithril('i.material-icons', 'aspect_ratio'), mithril('.title', 'GPU'), mithril('.sub', 'GPU frequency, memory'))),
        mithril('a[href="#!/record?p=power"]', mithril(`li${routePage === 'power' ? '.active' : ''}`, mithril('i.material-icons', 'battery_charging_full'), mithril('.title', 'Power'), mithril('.sub', 'Battery and other energy counters'))),
        mithril('a[href="#!/record?p=memory"]', mithril(`li${routePage === 'memory' ? '.active' : ''}`, mithril('i.material-icons', 'memory'), mithril('.title', 'Memory'), mithril('.sub', 'Physical mem, VM, LMK'))),
        mithril('a[href="#!/record?p=android"]', mithril(`li${routePage === 'android' ? '.active' : ''}`, mithril('i.material-icons', 'android'), mithril('.title', 'Android apps & svcs'), mithril('.sub', 'atrace and logcat'))),
        chromeProbe,
        mithril('a[href="#!/record?p=advanced"]', mithril(`li${routePage === 'advanced' ? '.active' : ''}`, mithril('i.material-icons', 'settings'), mithril('.title', 'Advanced settings'), mithril('.sub', 'Complicated stuff for wizards')))
    ]));
}
exports.RecordPage = pages.createPage({
    view() {
        const SECTIONS = {
            buffers: RecSettings,
            instructions: Instructions,
            config: Configurations,
            cpu: CpuSettings,
            gpu: GpuSettings,
            power: PowerSettings,
            memory: MemorySettings,
            android: AndroidSettings,
            chrome: ChromeSettings,
            advanced: AdvancedSettings,
        };
        const pages = [];
        const routePageParam = router$1.Router.param('p');
        let routePage = typeof routePageParam === 'string' ? routePageParam : '';
        if (!Object.keys(SECTIONS).includes(routePage)) {
            routePage = 'buffers';
        }
        for (const key of Object.keys(SECTIONS)) {
            const cssClass = routePage === key ? '.active' : '';
            pages.push(SECTIONS[key](cssClass));
        }
        return mithril('.record-page', globals$1.globals.state.recordingInProgress ? mithril('.hider') : [], mithril('.record-container', RecordHeader(), recordMenu(routePage), pages));
    }
});

});

var http_utils = createCommonjsModule(function (module, exports) {
// Copyright (C) 2019 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.
Object.defineProperty(exports, "__esModule", { value: true });
exports.fetchWithTimeout = void 0;
function fetchWithTimeout(input, init, timeoutMs) {
    return new Promise((resolve, reject) => {
        const timer = setTimeout(() => reject(new Error(`fetch(${input}) timed out after ${timeoutMs} ms`)), timeoutMs);
        fetch(input, init)
            .then(response => resolve(response))
            .catch(err => reject(err))
            .finally(() => clearTimeout(timer));
    });
}
exports.fetchWithTimeout = fetchWithTimeout;

});

var engine = createCommonjsModule(function (module, exports) {
// 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.
Object.defineProperty(exports, "__esModule", { value: true });
exports.Engine = exports.QueryError = exports.NullLoadingTracker = void 0;




class NullLoadingTracker {
    beginLoading() { }
    endLoading() { }
}
exports.NullLoadingTracker = NullLoadingTracker;
class QueryError extends Error {
}
exports.QueryError = QueryError;
/**
 * Abstract interface of a trace proccessor.
 * This is the TypeScript equivalent of src/trace_processor/rpc.h.
 *
 * Engine also defines helpers for the most common service methods
 * (e.g. query).
 */
class Engine {
    constructor(tracker) {
        this.loadingTracker = tracker ? tracker : new NullLoadingTracker();
    }
    /**
     * Shorthand for sending a SQL query to the engine.
     * Deals with {,un}marshalling of request/response args.
     */
    query(sqlQuery) {
        return tslib.__awaiter(this, void 0, void 0, function* () {
            const result = yield this.uncheckedQuery(sqlQuery);
            if (result.error) {
                throw new QueryError(`Query error "${sqlQuery}": ${result.error}`);
            }
            return result;
        });
    }
    // This method is for noncritical queries that shouldn't throw an error
    // on failure. The caller must handle the failure.
    uncheckedQuery(sqlQuery) {
        return tslib.__awaiter(this, void 0, void 0, function* () {
            this.loadingTracker.beginLoading();
            try {
                const args = new protos_1.RawQueryArgs();
                args.sqlQuery = sqlQuery;
                args.timeQueuedNs = Math.floor(performance.now() * 1e6);
                const argsEncoded = protos_1.RawQueryArgs.encode(args).finish();
                const respEncoded = yield this.rawQuery(argsEncoded);
                const result = protos_1.RawQueryResult.decode(respEncoded);
                return result;
            }
            finally {
                this.loadingTracker.endLoading();
            }
        });
    }
    /**
     * Shorthand for sending a compute metrics request to the engine.
     * Deals with {,un}marshalling of request/response args.
     */
    computeMetric(metrics) {
        return tslib.__awaiter(this, void 0, void 0, function* () {
            const args = new protos_1.ComputeMetricArgs();
            args.metricNames = metrics;
            args.format = protos_1.ComputeMetricArgs.ResultFormat.TEXTPROTO;
            const argsEncoded = protos_1.ComputeMetricArgs.encode(args).finish();
            const respEncoded = yield this.rawComputeMetric(argsEncoded);
            const result = protos_1.ComputeMetricResult.decode(respEncoded);
            if (result.error.length > 0) {
                throw new QueryError(result.error);
            }
            return result;
        });
    }
    queryOneRow(query) {
        return tslib.__awaiter(this, void 0, void 0, function* () {
            const result = yield this.query(query);
            const res = [];
            if (query_iterator.slowlyCountRows(result) === 0)
                return res;
            for (const col of result.columns) {
                if (col.longValues.length === 0) {
                    console.error(`queryOneRow should only be used for queries that return long values
             : ${query}`);
                    throw new Error(`queryOneRow should only be used for queries that return long values
             : ${query}`);
                }
                res.push(+col.longValues[0]);
            }
            return res;
        });
    }
    // TODO(hjd): When streaming must invalidate this somehow.
    getCpus() {
        return tslib.__awaiter(this, void 0, void 0, function* () {
            if (!this._cpus) {
                const result = yield this.query('select distinct(cpu) from sched order by cpu;');
                if (query_iterator.slowlyCountRows(result) === 0)
                    return [];
                this._cpus = result.columns[0].longValues.map(n => +n);
            }
            return this._cpus;
        });
    }
    getNumberOfGpus() {
        return tslib.__awaiter(this, void 0, void 0, function* () {
            if (!this._numGpus) {
                const result = yield this.query(`
        select count(distinct(gpu_id)) as gpuCount
        from gpu_counter_track
        where name = 'gpufreq';
      `);
                this._numGpus = +result.columns[0].longValues[0];
            }
            return this._numGpus;
        });
    }
    // TODO: This should live in code that's more specific to chrome, instead of
    // in engine.
    getNumberOfProcesses() {
        return tslib.__awaiter(this, void 0, void 0, function* () {
            const result = yield this.query('select count(*) from process;');
            return +result.columns[0].longValues[0];
        });
    }
    getTraceTimeBounds() {
        return tslib.__awaiter(this, void 0, void 0, function* () {
            const query = `select start_ts, end_ts from trace_bounds`;
            const res = (yield this.queryOneRow(query));
            return new time.TimeSpan(res[0] / 1e9, res[1] / 1e9);
        });
    }
    getTracingMetadataTimeBounds() {
        return tslib.__awaiter(this, void 0, void 0, function* () {
            const query = yield this.query(`select name, int_value from metadata
         where name = 'tracing_started_ns' or name = 'tracing_disabled_ns'
         or name = 'all_data_source_started_ns'`);
            let startBound = -Infinity;
            let endBound = Infinity;
            const it = query_iterator.iter({ 'name': query_iterator.STR, 'int_value': query_iterator.NUM_NULL }, query);
            for (; it.valid(); it.next()) {
                const columnName = it.row.name;
                const timestamp = it.row.int_value;
                if (timestamp === null)
                    continue;
                if (columnName === 'tracing_disabled_ns') {
                    endBound = Math.min(endBound, timestamp / 1e9);
                }
                else {
                    startBound = Math.max(startBound, timestamp / 1e9);
                }
            }
            return new time.TimeSpan(startBound, endBound);
        });
    }
}
exports.Engine = Engine;

});

var http_rpc_engine = createCommonjsModule(function (module, exports) {
// Copyright (C) 2019 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.
Object.defineProperty(exports, "__esModule", { value: true });
exports.HttpRpcEngine = exports.RPC_URL = void 0;






exports.RPC_URL = 'http://127.0.0.1:9001/';
const RPC_CONNECT_TIMEOUT_MS = 2000;
class HttpRpcEngine extends engine.Engine {
    constructor(id, loadingTracker) {
        super(loadingTracker);
        this.nextReqId = 0;
        this.sessionId = undefined;
        this.requestQueue = new Array();
        this.pendingRequest = undefined;
        this.errorHandler = () => { };
        this.id = id;
    }
    parse(data) {
        return tslib.__awaiter(this, void 0, void 0, function* () {
            yield this.enqueueRequest('parse', data);
        });
    }
    notifyEof() {
        return tslib.__awaiter(this, void 0, void 0, function* () {
            yield this.enqueueRequest('notify_eof');
        });
    }
    restoreInitialTables() {
        return tslib.__awaiter(this, void 0, void 0, function* () {
            yield this.enqueueRequest('restore_initial_tables');
        });
    }
    rawQuery(rawQueryArgs) {
        return this.enqueueRequest('raw_query', rawQueryArgs);
    }
    rawComputeMetric(rawComputeMetricArgs) {
        return this.enqueueRequest('compute_metric', rawComputeMetricArgs);
    }
    enableMetatrace() {
        return tslib.__awaiter(this, void 0, void 0, function* () {
            yield this.enqueueRequest('enable_metatrace');
        });
    }
    disableAndReadMetatrace() {
        return this.enqueueRequest('disable_and_read_metatrace');
    }
    enqueueRequest(methodName, data) {
        const resp = deferred.defer();
        const req = { methodName, reqData: data, resp, id: this.nextReqId++ };
        if (this.pendingRequest === undefined) {
            this.beginFetch(req);
        }
        else {
            this.requestQueue.push(req);
        }
        return resp;
    }
    beginFetch(req) {
        logging.assertTrue(this.pendingRequest === undefined);
        this.pendingRequest = req;
        const methodName = req.methodName.toLowerCase();
        // Deliberately not using fetchWithTimeout() here. These queries can be
        // arbitrarily long.
        // Deliberately not setting cache: no-cache. Doing so invalidates also the
        // CORS pre-flight responses, causing one OPTIONS request for each POST.
        // no-cache is also useless because trace-processor's replies are already
        // marked as no-cache and browsers generally already assume that POST
        // requests are not idempotent.
        fetch(exports.RPC_URL + methodName, {
            method: 'post',
            headers: {
                'Content-Type': 'application/x-protobuf',
                'X-Seq-Id': `${req.id}`,
            },
            body: req.reqData || new Uint8Array(),
        })
            .then(resp => this.endFetch(resp, req.id))
            .catch(err => this.errorHandler(err));
    }
    endFetch(resp, expectedReqId) {
        const req = logging.assertExists(this.pendingRequest);
        this.pendingRequest = undefined;
        logging.assertTrue(expectedReqId === req.id);
        if (resp.status !== 200) {
            req.resp.reject(`HTTP ${resp.status} - ${resp.statusText}`);
            return;
        }
        if (req.methodName === 'restore_initial_tables') {
            // restore_initial_tables resets the trace processor session id
            // so make sure to also reset on our end for future queries.
            this.sessionId = undefined;
        }
        else {
            const sessionId = resp.headers.get('X-TP-Session-ID') || undefined;
            if (this.sessionId !== undefined && sessionId !== this.sessionId) {
                req.resp.reject(`The trace processor HTTP session does not match the initally seen
             ID.

             This can happen when using a HTTP trace processor instance and
             either accidentally sharing this between multiple tabs or
             restarting the trace processor while still in use by UI.

             Please refresh this tab and ensure that trace processor is used by
             at most one tab at a time.

             Technical details:
             Expected session id: ${this.sessionId}
             Actual session id: ${sessionId}`);
                return;
            }
            this.sessionId = sessionId;
        }
        resp.arrayBuffer().then(arrBuf => {
            // Note: another request can sneak in via enqueueRequest() between the
            // arrayBuffer() call and this continuation. At this point
            // this.pendingRequest might be set again.
            // If not (the most common case) submit the next queued request, if any.
            this.maybeSubmitNextQueuedRequest();
            req.resp.resolve(new Uint8Array(arrBuf));
        });
    }
    maybeSubmitNextQueuedRequest() {
        if (this.pendingRequest === undefined && this.requestQueue.length > 0) {
            this.beginFetch(this.requestQueue.shift());
        }
    }
    static checkConnection() {
        return tslib.__awaiter(this, void 0, void 0, function* () {
            const httpRpcState = { connected: false };
            console.info(`It's safe to ignore the ERR_CONNECTION_REFUSED on ${exports.RPC_URL} below. ` +
                `That might happen while probing the exernal native accelerator. The ` +
                `error is non-fatal and unlikely to be the culprit for any UI bug.`);
            try {
                const resp = yield http_utils.fetchWithTimeout(exports.RPC_URL + 'status', { method: 'post', cache: 'no-cache' }, RPC_CONNECT_TIMEOUT_MS);
                if (resp.status !== 200) {
                    httpRpcState.failure = `${resp.status} - ${resp.statusText}`;
                }
                else {
                    const buf = new Uint8Array(yield resp.arrayBuffer());
                    const status = protos_1.StatusResult.decode(buf);
                    httpRpcState.connected = true;
                    if (status.loadedTraceName) {
                        httpRpcState.loadedTraceName = status.loadedTraceName;
                    }
                }
            }
            catch (err) {
                httpRpcState.failure = `${err}`;
            }
            return httpRpcState;
        });
    }
}
exports.HttpRpcEngine = HttpRpcEngine;

});

var rpc_http_dialog = createCommonjsModule(function (module, exports) {
// 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.
Object.defineProperty(exports, "__esModule", { value: true });
exports.CheckHttpRpcConnection = void 0;







const PROMPT = `Trace Processor Native Accelerator detected on ${http_rpc_engine.RPC_URL} with:
$loadedTraceName

YES, use loaded trace:
Will load from the current state of Trace Processor. If you did run
trace_processor_shell --httpd file.pftrace this is likely what you want.

YES, but reset state:
Use this if you want to open another trace but still use the
accelerator. This is the equivalent of killing and restarting
trace_processor_shell --httpd.

NO, Use builtin WASM:
Will not use the accelerator in this tab.

Using the native accelerator has some minor caveats:
- Only one tab can be using the accelerator.
- Sharing, downloading and conversion-to-legacy aren't supported.
- You may encounter UI errors if the Trace Processor version you are using is
too old. Get the latest version from get.perfetto.dev/trace_processor.
`;
// Try to connect to the external Trace Processor HTTP RPC accelerator (if
// available, often it isn't). If connected it will populate the
// |httpRpcState| in the frontend local state. In turn that will show the UI
// chip in the sidebar. trace_controller.ts will repeat this check before
// trying to load a new trace. We do this ahead of time just to have a
// consistent UX (i.e. so that the user can tell if the RPC is working without
// having to open a trace).
function CheckHttpRpcConnection() {
    return tslib.__awaiter(this, void 0, void 0, function* () {
        const state = yield http_rpc_engine.HttpRpcEngine.checkConnection();
        globals$1.globals.frontendLocalState.setHttpRpcState(state);
        // If a trace is already loaded in the trace processor (e.g., the user
        // launched trace_processor_shell -D trace_file.pftrace), prompt the user to
        // initialize the UI with the already-loaded trace.
        if (state.connected && state.loadedTraceName) {
            modal.showModal({
                title: 'Use Trace Processor Native Acceleration?',
                content: mithril('.modal-pre', PROMPT.replace('$loadedTraceName', state.loadedTraceName)),
                buttons: [
                    {
                        text: 'YES, use loaded trace',
                        primary: true,
                        id: 'rpc_load',
                        action: () => {
                            globals$1.globals.dispatch(actions.Actions.openTraceFromHttpRpc({}));
                        }
                    },
                    {
                        text: 'YES, but reset state',
                        primary: false,
                        id: 'rpc_reset',
                        action: () => { }
                    },
                    {
                        text: 'NO, Use builtin WASM',
                        primary: false,
                        id: 'rpc_force_wasm',
                        action: () => {
                            globals$1.globals.dispatch(actions.Actions.setNewEngineMode({ mode: 'FORCE_BUILTIN_WASM' }));
                        }
                    },
                ],
            });
        }
    });
}
exports.CheckHttpRpcConnection = CheckHttpRpcConnection;

});

var trace_info_page = createCommonjsModule(function (module, exports) {
// Copyright (C) 2020 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.
Object.defineProperty(exports, "__esModule", { value: true });
exports.TraceInfoPage = void 0;




// Generic class that generate a <section> + <table> from the stats table.
// The caller defines the query constraint, title and styling.
// Used for errors, data losses and debugging sections.
class StatsSection {
    constructor() {
        this.queryDispatched = false;
    }
    view({ attrs }) {
        if (!this.queryDispatched) {
            this.queryDispatched = true;
            globals$1.globals.dispatch(actions.Actions.executeQuery({
                engineId: '0',
                queryId: attrs.queryId,
                query: `select name, value, cast(ifnull(idx, '') as text) as idx,
                description, severity, source from stats
                where ${attrs.sqlConstraints || '1=1'}
                order by name, idx`,
            }));
        }
        const resp = globals$1.globals.queryResults.get(attrs.queryId);
        if (resp === undefined || resp.totalRowCount === 0) {
            return mithril('');
        }
        if (resp.error)
            throw new Error(resp.error);
        const tableRows = [];
        for (const row of resp.rows) {
            const help = [];
            if (row.description) {
                help.push(mithril('i.material-icons.contextual-help', 'help_outline'));
            }
            const idx = row.idx !== '' ? `[${row.idx}]` : '';
            tableRows.push(mithril('tr', mithril('td', { title: row.description }, `${row.name}${idx}`, help), mithril('td', `${row.value}`), mithril('td', `${row.severity} (${row.source})`)));
        }
        return mithril(`section${attrs.cssClass}`, mithril('h2', attrs.title), mithril('h3', attrs.subTitle), mithril('table', mithril('thead', mithril('tr', mithril('td', 'Name'), mithril('td', 'Value'), mithril('td', 'Type'))), mithril('tbody', tableRows)));
    }
}
class MetricErrors {
    view() {
        if (!globals$1.globals.metricError)
            return;
        return mithril(`section.errors`, mithril('h2', `Metric Errors`), mithril('h3', `One or more metrics were not computed successfully:`), mithril('div.metric-error', globals$1.globals.metricError));
    }
}
class TraceMetadata {
    constructor() {
        this.queryDispatched = false;
        this.QUERY_ID = 'info_metadata';
    }
    view() {
        if (!this.queryDispatched) {
            this.queryDispatched = true;
            globals$1.globals.dispatch(actions.Actions.executeQuery({
                engineId: '0',
                queryId: this.QUERY_ID,
                query: `select name, ifnull(str_value, cast(int_value as text)) as value
                from metadata order by name`,
            }));
        }
        const resp = globals$1.globals.queryResults.get(this.QUERY_ID);
        if (resp === undefined || resp.totalRowCount === 0) {
            return mithril('');
        }
        const tableRows = [];
        for (const row of resp.rows) {
            tableRows.push(mithril('tr', mithril('td', `${row.name}`), mithril('td', `${row.value}`)));
        }
        return mithril('section', mithril('h2', 'System info and metadata'), mithril('table', mithril('thead', mithril('tr', mithril('td', 'Name'), mithril('td', 'Value'))), mithril('tbody', tableRows)));
    }
}
class PackageList {
    constructor() {
        this.queryDispatched = false;
        this.QUERY_ID = 'info_package_list';
    }
    view() {
        if (!this.queryDispatched) {
            this.queryDispatched = true;
            globals$1.globals.dispatch(actions.Actions.executeQuery({
                engineId: '0',
                queryId: this.QUERY_ID,
                query: `select package_name, version_code, debuggable,
                profileable_from_shell from package_list`,
            }));
        }
        const resp = globals$1.globals.queryResults.get(this.QUERY_ID);
        if (resp === undefined || resp.totalRowCount === 0) {
            return mithril('');
        }
        const tableRows = [];
        for (const row of resp.rows) {
            tableRows.push(mithril('tr', mithril('td', `${row.package_name}`), mithril('td', `${row.version_code}`), mithril('td', `${row.debuggable ? 'debuggable' : ''} ${row.profileable_from_shell ? 'profileable' : ''}`)));
        }
        return mithril('section', mithril('h2', 'Package list'), mithril('table', mithril('thead', mithril('tr', mithril('td', 'Name'), mithril('td', 'Version code'), mithril('td', 'Flags'))), mithril('tbody', tableRows)));
    }
}
exports.TraceInfoPage = pages.createPage({
    view() {
        return mithril('.trace-info-page', mithril(MetricErrors), mithril(StatsSection, {
            queryId: 'info_errors',
            title: 'Import errors',
            cssClass: '.errors',
            subTitle: `The following errors have been encountered while importing the
               trace. These errors are usually non-fatal but indicate that one
               or more tracks might be missing or showing erroneous data.`,
            sqlConstraints: `severity = 'error' and value > 0`,
        }), mithril(StatsSection, {
            queryId: 'info_data_losses',
            title: 'Data losses',
            cssClass: '.errors',
            subTitle: `These counters are collected at trace recording time. The trace
               data for one or more data sources was droppped and hence some
               track contents will be incomplete.`,
            sqlConstraints: `severity = 'data_loss' and value > 0`,
        }), mithril(TraceMetadata), mithril(PackageList), mithril(StatsSection, {
            queryId: 'info_all',
            title: 'Debugging stats',
            cssClass: '',
            subTitle: `Debugging statistics such as trace buffer usage and metrics
                     coming from the TraceProcessor importer stages.`,
            sqlConstraints: '',
        }));
    }
});

});

var thread_state = createCommonjsModule(function (module, exports) {
// Copyright (C) 2019 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.
Object.defineProperty(exports, "__esModule", { value: true });
exports.translateState = void 0;
const states = {
    'R': 'Runnable',
    'S': 'Sleeping',
    'D': 'Uninterruptible Sleep',
    'T': 'Stopped',
    't': 'Traced',
    'X': 'Exit (Dead)',
    'Z': 'Exit (Zombie)',
    'x': 'Task Dead',
    'I': 'Task Dead',
    'K': 'Wake Kill',
    'W': 'Waking',
    'P': 'Parked',
    'N': 'No Load',
    '+': '(Preempted)'
};
function translateState(state, ioWait = undefined) {
    if (state === undefined)
        return '';
    if (state === 'Running') {
        return state;
    }
    let result = states[state[0]];
    if (ioWait === true) {
        result += ' (IO)';
    }
    else if (ioWait === false) {
        result += ' (non-IO)';
    }
    for (let i = 1; i < state.length; i++) {
        result += state[i] === '+' ? ' ' : ' + ';
        result += states[state[i]];
    }
    // state is some string we don't know how to translate.
    if (result === undefined)
        return state;
    return result;
}
exports.translateState = translateState;

});

var aggregation_panel = createCommonjsModule(function (module, exports) {
// Copyright (C) 2019 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use size 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.
Object.defineProperty(exports, "__esModule", { value: true });
exports.AggregationPanel = void 0;






class AggregationPanel extends panel.Panel {
    view({ attrs }) {
        return mithril('.details-panel', mithril('.details-panel-heading.aggregation', attrs.data.extra !== undefined &&
            attrs.data.extra.kind === 'THREAD_STATE' ?
            this.showStateSummary(attrs.data.extra) :
            null, this.showTimeRange(), mithril('table', mithril('tr', attrs.data.columns.map(col => this.formatColumnHeading(col, attrs.kind))), mithril('tr.sum', attrs.data.columnSums.map(sum => {
            const sumClass = sum === '' ? 'td' : 'td.sum-data';
            return mithril(sumClass, sum);
        })))), mithril('.details-table.aggregation', mithril('table', this.getRows(attrs.data))));
    }
    formatColumnHeading(col, id) {
        const pref = globals$1.globals.state.aggregatePreferences[id];
        let sortIcon = '';
        if (pref && pref.sorting && pref.sorting.column === col.columnId) {
            sortIcon = pref.sorting.direction === 'DESC' ? 'arrow_drop_down' :
                'arrow_drop_up';
        }
        return mithril('th', {
            onclick: () => {
                globals$1.globals.dispatch(actions.Actions.updateAggregateSorting({ id, column: col.columnId }));
            }
        }, col.title, mithril('i.material-icons', sortIcon));
    }
    getRows(data) {
        if (data.columns.length === 0)
            return;
        const rows = [];
        for (let i = 0; i < data.columns[0].data.length; i++) {
            const row = [];
            for (let j = 0; j < data.columns.length; j++) {
                row.push(mithril('td', this.getFormattedData(data, i, j)));
            }
            rows.push(mithril('tr', row));
        }
        return rows;
    }
    getFormattedData(data, rowIndex, columnIndex) {
        switch (data.columns[columnIndex].kind) {
            case 'STRING':
                return data.strings[data.columns[columnIndex].data[rowIndex]];
            case 'TIMESTAMP_NS':
                return `${data.columns[columnIndex].data[rowIndex] / 1000000}`;
            case 'STATE': {
                const concatState = data.strings[data.columns[columnIndex].data[rowIndex]];
                const split = concatState.split(',');
                const ioWait = split[1] === 'NULL' ? undefined : !!Number.parseInt(split[1], 10);
                return thread_state.translateState(split[0], ioWait);
            }
            case 'NUMBER':
            default:
                return data.columns[columnIndex].data[rowIndex];
        }
    }
    showTimeRange() {
        const selection = globals$1.globals.state.currentSelection;
        if (selection === null || selection.kind !== 'AREA')
            return undefined;
        const selectedArea = globals$1.globals.state.areas[selection.areaId];
        const rangeDurationMs = (selectedArea.endSec - selectedArea.startSec) * 1e3;
        return mithril('.time-range', `Selected range: ${rangeDurationMs.toFixed(6)} ms`);
    }
    // Thread state aggregation panel only
    showStateSummary(data) {
        if (data === undefined)
            return undefined;
        const states = [];
        for (let i = 0; i < data.states.length; i++) {
            const color = colorizer.colorForState(data.states[i]);
            const textColor = colorizer.textColorForState(data.states[i]);
            const width = data.values[i] / data.totalMs * 100;
            states.push(mithril('.state', {
                style: {
                    background: `hsl(${color.h},${color.s}%,${color.l}%)`,
                    color: `${textColor}`,
                    width: `${width}%`
                }
            }, `${data.states[i]}: ${data.values[i]} ms`));
        }
        return mithril('.states', states);
    }
    renderCanvas() { }
}
exports.AggregationPanel = AggregationPanel;

});

var prism = createCommonjsModule(function (module) {
/* **********************************************
     Begin prism-core.js
********************************************** */

/// <reference lib="WebWorker"/>

var _self = (typeof window !== 'undefined')
	? window   // if in browser
	: (
		(typeof WorkerGlobalScope !== 'undefined' && self instanceof WorkerGlobalScope)
		? self // if in worker
		: {}   // if in node js
	);

/**
 * Prism: Lightweight, robust, elegant syntax highlighting
 *
 * @license MIT <https://opensource.org/licenses/MIT>
 * @author Lea Verou <https://lea.verou.me>
 * @namespace
 * @public
 */
var Prism = (function (_self){

// Private helper vars
var lang = /\blang(?:uage)?-([\w-]+)\b/i;
var uniqueId = 0;


var _ = {
	/**
	 * By default, Prism will attempt to highlight all code elements (by calling {@link Prism.highlightAll}) on the
	 * current page after the page finished loading. This might be a problem if e.g. you wanted to asynchronously load
	 * additional languages or plugins yourself.
	 *
	 * By setting this value to `true`, Prism will not automatically highlight all code elements on the page.
	 *
	 * You obviously have to change this value before the automatic highlighting started. To do this, you can add an
	 * empty Prism object into the global scope before loading the Prism script like this:
	 *
	 * ```js
	 * window.Prism = window.Prism || {};
	 * Prism.manual = true;
	 * // add a new <script> to load Prism's script
	 * ```
	 *
	 * @default false
	 * @type {boolean}
	 * @memberof Prism
	 * @public
	 */
	manual: _self.Prism && _self.Prism.manual,
	disableWorkerMessageHandler: _self.Prism && _self.Prism.disableWorkerMessageHandler,

	/**
	 * A namespace for utility methods.
	 *
	 * All function in this namespace that are not explicitly marked as _public_ are for __internal use only__ and may
	 * change or disappear at any time.
	 *
	 * @namespace
	 * @memberof Prism
	 */
	util: {
		encode: function encode(tokens) {
			if (tokens instanceof Token) {
				return new Token(tokens.type, encode(tokens.content), tokens.alias);
			} else if (Array.isArray(tokens)) {
				return tokens.map(encode);
			} else {
				return tokens.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/\u00a0/g, ' ');
			}
		},

		/**
		 * Returns the name of the type of the given value.
		 *
		 * @param {any} o
		 * @returns {string}
		 * @example
		 * type(null)      === 'Null'
		 * type(undefined) === 'Undefined'
		 * type(123)       === 'Number'
		 * type('foo')     === 'String'
		 * type(true)      === 'Boolean'
		 * type([1, 2])    === 'Array'
		 * type({})        === 'Object'
		 * type(String)    === 'Function'
		 * type(/abc+/)    === 'RegExp'
		 */
		type: function (o) {
			return Object.prototype.toString.call(o).slice(8, -1);
		},

		/**
		 * Returns a unique number for the given object. Later calls will still return the same number.
		 *
		 * @param {Object} obj
		 * @returns {number}
		 */
		objId: function (obj) {
			if (!obj['__id']) {
				Object.defineProperty(obj, '__id', { value: ++uniqueId });
			}
			return obj['__id'];
		},

		/**
		 * Creates a deep clone of the given object.
		 *
		 * The main intended use of this function is to clone language definitions.
		 *
		 * @param {T} o
		 * @param {Record<number, any>} [visited]
		 * @returns {T}
		 * @template T
		 */
		clone: function deepClone(o, visited) {
			visited = visited || {};

			var clone, id;
			switch (_.util.type(o)) {
				case 'Object':
					id = _.util.objId(o);
					if (visited[id]) {
						return visited[id];
					}
					clone = /** @type {Record<string, any>} */ ({});
					visited[id] = clone;

					for (var key in o) {
						if (o.hasOwnProperty(key)) {
							clone[key] = deepClone(o[key], visited);
						}
					}

					return /** @type {any} */ (clone);

				case 'Array':
					id = _.util.objId(o);
					if (visited[id]) {
						return visited[id];
					}
					clone = [];
					visited[id] = clone;

					(/** @type {Array} */(/** @type {any} */(o))).forEach(function (v, i) {
						clone[i] = deepClone(v, visited);
					});

					return /** @type {any} */ (clone);

				default:
					return o;
			}
		},

		/**
		 * Returns the Prism language of the given element set by a `language-xxxx` or `lang-xxxx` class.
		 *
		 * If no language is set for the element or the element is `null` or `undefined`, `none` will be returned.
		 *
		 * @param {Element} element
		 * @returns {string}
		 */
		getLanguage: function (element) {
			while (element && !lang.test(element.className)) {
				element = element.parentElement;
			}
			if (element) {
				return (element.className.match(lang) || [, 'none'])[1].toLowerCase();
			}
			return 'none';
		},

		/**
		 * Returns the script element that is currently executing.
		 *
		 * This does __not__ work for line script element.
		 *
		 * @returns {HTMLScriptElement | null}
		 */
		currentScript: function () {
			if (typeof document === 'undefined') {
				return null;
			}
			if ('currentScript' in document && 1 < 2 /* hack to trip TS' flow analysis */) {
				return /** @type {any} */ (document.currentScript);
			}

			// IE11 workaround
			// we'll get the src of the current script by parsing IE11's error stack trace
			// this will not work for inline scripts

			try {
				throw new Error();
			} catch (err) {
				// Get file src url from stack. Specifically works with the format of stack traces in IE.
				// A stack will look like this:
				//
				// Error
				//    at _.util.currentScript (http://localhost/components/prism-core.js:119:5)
				//    at Global code (http://localhost/components/prism-core.js:606:1)

				var src = (/at [^(\r\n]*\((.*):.+:.+\)$/i.exec(err.stack) || [])[1];
				if (src) {
					var scripts = document.getElementsByTagName('script');
					for (var i in scripts) {
						if (scripts[i].src == src) {
							return scripts[i];
						}
					}
				}
				return null;
			}
		},

		/**
		 * Returns whether a given class is active for `element`.
		 *
		 * The class can be activated if `element` or one of its ancestors has the given class and it can be deactivated
		 * if `element` or one of its ancestors has the negated version of the given class. The _negated version_ of the
		 * given class is just the given class with a `no-` prefix.
		 *
		 * Whether the class is active is determined by the closest ancestor of `element` (where `element` itself is
		 * closest ancestor) that has the given class or the negated version of it. If neither `element` nor any of its
		 * ancestors have the given class or the negated version of it, then the default activation will be returned.
		 *
		 * In the paradoxical situation where the closest ancestor contains __both__ the given class and the negated
		 * version of it, the class is considered active.
		 *
		 * @param {Element} element
		 * @param {string} className
		 * @param {boolean} [defaultActivation=false]
		 * @returns {boolean}
		 */
		isActive: function (element, className, defaultActivation) {
			var no = 'no-' + className;

			while (element) {
				var classList = element.classList;
				if (classList.contains(className)) {
					return true;
				}
				if (classList.contains(no)) {
					return false;
				}
				element = element.parentElement;
			}
			return !!defaultActivation;
		}
	},

	/**
	 * This namespace contains all currently loaded languages and the some helper functions to create and modify languages.
	 *
	 * @namespace
	 * @memberof Prism
	 * @public
	 */
	languages: {
		/**
		 * Creates a deep copy of the language with the given id and appends the given tokens.
		 *
		 * If a token in `redef` also appears in the copied language, then the existing token in the copied language
		 * will be overwritten at its original position.
		 *
		 * ## Best practices
		 *
		 * Since the position of overwriting tokens (token in `redef` that overwrite tokens in the copied language)
		 * doesn't matter, they can technically be in any order. However, this can be confusing to others that trying to
		 * understand the language definition because, normally, the order of tokens matters in Prism grammars.
		 *
		 * Therefore, it is encouraged to order overwriting tokens according to the positions of the overwritten tokens.
		 * Furthermore, all non-overwriting tokens should be placed after the overwriting ones.
		 *
		 * @param {string} id The id of the language to extend. This has to be a key in `Prism.languages`.
		 * @param {Grammar} redef The new tokens to append.
		 * @returns {Grammar} The new language created.
		 * @public
		 * @example
		 * Prism.languages['css-with-colors'] = Prism.languages.extend('css', {
		 *     // Prism.languages.css already has a 'comment' token, so this token will overwrite CSS' 'comment' token
		 *     // at its original position
		 *     'comment': { ... },
		 *     // CSS doesn't have a 'color' token, so this token will be appended
		 *     'color': /\b(?:red|green|blue)\b/
		 * });
		 */
		extend: function (id, redef) {
			var lang = _.util.clone(_.languages[id]);

			for (var key in redef) {
				lang[key] = redef[key];
			}

			return lang;
		},

		/**
		 * Inserts tokens _before_ another token in a language definition or any other grammar.
		 *
		 * ## Usage
		 *
		 * This helper method makes it easy to modify existing languages. For example, the CSS language definition
		 * not only defines CSS highlighting for CSS documents, but also needs to define highlighting for CSS embedded
		 * in HTML through `<style>` elements. To do this, it needs to modify `Prism.languages.markup` and add the
		 * appropriate tokens. However, `Prism.languages.markup` is a regular JavaScript object literal, so if you do
		 * this:
		 *
		 * ```js
		 * Prism.languages.markup.style = {
		 *     // token
		 * };
		 * ```
		 *
		 * then the `style` token will be added (and processed) at the end. `insertBefore` allows you to insert tokens
		 * before existing tokens. For the CSS example above, you would use it like this:
		 *
		 * ```js
		 * Prism.languages.insertBefore('markup', 'cdata', {
		 *     'style': {
		 *         // token
		 *     }
		 * });
		 * ```
		 *
		 * ## Special cases
		 *
		 * If the grammars of `inside` and `insert` have tokens with the same name, the tokens in `inside`'s grammar
		 * will be ignored.
		 *
		 * This behavior can be used to insert tokens after `before`:
		 *
		 * ```js
		 * Prism.languages.insertBefore('markup', 'comment', {
		 *     'comment': Prism.languages.markup.comment,
		 *     // tokens after 'comment'
		 * });
		 * ```
		 *
		 * ## Limitations
		 *
		 * The main problem `insertBefore` has to solve is iteration order. Since ES2015, the iteration order for object
		 * properties is guaranteed to be the insertion order (except for integer keys) but some browsers behave
		 * differently when keys are deleted and re-inserted. So `insertBefore` can't be implemented by temporarily
		 * deleting properties which is necessary to insert at arbitrary positions.
		 *
		 * To solve this problem, `insertBefore` doesn't actually insert the given tokens into the target object.
		 * Instead, it will create a new object and replace all references to the target object with the new one. This
		 * can be done without temporarily deleting properties, so the iteration order is well-defined.
		 *
		 * However, only references that can be reached from `Prism.languages` or `insert` will be replaced. I.e. if
		 * you hold the target object in a variable, then the value of the variable will not change.
		 *
		 * ```js
		 * var oldMarkup = Prism.languages.markup;
		 * var newMarkup = Prism.languages.insertBefore('markup', 'comment', { ... });
		 *
		 * assert(oldMarkup !== Prism.languages.markup);
		 * assert(newMarkup === Prism.languages.markup);
		 * ```
		 *
		 * @param {string} inside The property of `root` (e.g. a language id in `Prism.languages`) that contains the
		 * object to be modified.
		 * @param {string} before The key to insert before.
		 * @param {Grammar} insert An object containing the key-value pairs to be inserted.
		 * @param {Object<string, any>} [root] The object containing `inside`, i.e. the object that contains the
		 * object to be modified.
		 *
		 * Defaults to `Prism.languages`.
		 * @returns {Grammar} The new grammar object.
		 * @public
		 */
		insertBefore: function (inside, before, insert, root) {
			root = root || /** @type {any} */ (_.languages);
			var grammar = root[inside];
			/** @type {Grammar} */
			var ret = {};

			for (var token in grammar) {
				if (grammar.hasOwnProperty(token)) {

					if (token == before) {
						for (var newToken in insert) {
							if (insert.hasOwnProperty(newToken)) {
								ret[newToken] = insert[newToken];
							}
						}
					}

					// Do not insert token which also occur in insert. See #1525
					if (!insert.hasOwnProperty(token)) {
						ret[token] = grammar[token];
					}
				}
			}

			var old = root[inside];
			root[inside] = ret;

			// Update references in other language definitions
			_.languages.DFS(_.languages, function(key, value) {
				if (value === old && key != inside) {
					this[key] = ret;
				}
			});

			return ret;
		},

		// Traverse a language definition with Depth First Search
		DFS: function DFS(o, callback, type, visited) {
			visited = visited || {};

			var objId = _.util.objId;

			for (var i in o) {
				if (o.hasOwnProperty(i)) {
					callback.call(o, i, o[i], type || i);

					var property = o[i],
					    propertyType = _.util.type(property);

					if (propertyType === 'Object' && !visited[objId(property)]) {
						visited[objId(property)] = true;
						DFS(property, callback, null, visited);
					}
					else if (propertyType === 'Array' && !visited[objId(property)]) {
						visited[objId(property)] = true;
						DFS(property, callback, i, visited);
					}
				}
			}
		}
	},

	plugins: {},

	/**
	 * This is the most high-level function in Prism’s API.
	 * It fetches all the elements that have a `.language-xxxx` class and then calls {@link Prism.highlightElement} on
	 * each one of them.
	 *
	 * This is equivalent to `Prism.highlightAllUnder(document, async, callback)`.
	 *
	 * @param {boolean} [async=false] Same as in {@link Prism.highlightAllUnder}.
	 * @param {HighlightCallback} [callback] Same as in {@link Prism.highlightAllUnder}.
	 * @memberof Prism
	 * @public
	 */
	highlightAll: function(async, callback) {
		_.highlightAllUnder(document, async, callback);
	},

	/**
	 * Fetches all the descendants of `container` that have a `.language-xxxx` class and then calls
	 * {@link Prism.highlightElement} on each one of them.
	 *
	 * The following hooks will be run:
	 * 1. `before-highlightall`
	 * 2. `before-all-elements-highlight`
	 * 3. All hooks of {@link Prism.highlightElement} for each element.
	 *
	 * @param {ParentNode} container The root element, whose descendants that have a `.language-xxxx` class will be highlighted.
	 * @param {boolean} [async=false] Whether each element is to be highlighted asynchronously using Web Workers.
	 * @param {HighlightCallback} [callback] An optional callback to be invoked on each element after its highlighting is done.
	 * @memberof Prism
	 * @public
	 */
	highlightAllUnder: function(container, async, callback) {
		var env = {
			callback: callback,
			container: container,
			selector: 'code[class*="language-"], [class*="language-"] code, code[class*="lang-"], [class*="lang-"] code'
		};

		_.hooks.run('before-highlightall', env);

		env.elements = Array.prototype.slice.apply(env.container.querySelectorAll(env.selector));

		_.hooks.run('before-all-elements-highlight', env);

		for (var i = 0, element; element = env.elements[i++];) {
			_.highlightElement(element, async === true, env.callback);
		}
	},

	/**
	 * Highlights the code inside a single element.
	 *
	 * The following hooks will be run:
	 * 1. `before-sanity-check`
	 * 2. `before-highlight`
	 * 3. All hooks of {@link Prism.highlight}. These hooks will be run by an asynchronous worker if `async` is `true`.
	 * 4. `before-insert`
	 * 5. `after-highlight`
	 * 6. `complete`
	 *
	 * Some the above hooks will be skipped if the element doesn't contain any text or there is no grammar loaded for
	 * the element's language.
	 *
	 * @param {Element} element The element containing the code.
	 * It must have a class of `language-xxxx` to be processed, where `xxxx` is a valid language identifier.
	 * @param {boolean} [async=false] Whether the element is to be highlighted asynchronously using Web Workers
	 * to improve performance and avoid blocking the UI when highlighting very large chunks of code. This option is
	 * [disabled by default](https://prismjs.com/faq.html#why-is-asynchronous-highlighting-disabled-by-default).
	 *
	 * Note: All language definitions required to highlight the code must be included in the main `prism.js` file for
	 * asynchronous highlighting to work. You can build your own bundle on the
	 * [Download page](https://prismjs.com/download.html).
	 * @param {HighlightCallback} [callback] An optional callback to be invoked after the highlighting is done.
	 * Mostly useful when `async` is `true`, since in that case, the highlighting is done asynchronously.
	 * @memberof Prism
	 * @public
	 */
	highlightElement: function(element, async, callback) {
		// Find language
		var language = _.util.getLanguage(element);
		var grammar = _.languages[language];

		// Set language on the element, if not present
		element.className = element.className.replace(lang, '').replace(/\s+/g, ' ') + ' language-' + language;

		// Set language on the parent, for styling
		var parent = element.parentElement;
		if (parent && parent.nodeName.toLowerCase() === 'pre') {
			parent.className = parent.className.replace(lang, '').replace(/\s+/g, ' ') + ' language-' + language;
		}

		var code = element.textContent;

		var env = {
			element: element,
			language: language,
			grammar: grammar,
			code: code
		};

		function insertHighlightedCode(highlightedCode) {
			env.highlightedCode = highlightedCode;

			_.hooks.run('before-insert', env);

			env.element.innerHTML = env.highlightedCode;

			_.hooks.run('after-highlight', env);
			_.hooks.run('complete', env);
			callback && callback.call(env.element);
		}

		_.hooks.run('before-sanity-check', env);

		if (!env.code) {
			_.hooks.run('complete', env);
			callback && callback.call(env.element);
			return;
		}

		_.hooks.run('before-highlight', env);

		if (!env.grammar) {
			insertHighlightedCode(_.util.encode(env.code));
			return;
		}

		if (async && _self.Worker) {
			var worker = new Worker(_.filename);

			worker.onmessage = function(evt) {
				insertHighlightedCode(evt.data);
			};

			worker.postMessage(JSON.stringify({
				language: env.language,
				code: env.code,
				immediateClose: true
			}));
		}
		else {
			insertHighlightedCode(_.highlight(env.code, env.grammar, env.language));
		}
	},

	/**
	 * Low-level function, only use if you know what you’re doing. It accepts a string of text as input
	 * and the language definitions to use, and returns a string with the HTML produced.
	 *
	 * The following hooks will be run:
	 * 1. `before-tokenize`
	 * 2. `after-tokenize`
	 * 3. `wrap`: On each {@link Token}.
	 *
	 * @param {string} text A string with the code to be highlighted.
	 * @param {Grammar} grammar An object containing the tokens to use.
	 *
	 * Usually a language definition like `Prism.languages.markup`.
	 * @param {string} language The name of the language definition passed to `grammar`.
	 * @returns {string} The highlighted HTML.
	 * @memberof Prism
	 * @public
	 * @example
	 * Prism.highlight('var foo = true;', Prism.languages.javascript, 'javascript');
	 */
	highlight: function (text, grammar, language) {
		var env = {
			code: text,
			grammar: grammar,
			language: language
		};
		_.hooks.run('before-tokenize', env);
		env.tokens = _.tokenize(env.code, env.grammar);
		_.hooks.run('after-tokenize', env);
		return Token.stringify(_.util.encode(env.tokens), env.language);
	},

	/**
	 * This is the heart of Prism, and the most low-level function you can use. It accepts a string of text as input
	 * and the language definitions to use, and returns an array with the tokenized code.
	 *
	 * When the language definition includes nested tokens, the function is called recursively on each of these tokens.
	 *
	 * This method could be useful in other contexts as well, as a very crude parser.
	 *
	 * @param {string} text A string with the code to be highlighted.
	 * @param {Grammar} grammar An object containing the tokens to use.
	 *
	 * Usually a language definition like `Prism.languages.markup`.
	 * @returns {TokenStream} An array of strings and tokens, a token stream.
	 * @memberof Prism
	 * @public
	 * @example
	 * let code = `var foo = 0;`;
	 * let tokens = Prism.tokenize(code, Prism.languages.javascript);
	 * tokens.forEach(token => {
	 *     if (token instanceof Prism.Token && token.type === 'number') {
	 *         console.log(`Found numeric literal: ${token.content}`);
	 *     }
	 * });
	 */
	tokenize: function(text, grammar) {
		var rest = grammar.rest;
		if (rest) {
			for (var token in rest) {
				grammar[token] = rest[token];
			}

			delete grammar.rest;
		}

		var tokenList = new LinkedList();
		addAfter(tokenList, tokenList.head, text);

		matchGrammar(text, tokenList, grammar, tokenList.head, 0);

		return toArray(tokenList);
	},

	/**
	 * @namespace
	 * @memberof Prism
	 * @public
	 */
	hooks: {
		all: {},

		/**
		 * Adds the given callback to the list of callbacks for the given hook.
		 *
		 * The callback will be invoked when the hook it is registered for is run.
		 * Hooks are usually directly run by a highlight function but you can also run hooks yourself.
		 *
		 * One callback function can be registered to multiple hooks and the same hook multiple times.
		 *
		 * @param {string} name The name of the hook.
		 * @param {HookCallback} callback The callback function which is given environment variables.
		 * @public
		 */
		add: function (name, callback) {
			var hooks = _.hooks.all;

			hooks[name] = hooks[name] || [];

			hooks[name].push(callback);
		},

		/**
		 * Runs a hook invoking all registered callbacks with the given environment variables.
		 *
		 * Callbacks will be invoked synchronously and in the order in which they were registered.
		 *
		 * @param {string} name The name of the hook.
		 * @param {Object<string, any>} env The environment variables of the hook passed to all callbacks registered.
		 * @public
		 */
		run: function (name, env) {
			var callbacks = _.hooks.all[name];

			if (!callbacks || !callbacks.length) {
				return;
			}

			for (var i=0, callback; callback = callbacks[i++];) {
				callback(env);
			}
		}
	},

	Token: Token
};
_self.Prism = _;


// Typescript note:
// The following can be used to import the Token type in JSDoc:
//
//   @typedef {InstanceType<import("./prism-core")["Token"]>} Token

/**
 * Creates a new token.
 *
 * @param {string} type See {@link Token#type type}
 * @param {string | TokenStream} content See {@link Token#content content}
 * @param {string|string[]} [alias] The alias(es) of the token.
 * @param {string} [matchedStr=""] A copy of the full string this token was created from.
 * @class
 * @global
 * @public
 */
function Token(type, content, alias, matchedStr) {
	/**
	 * The type of the token.
	 *
	 * This is usually the key of a pattern in a {@link Grammar}.
	 *
	 * @type {string}
	 * @see GrammarToken
	 * @public
	 */
	this.type = type;
	/**
	 * The strings or tokens contained by this token.
	 *
	 * This will be a token stream if the pattern matched also defined an `inside` grammar.
	 *
	 * @type {string | TokenStream}
	 * @public
	 */
	this.content = content;
	/**
	 * The alias(es) of the token.
	 *
	 * @type {string|string[]}
	 * @see GrammarToken
	 * @public
	 */
	this.alias = alias;
	// Copy of the full string this token was created from
	this.length = (matchedStr || '').length | 0;
}

/**
 * A token stream is an array of strings and {@link Token Token} objects.
 *
 * Token streams have to fulfill a few properties that are assumed by most functions (mostly internal ones) that process
 * them.
 *
 * 1. No adjacent strings.
 * 2. No empty strings.
 *
 *    The only exception here is the token stream that only contains the empty string and nothing else.
 *
 * @typedef {Array<string | Token>} TokenStream
 * @global
 * @public
 */

/**
 * Converts the given token or token stream to an HTML representation.
 *
 * The following hooks will be run:
 * 1. `wrap`: On each {@link Token}.
 *
 * @param {string | Token | TokenStream} o The token or token stream to be converted.
 * @param {string} language The name of current language.
 * @returns {string} The HTML representation of the token or token stream.
 * @memberof Token
 * @static
 */
Token.stringify = function stringify(o, language) {
	if (typeof o == 'string') {
		return o;
	}
	if (Array.isArray(o)) {
		var s = '';
		o.forEach(function (e) {
			s += stringify(e, language);
		});
		return s;
	}

	var env = {
		type: o.type,
		content: stringify(o.content, language),
		tag: 'span',
		classes: ['token', o.type],
		attributes: {},
		language: language
	};

	var aliases = o.alias;
	if (aliases) {
		if (Array.isArray(aliases)) {
			Array.prototype.push.apply(env.classes, aliases);
		} else {
			env.classes.push(aliases);
		}
	}

	_.hooks.run('wrap', env);

	var attributes = '';
	for (var name in env.attributes) {
		attributes += ' ' + name + '="' + (env.attributes[name] || '').replace(/"/g, '&quot;') + '"';
	}

	return '<' + env.tag + ' class="' + env.classes.join(' ') + '"' + attributes + '>' + env.content + '</' + env.tag + '>';
};

/**
 * @param {RegExp} pattern
 * @param {number} pos
 * @param {string} text
 * @param {boolean} lookbehind
 * @returns {RegExpExecArray | null}
 */
function matchPattern(pattern, pos, text, lookbehind) {
	pattern.lastIndex = pos;
	var match = pattern.exec(text);
	if (match && lookbehind && match[1]) {
		// change the match to remove the text matched by the Prism lookbehind group
		var lookbehindLength = match[1].length;
		match.index += lookbehindLength;
		match[0] = match[0].slice(lookbehindLength);
	}
	return match;
}

/**
 * @param {string} text
 * @param {LinkedList<string | Token>} tokenList
 * @param {any} grammar
 * @param {LinkedListNode<string | Token>} startNode
 * @param {number} startPos
 * @param {RematchOptions} [rematch]
 * @returns {void}
 * @private
 *
 * @typedef RematchOptions
 * @property {string} cause
 * @property {number} reach
 */
function matchGrammar(text, tokenList, grammar, startNode, startPos, rematch) {
	for (var token in grammar) {
		if (!grammar.hasOwnProperty(token) || !grammar[token]) {
			continue;
		}

		var patterns = grammar[token];
		patterns = Array.isArray(patterns) ? patterns : [patterns];

		for (var j = 0; j < patterns.length; ++j) {
			if (rematch && rematch.cause == token + ',' + j) {
				return;
			}

			var patternObj = patterns[j],
				inside = patternObj.inside,
				lookbehind = !!patternObj.lookbehind,
				greedy = !!patternObj.greedy,
				alias = patternObj.alias;

			if (greedy && !patternObj.pattern.global) {
				// Without the global flag, lastIndex won't work
				var flags = patternObj.pattern.toString().match(/[imsuy]*$/)[0];
				patternObj.pattern = RegExp(patternObj.pattern.source, flags + 'g');
			}

			/** @type {RegExp} */
			var pattern = patternObj.pattern || patternObj;

			for ( // iterate the token list and keep track of the current token/string position
				var currentNode = startNode.next, pos = startPos;
				currentNode !== tokenList.tail;
				pos += currentNode.value.length, currentNode = currentNode.next
			) {

				if (rematch && pos >= rematch.reach) {
					break;
				}

				var str = currentNode.value;

				if (tokenList.length > text.length) {
					// Something went terribly wrong, ABORT, ABORT!
					return;
				}

				if (str instanceof Token) {
					continue;
				}

				var removeCount = 1; // this is the to parameter of removeBetween
				var match;

				if (greedy) {
					match = matchPattern(pattern, pos, text, lookbehind);
					if (!match) {
						break;
					}

					var from = match.index;
					var to = match.index + match[0].length;
					var p = pos;

					// find the node that contains the match
					p += currentNode.value.length;
					while (from >= p) {
						currentNode = currentNode.next;
						p += currentNode.value.length;
					}
					// adjust pos (and p)
					p -= currentNode.value.length;
					pos = p;

					// the current node is a Token, then the match starts inside another Token, which is invalid
					if (currentNode.value instanceof Token) {
						continue;
					}

					// find the last node which is affected by this match
					for (
						var k = currentNode;
						k !== tokenList.tail && (p < to || typeof k.value === 'string');
						k = k.next
					) {
						removeCount++;
						p += k.value.length;
					}
					removeCount--;

					// replace with the new match
					str = text.slice(pos, p);
					match.index -= pos;
				} else {
					match = matchPattern(pattern, 0, str, lookbehind);
					if (!match) {
						continue;
					}
				}

				var from = match.index,
					matchStr = match[0],
					before = str.slice(0, from),
					after = str.slice(from + matchStr.length);

				var reach = pos + str.length;
				if (rematch && reach > rematch.reach) {
					rematch.reach = reach;
				}

				var removeFrom = currentNode.prev;

				if (before) {
					removeFrom = addAfter(tokenList, removeFrom, before);
					pos += before.length;
				}

				removeRange(tokenList, removeFrom, removeCount);

				var wrapped = new Token(token, inside ? _.tokenize(matchStr, inside) : matchStr, alias, matchStr);
				currentNode = addAfter(tokenList, removeFrom, wrapped);

				if (after) {
					addAfter(tokenList, currentNode, after);
				}

				if (removeCount > 1) {
					// at least one Token object was removed, so we have to do some rematching
					// this can only happen if the current pattern is greedy
					matchGrammar(text, tokenList, grammar, currentNode.prev, pos, {
						cause: token + ',' + j,
						reach: reach
					});
				}
			}
		}
	}
}

/**
 * @typedef LinkedListNode
 * @property {T} value
 * @property {LinkedListNode<T> | null} prev The previous node.
 * @property {LinkedListNode<T> | null} next The next node.
 * @template T
 * @private
 */

/**
 * @template T
 * @private
 */
function LinkedList() {
	/** @type {LinkedListNode<T>} */
	var head = { value: null, prev: null, next: null };
	/** @type {LinkedListNode<T>} */
	var tail = { value: null, prev: head, next: null };
	head.next = tail;

	/** @type {LinkedListNode<T>} */
	this.head = head;
	/** @type {LinkedListNode<T>} */
	this.tail = tail;
	this.length = 0;
}

/**
 * Adds a new node with the given value to the list.
 * @param {LinkedList<T>} list
 * @param {LinkedListNode<T>} node
 * @param {T} value
 * @returns {LinkedListNode<T>} The added node.
 * @template T
 */
function addAfter(list, node, value) {
	// assumes that node != list.tail && values.length >= 0
	var next = node.next;

	var newNode = { value: value, prev: node, next: next };
	node.next = newNode;
	next.prev = newNode;
	list.length++;

	return newNode;
}
/**
 * Removes `count` nodes after the given node. The given node will not be removed.
 * @param {LinkedList<T>} list
 * @param {LinkedListNode<T>} node
 * @param {number} count
 * @template T
 */
function removeRange(list, node, count) {
	var next = node.next;
	for (var i = 0; i < count && next !== list.tail; i++) {
		next = next.next;
	}
	node.next = next;
	next.prev = node;
	list.length -= i;
}
/**
 * @param {LinkedList<T>} list
 * @returns {T[]}
 * @template T
 */
function toArray(list) {
	var array = [];
	var node = list.head.next;
	while (node !== list.tail) {
		array.push(node.value);
		node = node.next;
	}
	return array;
}


if (!_self.document) {
	if (!_self.addEventListener) {
		// in Node.js
		return _;
	}

	if (!_.disableWorkerMessageHandler) {
		// In worker
		_self.addEventListener('message', function (evt) {
			var message = JSON.parse(evt.data),
				lang = message.language,
				code = message.code,
				immediateClose = message.immediateClose;

			_self.postMessage(_.highlight(code, _.languages[lang], lang));
			if (immediateClose) {
				_self.close();
			}
		}, false);
	}

	return _;
}

// Get current script and highlight
var script = _.util.currentScript();

if (script) {
	_.filename = script.src;

	if (script.hasAttribute('data-manual')) {
		_.manual = true;
	}
}

function highlightAutomaticallyCallback() {
	if (!_.manual) {
		_.highlightAll();
	}
}

if (!_.manual) {
	// If the document state is "loading", then we'll use DOMContentLoaded.
	// If the document state is "interactive" and the prism.js script is deferred, then we'll also use the
	// DOMContentLoaded event because there might be some plugins or languages which have also been deferred and they
	// might take longer one animation frame to execute which can create a race condition where only some plugins have
	// been loaded when Prism.highlightAll() is executed, depending on how fast resources are loaded.
	// See https://github.com/PrismJS/prism/issues/2102
	var readyState = document.readyState;
	if (readyState === 'loading' || readyState === 'interactive' && script && script.defer) {
		document.addEventListener('DOMContentLoaded', highlightAutomaticallyCallback);
	} else {
		if (window.requestAnimationFrame) {
			window.requestAnimationFrame(highlightAutomaticallyCallback);
		} else {
			window.setTimeout(highlightAutomaticallyCallback, 16);
		}
	}
}

return _;

})(_self);

if (module.exports) {
	module.exports = Prism;
}

// hack for components to work correctly in node.js
if (typeof commonjsGlobal !== 'undefined') {
	commonjsGlobal.Prism = Prism;
}

// some additional documentation/types

/**
 * The expansion of a simple `RegExp` literal to support additional properties.
 *
 * @typedef GrammarToken
 * @property {RegExp} pattern The regular expression of the token.
 * @property {boolean} [lookbehind=false] If `true`, then the first capturing group of `pattern` will (effectively)
 * behave as a lookbehind group meaning that the captured text will not be part of the matched text of the new token.
 * @property {boolean} [greedy=false] Whether the token is greedy.
 * @property {string|string[]} [alias] An optional alias or list of aliases.
 * @property {Grammar} [inside] The nested grammar of this token.
 *
 * The `inside` grammar will be used to tokenize the text value of each token of this kind.
 *
 * This can be used to make nested and even recursive language definitions.
 *
 * Note: This can cause infinite recursion. Be careful when you embed different languages or even the same language into
 * each another.
 * @global
 * @public
*/

/**
 * @typedef Grammar
 * @type {Object<string, RegExp | GrammarToken | Array<RegExp | GrammarToken>>}
 * @property {Grammar} [rest] An optional grammar object that will be appended to this grammar.
 * @global
 * @public
 */

/**
 * A function which will invoked after an element was successfully highlighted.
 *
 * @callback HighlightCallback
 * @param {Element} element The element successfully highlighted.
 * @returns {void}
 * @global
 * @public
*/

/**
 * @callback HookCallback
 * @param {Object<string, any>} env The environment variables of the hook.
 * @returns {void}
 * @global
 * @public
 */


/* **********************************************
     Begin prism-markup.js
********************************************** */

Prism.languages.markup = {
	'comment': /<!--[\s\S]*?-->/,
	'prolog': /<\?[\s\S]+?\?>/,
	'doctype': {
		// https://www.w3.org/TR/xml/#NT-doctypedecl
		pattern: /<!DOCTYPE(?:[^>"'[\]]|"[^"]*"|'[^']*')+(?:\[(?:[^<"'\]]|"[^"]*"|'[^']*'|<(?!!--)|<!--(?:[^-]|-(?!->))*-->)*\]\s*)?>/i,
		greedy: true,
		inside: {
			'internal-subset': {
				pattern: /(\[)[\s\S]+(?=\]>$)/,
				lookbehind: true,
				greedy: true,
				inside: null // see below
			},
			'string': {
				pattern: /"[^"]*"|'[^']*'/,
				greedy: true
			},
			'punctuation': /^<!|>$|[[\]]/,
			'doctype-tag': /^DOCTYPE/,
			'name': /[^\s<>'"]+/
		}
	},
	'cdata': /<!\[CDATA\[[\s\S]*?]]>/i,
	'tag': {
		pattern: /<\/?(?!\d)[^\s>\/=$<%]+(?:\s(?:\s*[^\s>\/=]+(?:\s*=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+(?=[\s>]))|(?=[\s/>])))+)?\s*\/?>/,
		greedy: true,
		inside: {
			'tag': {
				pattern: /^<\/?[^\s>\/]+/,
				inside: {
					'punctuation': /^<\/?/,
					'namespace': /^[^\s>\/:]+:/
				}
			},
			'attr-value': {
				pattern: /=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+)/,
				inside: {
					'punctuation': [
						{
							pattern: /^=/,
							alias: 'attr-equals'
						},
						/"|'/
					]
				}
			},
			'punctuation': /\/?>/,
			'attr-name': {
				pattern: /[^\s>\/]+/,
				inside: {
					'namespace': /^[^\s>\/:]+:/
				}
			}

		}
	},
	'entity': [
		{
			pattern: /&[\da-z]{1,8};/i,
			alias: 'named-entity'
		},
		/&#x?[\da-f]{1,8};/i
	]
};

Prism.languages.markup['tag'].inside['attr-value'].inside['entity'] =
	Prism.languages.markup['entity'];
Prism.languages.markup['doctype'].inside['internal-subset'].inside = Prism.languages.markup;

// Plugin to make entity title show the real entity, idea by Roman Komarov
Prism.hooks.add('wrap', function (env) {

	if (env.type === 'entity') {
		env.attributes['title'] = env.content.replace(/&amp;/, '&');
	}
});

Object.defineProperty(Prism.languages.markup.tag, 'addInlined', {
	/**
	 * Adds an inlined language to markup.
	 *
	 * An example of an inlined language is CSS with `<style>` tags.
	 *
	 * @param {string} tagName The name of the tag that contains the inlined language. This name will be treated as
	 * case insensitive.
	 * @param {string} lang The language key.
	 * @example
	 * addInlined('style', 'css');
	 */
	value: function addInlined(tagName, lang) {
		var includedCdataInside = {};
		includedCdataInside['language-' + lang] = {
			pattern: /(^<!\[CDATA\[)[\s\S]+?(?=\]\]>$)/i,
			lookbehind: true,
			inside: Prism.languages[lang]
		};
		includedCdataInside['cdata'] = /^<!\[CDATA\[|\]\]>$/i;

		var inside = {
			'included-cdata': {
				pattern: /<!\[CDATA\[[\s\S]*?\]\]>/i,
				inside: includedCdataInside
			}
		};
		inside['language-' + lang] = {
			pattern: /[\s\S]+/,
			inside: Prism.languages[lang]
		};

		var def = {};
		def[tagName] = {
			pattern: RegExp(/(<__[^>]*>)(?:<!\[CDATA\[(?:[^\]]|\](?!\]>))*\]\]>|(?!<!\[CDATA\[)[\s\S])*?(?=<\/__>)/.source.replace(/__/g, function () { return tagName; }), 'i'),
			lookbehind: true,
			greedy: true,
			inside: inside
		};

		Prism.languages.insertBefore('markup', 'cdata', def);
	}
});

Prism.languages.html = Prism.languages.markup;
Prism.languages.mathml = Prism.languages.markup;
Prism.languages.svg = Prism.languages.markup;

Prism.languages.xml = Prism.languages.extend('markup', {});
Prism.languages.ssml = Prism.languages.xml;
Prism.languages.atom = Prism.languages.xml;
Prism.languages.rss = Prism.languages.xml;


/* **********************************************
     Begin prism-css.js
********************************************** */

(function (Prism) {

	var string = /("|')(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/;

	Prism.languages.css = {
		'comment': /\/\*[\s\S]*?\*\//,
		'atrule': {
			pattern: /@[\w-](?:[^;{\s]|\s+(?![\s{]))*(?:;|(?=\s*\{))/,
			inside: {
				'rule': /^@[\w-]+/,
				'selector-function-argument': {
					pattern: /(\bselector\s*\(\s*(?![\s)]))(?:[^()\s]|\s+(?![\s)])|\((?:[^()]|\([^()]*\))*\))+(?=\s*\))/,
					lookbehind: true,
					alias: 'selector'
				},
				'keyword': {
					pattern: /(^|[^\w-])(?:and|not|only|or)(?![\w-])/,
					lookbehind: true
				}
				// See rest below
			}
		},
		'url': {
			// https://drafts.csswg.org/css-values-3/#urls
			pattern: RegExp('\\burl\\((?:' + string.source + '|' + /(?:[^\\\r\n()"']|\\[\s\S])*/.source + ')\\)', 'i'),
			greedy: true,
			inside: {
				'function': /^url/i,
				'punctuation': /^\(|\)$/,
				'string': {
					pattern: RegExp('^' + string.source + '$'),
					alias: 'url'
				}
			}
		},
		'selector': RegExp('[^{}\\s](?:[^{};"\'\\s]|\\s+(?![\\s{])|' + string.source + ')*(?=\\s*\\{)'),
		'string': {
			pattern: string,
			greedy: true
		},
		'property': /(?!\s)[-_a-z\xA0-\uFFFF](?:(?!\s)[-\w\xA0-\uFFFF])*(?=\s*:)/i,
		'important': /!important\b/i,
		'function': /[-a-z0-9]+(?=\()/i,
		'punctuation': /[(){};:,]/
	};

	Prism.languages.css['atrule'].inside.rest = Prism.languages.css;

	var markup = Prism.languages.markup;
	if (markup) {
		markup.tag.addInlined('style', 'css');

		Prism.languages.insertBefore('inside', 'attr-value', {
			'style-attr': {
				pattern: /(^|["'\s])style\s*=\s*(?:"[^"]*"|'[^']*')/i,
				lookbehind: true,
				inside: {
					'attr-value': {
						pattern: /=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+)/,
						inside: {
							'style': {
								pattern: /(["'])[\s\S]+(?=["']$)/,
								lookbehind: true,
								alias: 'language-css',
								inside: Prism.languages.css
							},
							'punctuation': [
								{
									pattern: /^=/,
									alias: 'attr-equals'
								},
								/"|'/
							]
						}
					},
					'attr-name': /^style/i
				}
			}
		}, markup.tag);
	}

}(Prism));


/* **********************************************
     Begin prism-clike.js
********************************************** */

Prism.languages.clike = {
	'comment': [
		{
			pattern: /(^|[^\\])\/\*[\s\S]*?(?:\*\/|$)/,
			lookbehind: true,
			greedy: true
		},
		{
			pattern: /(^|[^\\:])\/\/.*/,
			lookbehind: true,
			greedy: true
		}
	],
	'string': {
		pattern: /(["'])(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,
		greedy: true
	},
	'class-name': {
		pattern: /(\b(?:class|interface|extends|implements|trait|instanceof|new)\s+|\bcatch\s+\()[\w.\\]+/i,
		lookbehind: true,
		inside: {
			'punctuation': /[.\\]/
		}
	},
	'keyword': /\b(?:if|else|while|do|for|return|in|instanceof|function|new|try|throw|catch|finally|null|break|continue)\b/,
	'boolean': /\b(?:true|false)\b/,
	'function': /\w+(?=\()/,
	'number': /\b0x[\da-f]+\b|(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:e[+-]?\d+)?/i,
	'operator': /[<>]=?|[!=]=?=?|--?|\+\+?|&&?|\|\|?|[?*/~^%]/,
	'punctuation': /[{}[\];(),.:]/
};


/* **********************************************
     Begin prism-javascript.js
********************************************** */

Prism.languages.javascript = Prism.languages.extend('clike', {
	'class-name': [
		Prism.languages.clike['class-name'],
		{
			pattern: /(^|[^$\w\xA0-\uFFFF])(?!\s)[_$A-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\.(?:prototype|constructor))/,
			lookbehind: true
		}
	],
	'keyword': [
		{
			pattern: /((?:^|})\s*)(?:catch|finally)\b/,
			lookbehind: true
		},
		{
			pattern: /(^|[^.]|\.\.\.\s*)\b(?:as|async(?=\s*(?:function\b|\(|[$\w\xA0-\uFFFF]|$))|await|break|case|class|const|continue|debugger|default|delete|do|else|enum|export|extends|for|from|function|(?:get|set)(?=\s*[\[$\w\xA0-\uFFFF])|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|static|super|switch|this|throw|try|typeof|undefined|var|void|while|with|yield)\b/,
			lookbehind: true
		},
	],
	// Allow for all non-ASCII characters (See http://stackoverflow.com/a/2008444)
	'function': /#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*(?:\.\s*(?:apply|bind|call)\s*)?\()/,
	'number': /\b(?:(?:0[xX](?:[\dA-Fa-f](?:_[\dA-Fa-f])?)+|0[bB](?:[01](?:_[01])?)+|0[oO](?:[0-7](?:_[0-7])?)+)n?|(?:\d(?:_\d)?)+n|NaN|Infinity)\b|(?:\b(?:\d(?:_\d)?)+\.?(?:\d(?:_\d)?)*|\B\.(?:\d(?:_\d)?)+)(?:[Ee][+-]?(?:\d(?:_\d)?)+)?/,
	'operator': /--|\+\+|\*\*=?|=>|&&=?|\|\|=?|[!=]==|<<=?|>>>?=?|[-+*/%&|^!=<>]=?|\.{3}|\?\?=?|\?\.?|[~:]/
});

Prism.languages.javascript['class-name'][0].pattern = /(\b(?:class|interface|extends|implements|instanceof|new)\s+)[\w.\\]+/;

Prism.languages.insertBefore('javascript', 'keyword', {
	'regex': {
		pattern: /((?:^|[^$\w\xA0-\uFFFF."'\])\s]|\b(?:return|yield))\s*)\/(?:\[(?:[^\]\\\r\n]|\\.)*]|\\.|[^/\\\[\r\n])+\/[gimyus]{0,6}(?=(?:\s|\/\*(?:[^*]|\*(?!\/))*\*\/)*(?:$|[\r\n,.;:})\]]|\/\/))/,
		lookbehind: true,
		greedy: true,
		inside: {
			'regex-source': {
				pattern: /^(\/)[\s\S]+(?=\/[a-z]*$)/,
				lookbehind: true,
				alias: 'language-regex',
				inside: Prism.languages.regex
			},
			'regex-flags': /[a-z]+$/,
			'regex-delimiter': /^\/|\/$/
		}
	},
	// This must be declared before keyword because we use "function" inside the look-forward
	'function-variable': {
		pattern: /#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*[=:]\s*(?:async\s*)?(?:\bfunction\b|(?:\((?:[^()]|\([^()]*\))*\)|(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*)\s*=>))/,
		alias: 'function'
	},
	'parameter': [
		{
			pattern: /(function(?:\s+(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*)?\s*\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\))/,
			lookbehind: true,
			inside: Prism.languages.javascript
		},
		{
			pattern: /(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*=>)/i,
			inside: Prism.languages.javascript
		},
		{
			pattern: /(\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\)\s*=>)/,
			lookbehind: true,
			inside: Prism.languages.javascript
		},
		{
			pattern: /((?:\b|\s|^)(?!(?:as|async|await|break|case|catch|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally|for|from|function|get|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|set|static|super|switch|this|throw|try|typeof|undefined|var|void|while|with|yield)(?![$\w\xA0-\uFFFF]))(?:(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*\s*)\(\s*|\]\s*\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\)\s*\{)/,
			lookbehind: true,
			inside: Prism.languages.javascript
		}
	],
	'constant': /\b[A-Z](?:[A-Z_]|\dx?)*\b/
});

Prism.languages.insertBefore('javascript', 'string', {
	'template-string': {
		pattern: /`(?:\\[\s\S]|\${(?:[^{}]|{(?:[^{}]|{[^}]*})*})+}|(?!\${)[^\\`])*`/,
		greedy: true,
		inside: {
			'template-punctuation': {
				pattern: /^`|`$/,
				alias: 'string'
			},
			'interpolation': {
				pattern: /((?:^|[^\\])(?:\\{2})*)\${(?:[^{}]|{(?:[^{}]|{[^}]*})*})+}/,
				lookbehind: true,
				inside: {
					'interpolation-punctuation': {
						pattern: /^\${|}$/,
						alias: 'punctuation'
					},
					rest: Prism.languages.javascript
				}
			},
			'string': /[\s\S]+/
		}
	}
});

if (Prism.languages.markup) {
	Prism.languages.markup.tag.addInlined('script', 'javascript');
}

Prism.languages.js = Prism.languages.javascript;


/* **********************************************
     Begin prism-file-highlight.js
********************************************** */

(function () {
	if (typeof self === 'undefined' || !self.Prism || !self.document) {
		return;
	}

	// https://developer.mozilla.org/en-US/docs/Web/API/Element/matches#Polyfill
	if (!Element.prototype.matches) {
		Element.prototype.matches = Element.prototype.msMatchesSelector || Element.prototype.webkitMatchesSelector;
	}

	var Prism = window.Prism;

	var LOADING_MESSAGE = 'Loading…';
	var FAILURE_MESSAGE = function (status, message) {
		return '✖ Error ' + status + ' while fetching file: ' + message;
	};
	var FAILURE_EMPTY_MESSAGE = '✖ Error: File does not exist or is empty';

	var EXTENSIONS = {
		'js': 'javascript',
		'py': 'python',
		'rb': 'ruby',
		'ps1': 'powershell',
		'psm1': 'powershell',
		'sh': 'bash',
		'bat': 'batch',
		'h': 'c',
		'tex': 'latex'
	};

	var STATUS_ATTR = 'data-src-status';
	var STATUS_LOADING = 'loading';
	var STATUS_LOADED = 'loaded';
	var STATUS_FAILED = 'failed';

	var SELECTOR = 'pre[data-src]:not([' + STATUS_ATTR + '="' + STATUS_LOADED + '"])'
		+ ':not([' + STATUS_ATTR + '="' + STATUS_LOADING + '"])';

	var lang = /\blang(?:uage)?-([\w-]+)\b/i;

	/**
	 * Sets the Prism `language-xxxx` or `lang-xxxx` class to the given language.
	 *
	 * @param {HTMLElement} element
	 * @param {string} language
	 * @returns {void}
	 */
	function setLanguageClass(element, language) {
		var className = element.className;
		className = className.replace(lang, ' ') + ' language-' + language;
		element.className = className.replace(/\s+/g, ' ').trim();
	}


	Prism.hooks.add('before-highlightall', function (env) {
		env.selector += ', ' + SELECTOR;
	});

	Prism.hooks.add('before-sanity-check', function (env) {
		var pre = /** @type {HTMLPreElement} */ (env.element);
		if (pre.matches(SELECTOR)) {
			env.code = ''; // fast-path the whole thing and go to complete

			pre.setAttribute(STATUS_ATTR, STATUS_LOADING); // mark as loading

			// add code element with loading message
			var code = pre.appendChild(document.createElement('CODE'));
			code.textContent = LOADING_MESSAGE;

			var src = pre.getAttribute('data-src');

			var language = env.language;
			if (language === 'none') {
				// the language might be 'none' because there is no language set;
				// in this case, we want to use the extension as the language
				var extension = (/\.(\w+)$/.exec(src) || [, 'none'])[1];
				language = EXTENSIONS[extension] || extension;
			}

			// set language classes
			setLanguageClass(code, language);
			setLanguageClass(pre, language);

			// preload the language
			var autoloader = Prism.plugins.autoloader;
			if (autoloader) {
				autoloader.loadLanguages(language);
			}

			// load file
			var xhr = new XMLHttpRequest();
			xhr.open('GET', src, true);
			xhr.onreadystatechange = function () {
				if (xhr.readyState == 4) {
					if (xhr.status < 400 && xhr.responseText) {
						// mark as loaded
						pre.setAttribute(STATUS_ATTR, STATUS_LOADED);

						// highlight code
						code.textContent = xhr.responseText;
						Prism.highlightElement(code);

					} else {
						// mark as failed
						pre.setAttribute(STATUS_ATTR, STATUS_FAILED);

						if (xhr.status >= 400) {
							code.textContent = FAILURE_MESSAGE(xhr.status, xhr.statusText);
						} else {
							code.textContent = FAILURE_EMPTY_MESSAGE;
						}
					}
				}
			};
			xhr.send(null);
		}
	});

	Prism.plugins.fileHighlight = {
		/**
		 * Executes the File Highlight plugin for all matching `pre` elements under the given container.
		 *
		 * Note: Elements which are already loaded or currently loading will not be touched by this method.
		 *
		 * @param {ParentNode} [container=document]
		 */
		highlight: function highlight(container) {
			var elements = (container || document).querySelectorAll(SELECTOR);

			for (var i = 0, element; element = elements[i++];) {
				Prism.highlightElement(element);
			}
		}
	};

	var logged = false;
	/** @deprecated Use `Prism.plugins.fileHighlight.highlight` instead. */
	Prism.fileHighlight = function () {
		if (!logged) {
			console.warn('Prism.fileHighlight is deprecated. Use `Prism.plugins.fileHighlight.highlight` instead.');
			logged = true;
		}
		Prism.plugins.fileHighlight.highlight.apply(this, arguments);
	};

})();
});

Prism.languages.python = {
	'comment': {
		pattern: /(^|[^\\])#.*/,
		lookbehind: true
	},
	'string-interpolation': {
		pattern: /(?:f|rf|fr)(?:("""|''')[\s\S]*?\1|("|')(?:\\.|(?!\2)[^\\\r\n])*\2)/i,
		greedy: true,
		inside: {
			'interpolation': {
				// "{" <expression> <optional "!s", "!r", or "!a"> <optional ":" format specifier> "}"
				pattern: /((?:^|[^{])(?:{{)*){(?!{)(?:[^{}]|{(?!{)(?:[^{}]|{(?!{)(?:[^{}])+})+})+}/,
				lookbehind: true,
				inside: {
					'format-spec': {
						pattern: /(:)[^:(){}]+(?=}$)/,
						lookbehind: true
					},
					'conversion-option': {
						pattern: /![sra](?=[:}]$)/,
						alias: 'punctuation'
					},
					rest: null
				}
			},
			'string': /[\s\S]+/
		}
	},
	'triple-quoted-string': {
		pattern: /(?:[rub]|rb|br)?("""|''')[\s\S]*?\1/i,
		greedy: true,
		alias: 'string'
	},
	'string': {
		pattern: /(?:[rub]|rb|br)?("|')(?:\\.|(?!\1)[^\\\r\n])*\1/i,
		greedy: true
	},
	'function': {
		pattern: /((?:^|\s)def[ \t]+)[a-zA-Z_]\w*(?=\s*\()/g,
		lookbehind: true
	},
	'class-name': {
		pattern: /(\bclass\s+)\w+/i,
		lookbehind: true
	},
	'decorator': {
		pattern: /(^\s*)@\w+(?:\.\w+)*/im,
		lookbehind: true,
		alias: ['annotation', 'punctuation'],
		inside: {
			'punctuation': /\./
		}
	},
	'keyword': /\b(?:and|as|assert|async|await|break|class|continue|def|del|elif|else|except|exec|finally|for|from|global|if|import|in|is|lambda|nonlocal|not|or|pass|print|raise|return|try|while|with|yield)\b/,
	'builtin': /\b(?:__import__|abs|all|any|apply|ascii|basestring|bin|bool|buffer|bytearray|bytes|callable|chr|classmethod|cmp|coerce|compile|complex|delattr|dict|dir|divmod|enumerate|eval|execfile|file|filter|float|format|frozenset|getattr|globals|hasattr|hash|help|hex|id|input|int|intern|isinstance|issubclass|iter|len|list|locals|long|map|max|memoryview|min|next|object|oct|open|ord|pow|property|range|raw_input|reduce|reload|repr|reversed|round|set|setattr|slice|sorted|staticmethod|str|sum|super|tuple|type|unichr|unicode|vars|xrange|zip)\b/,
	'boolean': /\b(?:True|False|None)\b/,
	'number': /(?:\b(?=\d)|\B(?=\.))(?:0[bo])?(?:(?:\d|0x[\da-f])[\da-f]*(?:\.\d*)?|\.\d+)(?:e[+-]?\d+)?j?\b/i,
	'operator': /[-+%=]=?|!=|\*\*?=?|\/\/?=?|<[<=>]?|>[=>]?|[&|^~]/,
	'punctuation': /[{}[\];(),.:]/
};

Prism.languages.python['string-interpolation'].inside['interpolation'].inside.rest = Prism.languages.python;

Prism.languages.py = Prism.languages.python;

(function () {

	if (typeof self === 'undefined' || !self.Prism || !self.document) {
		return;
	}

	/**
	 * Plugin name which is used as a class name for <pre> which is activating the plugin
	 * @type {String}
	 */
	var PLUGIN_NAME = 'line-numbers';

	/**
	 * Regular expression used for determining line breaks
	 * @type {RegExp}
	 */
	var NEW_LINE_EXP = /\n(?!$)/g;


	/**
	 * Global exports
	 */
	var config = Prism.plugins.lineNumbers = {
		/**
		 * Get node for provided line number
		 * @param {Element} element pre element
		 * @param {Number} number line number
		 * @return {Element|undefined}
		 */
		getLine: function (element, number) {
			if (element.tagName !== 'PRE' || !element.classList.contains(PLUGIN_NAME)) {
				return;
			}

			var lineNumberRows = element.querySelector('.line-numbers-rows');
			if (!lineNumberRows) {
				return;
			}
			var lineNumberStart = parseInt(element.getAttribute('data-start'), 10) || 1;
			var lineNumberEnd = lineNumberStart + (lineNumberRows.children.length - 1);

			if (number < lineNumberStart) {
				number = lineNumberStart;
			}
			if (number > lineNumberEnd) {
				number = lineNumberEnd;
			}

			var lineIndex = number - lineNumberStart;

			return lineNumberRows.children[lineIndex];
		},

		/**
		 * Resizes the line numbers of the given element.
		 *
		 * This function will not add line numbers. It will only resize existing ones.
		 * @param {HTMLElement} element A `<pre>` element with line numbers.
		 * @returns {void}
		 */
		resize: function (element) {
			resizeElements([element]);
		},

		/**
		 * Whether the plugin can assume that the units font sizes and margins are not depended on the size of
		 * the current viewport.
		 *
		 * Setting this to `true` will allow the plugin to do certain optimizations for better performance.
		 *
		 * Set this to `false` if you use any of the following CSS units: `vh`, `vw`, `vmin`, `vmax`.
		 *
		 * @type {boolean}
		 */
		assumeViewportIndependence: true
	};

	/**
	 * Resizes the given elements.
	 *
	 * @param {HTMLElement[]} elements
	 */
	function resizeElements(elements) {
		elements = elements.filter(function (e) {
			var codeStyles = getStyles(e);
			var whiteSpace = codeStyles['white-space'];
			return whiteSpace === 'pre-wrap' || whiteSpace === 'pre-line';
		});

		if (elements.length == 0) {
			return;
		}

		var infos = elements.map(function (element) {
			var codeElement = element.querySelector('code');
			var lineNumbersWrapper = element.querySelector('.line-numbers-rows');
			if (!codeElement || !lineNumbersWrapper) {
				return undefined;
			}

			/** @type {HTMLElement} */
			var lineNumberSizer = element.querySelector('.line-numbers-sizer');
			var codeLines = codeElement.textContent.split(NEW_LINE_EXP);

			if (!lineNumberSizer) {
				lineNumberSizer = document.createElement('span');
				lineNumberSizer.className = 'line-numbers-sizer';

				codeElement.appendChild(lineNumberSizer);
			}

			lineNumberSizer.innerHTML = '0';
			lineNumberSizer.style.display = 'block';

			var oneLinerHeight = lineNumberSizer.getBoundingClientRect().height;
			lineNumberSizer.innerHTML = '';

			return {
				element: element,
				lines: codeLines,
				lineHeights: [],
				oneLinerHeight: oneLinerHeight,
				sizer: lineNumberSizer,
			};
		}).filter(Boolean);

		infos.forEach(function (info) {
			var lineNumberSizer = info.sizer;
			var lines = info.lines;
			var lineHeights = info.lineHeights;
			var oneLinerHeight = info.oneLinerHeight;

			lineHeights[lines.length - 1] = undefined;
			lines.forEach(function (line, index) {
				if (line && line.length > 1) {
					var e = lineNumberSizer.appendChild(document.createElement('span'));
					e.style.display = 'block';
					e.textContent = line;
				} else {
					lineHeights[index] = oneLinerHeight;
				}
			});
		});

		infos.forEach(function (info) {
			var lineNumberSizer = info.sizer;
			var lineHeights = info.lineHeights;

			var childIndex = 0;
			for (var i = 0; i < lineHeights.length; i++) {
				if (lineHeights[i] === undefined) {
					lineHeights[i] = lineNumberSizer.children[childIndex++].getBoundingClientRect().height;
				}
			}
		});

		infos.forEach(function (info) {
			var lineNumberSizer = info.sizer;
			var wrapper = info.element.querySelector('.line-numbers-rows');

			lineNumberSizer.style.display = 'none';
			lineNumberSizer.innerHTML = '';

			info.lineHeights.forEach(function (height, lineNumber) {
				wrapper.children[lineNumber].style.height = height + 'px';
			});
		});
	}

	/**
	 * Returns style declarations for the element
	 * @param {Element} element
	 */
	var getStyles = function (element) {
		if (!element) {
			return null;
		}

		return window.getComputedStyle ? getComputedStyle(element) : (element.currentStyle || null);
	};

	var lastWidth = undefined;
	window.addEventListener('resize', function () {
		if (config.assumeViewportIndependence && lastWidth === window.innerWidth) {
			return;
		}
		lastWidth = window.innerWidth;

		resizeElements(Array.prototype.slice.call(document.querySelectorAll('pre.' + PLUGIN_NAME)));
	});

	Prism.hooks.add('complete', function (env) {
		if (!env.code) {
			return;
		}

		var code = /** @type {Element} */ (env.element);
		var pre = /** @type {HTMLElement} */ (code.parentNode);

		// works only for <code> wrapped inside <pre> (not inline)
		if (!pre || !/pre/i.test(pre.nodeName)) {
			return;
		}

		// Abort if line numbers already exists
		if (code.querySelector('.line-numbers-rows')) {
			return;
		}

		// only add line numbers if <code> or one of its ancestors has the `line-numbers` class
		if (!Prism.util.isActive(code, PLUGIN_NAME)) {
			return;
		}

		// Remove the class 'line-numbers' from the <code>
		code.classList.remove(PLUGIN_NAME);
		// Add the class 'line-numbers' to the <pre>
		pre.classList.add(PLUGIN_NAME);

		var match = env.code.match(NEW_LINE_EXP);
		var linesNum = match ? match.length + 1 : 1;
		var lineNumbersWrapper;

		var lines = new Array(linesNum + 1).join('<span></span>');

		lineNumbersWrapper = document.createElement('span');
		lineNumbersWrapper.setAttribute('aria-hidden', 'true');
		lineNumbersWrapper.className = 'line-numbers-rows';
		lineNumbersWrapper.innerHTML = lines;

		if (pre.hasAttribute('data-start')) {
			pre.style.counterReset = 'linenumber ' + (parseInt(pre.getAttribute('data-start'), 10) - 1);
		}

		env.element.appendChild(lineNumbersWrapper);

		resizeElements([pre]);

		Prism.hooks.run('line-numbers', env);
	});

	Prism.hooks.add('line-numbers', function (env) {
		env.plugins = env.plugins || {};
		env.plugins.lineNumbers = true;
	});

}());

var arg_types = createCommonjsModule(function (module, exports) {
// Copyright (C) 2021 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use size 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.
Object.defineProperty(exports, "__esModule", { value: true });
exports.isArgTreeMap = exports.isArgTreeArray = void 0;
function isArgTreeArray(item) {
    return typeof item === 'object' && item.length !== undefined;
}
exports.isArgTreeArray = isArgTreeArray;
function isArgTreeMap(item) {
    return typeof item === 'object' && item.length === undefined;
}
exports.isArgTreeMap = isArgTreeMap;

});

var chrome_slice_panel = createCommonjsModule(function (module, exports) {
// Copyright (C) 2019 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use size 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.
Object.defineProperty(exports, "__esModule", { value: true });
exports.ChromeSliceDetailsPanel = void 0;










function isTableHeader(contents) {
    return contents.kind === 'TableHeader';
}
class TableBuilder {
    constructor() {
        // Stack contains indices inside repeated fields, or -1 if the appropriate
        // index is already displayed.
        this.stack = [];
        // Row data generated by builder
        this.rows = [];
        // Maximum indent level of a key, used to determine total number of columns
        this.maxIndent = 0;
    }
    // Add a key-value pair into the table
    add(key, value) {
        this.rows.push({ indentLevel: 0, index: -1, contents: { kind: 'KVPair', key, value } });
    }
    // Add arguments tree into the table
    addTree(tree) {
        this.addTreeInternal(tree, '');
    }
    // Return indent level and index for a fresh row
    prepareRow() {
        const level = this.stack.length;
        let index = -1;
        if (level > 0) {
            index = this.stack[level - 1];
            if (index !== -1) {
                this.stack[level - 1] = -1;
            }
        }
        this.maxIndent = Math.max(this.maxIndent, level);
        return [level, index];
    }
    addTreeInternal(record, prefix) {
        if (arg_types.isArgTreeArray(record)) {
            // Add the current prefix as a separate row
            const row = this.prepareRow();
            this.rows.push({
                indentLevel: row[0],
                index: row[1],
                contents: { kind: 'TableHeader', header: prefix }
            });
            for (let i = 0; i < record.length; i++) {
                // Push the current array index to the stack.
                this.stack.push(i);
                // Prefix is empty for array elements because we don't want to repeat
                // the common prefix
                this.addTreeInternal(record[i], '');
                this.stack.pop();
            }
        }
        else if (arg_types.isArgTreeMap(record)) {
            for (const [key, value] of Object.entries(record)) {
                // If the prefix was non-empty, we have to add dot at the end as well.
                const newPrefix = (prefix === '') ? key : prefix + '.' + key;
                this.addTreeInternal(value, newPrefix);
            }
        }
        else {
            // Leaf value in the tree: add to the table
            const row = this.prepareRow();
            this.rows.push({
                indentLevel: row[0],
                index: row[1],
                contents: { kind: 'KVPair', key: prefix, value: record }
            });
        }
    }
}
class ChromeSliceDetailsPanel extends panel.Panel {
    constructor() {
        super(...arguments);
        this.pre_height = 100;
    }
    view() {
        const sliceInfo = globals$1.globals.sliceDetails;
        if (sliceInfo.ts !== undefined && sliceInfo.dur !== undefined &&
            sliceInfo.name !== undefined) {
            const builder = new TableBuilder();
            builder.add('Name', sliceInfo.name);
            builder.add('Category', !sliceInfo.category || sliceInfo.category === '[NULL]' ?
                'N/A' :
                sliceInfo.category);
            builder.add('Start time', time.timeToCode(sliceInfo.ts));
            builder.add('Duration', time.toNs(sliceInfo.dur) === -1 ? '-1 (Did not end)' :
                time.timeToCode(sliceInfo.dur));
            builder.add('Slice ID', sliceInfo.id ? sliceInfo.id.toString() : 'Unknown');
            if (sliceInfo.description) {
                this.fillDescription(sliceInfo.description, builder);
            }
            this.fillArgs(sliceInfo, builder);
            // Find source code
            const funcName = sliceInfo.name;
            const sourceStorage = globals$1.globals.sourceFileStorage;
            if (sourceStorage && sourceStorage["functions"]) {
                const file_data = sourceStorage["functions"][funcName] || null;
                if (file_data) {
                    const file_name = file_data[0];
                    const lineno = file_data[1];
                    const code = sourceStorage["files"][file_name][0];
                    const total_lineno = sourceStorage["files"][file_name][1];
                    return mithril('.details-panel', mithril('.details-panel-heading', mithril('h2', `Slice Details`)), mithril('.details-table', this.renderTable(builder), mithril('.details-source .half-width', this.renderSourceCode(code, lineno, total_lineno))));
                }
            }
            return mithril('.details-panel', mithril('.details-panel-heading', mithril('h2', `Slice Details`)), mithril('.details-table', this.renderTable(builder)));
        }
        else {
            return mithril('.details-panel', mithril('.details-panel-heading', mithril('h2', `Slice Details`)));
        }
    }
    renderCanvas(_ctx, _size) { }
    fillArgs(slice, builder) {
        if (slice.argsTree && slice.args) {
            // Parsed arguments are available, need only to iterate over them to get
            // slice references
            for (const [key, value] of slice.args) {
                if (typeof value !== 'string') {
                    builder.add(key, value);
                }
            }
            builder.addTree(slice.argsTree);
        }
        else if (slice.args) {
            // Parsing has failed, but arguments are available: display them in a flat
            // 2-column table
            for (const [key, value] of slice.args) {
                builder.add(key, value);
            }
        }
    }
    renderTable(builder) {
        const rows = [];
        const keyColumnCount = builder.maxIndent + 1;
        for (const row of builder.rows) {
            const renderedRow = [];
            let indent = row.indentLevel;
            if (row.index !== -1) {
                indent--;
            }
            if (indent > 0) {
                renderedRow.push(mithril('td', { colspan: indent }));
            }
            if (row.index !== -1) {
                renderedRow.push(mithril('td', { class: 'array-index' }, `[${row.index}]`));
            }
            if (isTableHeader(row.contents)) {
                renderedRow.push(mithril('th', { colspan: keyColumnCount + 1 - row.indentLevel }, row.contents.header));
            }
            else {
                renderedRow.push(mithril('th', { colspan: keyColumnCount - row.indentLevel }, row.contents.key));
                const value = row.contents.value;
                if (typeof value === 'string') {
                    renderedRow.push(mithril('td', value));
                }
                else {
                    // Type of value being a record is not propagated into the callback
                    // for some reason, extracting necessary parts as constants instead.
                    const sliceId = value.sliceId;
                    const trackId = value.trackId;
                    renderedRow.push(mithril('td', mithril('i.material-icons.grey', {
                        onclick: () => {
                            globals$1.globals.makeSelection(actions.Actions.selectChromeSlice({ id: sliceId, trackId, table: 'slice' }));
                            // Ideally we want to have a callback to
                            // findCurrentSelection after this selection has been
                            // made. Here we do not have the info for horizontally
                            // scrolling to ts.
                            scroll_helper.verticalScrollToTrack(trackId, true);
                        },
                        title: 'Go to destination slice'
                    }, 'call_made')));
                }
            }
            rows.push(mithril('tr', renderedRow));
        }
        return mithril('table.half-width.auto-layout', rows);
    }
    renderSourceCode(code, lineno, total_lineno) {
        var el_pre = document.createElement("pre");
        var el_code = document.createElement("code");
        el_pre.className = "language-py line-numbers";
        el_code.className = "language-py";
        el_pre.appendChild(el_code);
        el_code.innerHTML = prism.highlight(code, prism.languages.python, "python");
        var env = {
            element: el_code,
            language: "python",
            grammar: prism.languages.python,
            code: code
        };
        prism.hooks.run("complete", env);
        return mithril('pre.language-py.line-numbers', {
            style: {
                height: `${this.pre_height}px`
            },
            oncreate: () => {
                this.resize(lineno, total_lineno);
            },
            onupdate: () => {
                this.resize(lineno, total_lineno);
            }
        }, mithril.trust(el_pre.innerHTML));
    }
    resize(lineno, total_lineno) {
        var contents_height = document.getElementsByClassName("details-content")[0].clientHeight;
        var handle_height = document.getElementsByClassName("handle")[0].clientHeight;
        var heading_height = document.getElementsByClassName("details-panel-heading")[0].clientHeight;
        this.pre_height = contents_height - handle_height - heading_height;
        const pre_el = document.querySelector("pre.language-py");
        const code_el = document.querySelector("code.language-py");
        if (pre_el !== null && code_el !== null) {
            pre_el.scrollTop = 12 + (lineno - 1) / total_lineno * code_el.offsetHeight;
        }
    }
    fillDescription(description, builder) {
        for (const [key, value] of description) {
            builder.add(key, value);
        }
    }
}
exports.ChromeSliceDetailsPanel = ChromeSliceDetailsPanel;

});

var counter_panel = createCommonjsModule(function (module, exports) {
// Copyright (C) 2019 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use size 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.
Object.defineProperty(exports, "__esModule", { value: true });
exports.CounterDetailsPanel = void 0;




class CounterDetailsPanel extends panel.Panel {
    view() {
        const counterInfo = globals$1.globals.counterDetails;
        if (counterInfo && counterInfo.startTime &&
            counterInfo.value !== undefined && counterInfo.delta !== undefined &&
            counterInfo.duration !== undefined) {
            return mithril('.details-panel', mithril('.details-panel-heading', mithril('h2', `Counter Details`)), mithril('.details-table', [mithril('table.half-width', [
                    mithril('tr', mithril('th', `Start time`), mithril('td', `${time.timeToCode(counterInfo.startTime)}`)),
                    mithril('tr', mithril('th', `Value`), mithril('td', `${counterInfo.value.toLocaleString()}`)),
                    mithril('tr', mithril('th', `Delta`), mithril('td', `${counterInfo.delta.toLocaleString()}`)),
                    mithril('tr', mithril('th', `Duration`), mithril('td', `${time.timeToCode(time.fromNs(counterInfo.duration))}`)),
                ])]));
        }
        else {
            return mithril('.details-panel', mithril('.details-panel-heading', mithril('h2', `Counter Details`)));
        }
    }
    renderCanvas() { }
}
exports.CounterDetailsPanel = CounterDetailsPanel;

});

var cpu_profile_panel = createCommonjsModule(function (module, exports) {
// Copyright (C) 2020 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use size 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.
Object.defineProperty(exports, "__esModule", { value: true });
exports.CpuProfileDetailsPanel = void 0;



class CpuProfileDetailsPanel extends panel.Panel {
    view() {
        const sampleDetails = globals$1.globals.cpuProfileDetails;
        const header = mithril('.details-panel-heading', mithril('h2', `CPU Profile Sample Details`));
        if (!sampleDetails || sampleDetails.id === undefined) {
            return mithril('.details-panel', header);
        }
        return mithril('.details-panel', header, mithril('table', this.getStackText(sampleDetails.stack)));
    }
    getStackText(stack) {
        if (!stack)
            return [];
        const result = [];
        for (let i = 0; i < stack.length; i++) {
            result.push(mithril('tr', mithril('td', stack[i].name), mithril('td', stack[i].mapping)));
        }
        return result;
    }
    renderCanvas() { }
}
exports.CpuProfileDetailsPanel = CpuProfileDetailsPanel;

});

var drag_gesture_handler = createCommonjsModule(function (module, exports) {
// 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.
Object.defineProperty(exports, "__esModule", { value: true });
exports.DragGestureHandler = void 0;
class DragGestureHandler {
    constructor(element, onDrag, onDragStarted = () => { }, onDragFinished = () => { }) {
        this.element = element;
        this.onDrag = onDrag;
        this.onDragStarted = onDragStarted;
        this.onDragFinished = onDragFinished;
        this.boundOnMouseDown = this.onMouseDown.bind(this);
        this.boundOnMouseMove = this.onMouseMove.bind(this);
        this.boundOnMouseUp = this.onMouseUp.bind(this);
        this._isDragging = false;
        element.addEventListener('mousedown', this.boundOnMouseDown);
    }
    onMouseDown(e) {
        this._isDragging = true;
        document.body.addEventListener('mousemove', this.boundOnMouseMove);
        document.body.addEventListener('mouseup', this.boundOnMouseUp);
        this.pendingMouseDownEvent = e;
        // Prevent interactions with other DragGestureHandlers and event listeners
        e.stopPropagation();
    }
    // We don't start the drag gesture on mouse down, instead we wait until
    // the mouse has moved at least 1px. This prevents accidental drags that
    // were meant to be clicks.
    startDragGesture(e) {
        this.clientRect = this.element.getBoundingClientRect();
        this.onDragStarted(e.clientX - this.clientRect.left, e.clientY - this.clientRect.top);
    }
    onMouseMove(e) {
        if (e.buttons === 0) {
            return this.onMouseUp(e);
        }
        if (this.pendingMouseDownEvent &&
            (Math.abs(e.clientX - this.pendingMouseDownEvent.clientX) > 1 ||
                Math.abs(e.clientY - this.pendingMouseDownEvent.clientY) > 1)) {
            this.startDragGesture(this.pendingMouseDownEvent);
            this.pendingMouseDownEvent = undefined;
        }
        if (!this.pendingMouseDownEvent) {
            this.onDrag(e.clientX - this.clientRect.left, e.clientY - this.clientRect.top);
        }
        e.stopPropagation();
    }
    onMouseUp(e) {
        this._isDragging = false;
        document.body.removeEventListener('mousemove', this.boundOnMouseMove);
        document.body.removeEventListener('mouseup', this.boundOnMouseUp);
        if (!this.pendingMouseDownEvent) {
            this.onDragFinished();
        }
        e.stopPropagation();
    }
    get isDragging() {
        return this._isDragging;
    }
}
exports.DragGestureHandler = DragGestureHandler;

});

var flow_events_panel = createCommonjsModule(function (module, exports) {
// Copyright (C) 2020 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use size 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.
Object.defineProperty(exports, "__esModule", { value: true });
exports.FlowEventsAreaSelectedPanel = exports.FlowEventsPanel = exports.getFlowCategories = exports.ALL_CATEGORIES = void 0;






exports.ALL_CATEGORIES = '_all_';
function getFlowCategories(flow) {
    const categories = [];
    // v1 flows have their own categories
    if (flow.category) {
        categories.push(...flow.category.split(','));
        return categories;
    }
    const beginCats = flow.begin.sliceCategory.split(',');
    const endCats = flow.end.sliceCategory.split(',');
    categories.push(...new Set([...beginCats, ...endCats]));
    return categories;
}
exports.getFlowCategories = getFlowCategories;
class FlowEventsPanel extends panel.Panel {
    view() {
        const selection = globals$1.globals.state.currentSelection;
        if (!selection || selection.kind !== 'CHROME_SLICE') {
            return;
        }
        const flowClickHandler = (sliceId, trackId) => {
            const uiTrackId = scroll_helper.findUiTrackId(trackId);
            if (uiTrackId) {
                globals$1.globals.makeSelection(actions.Actions.selectChromeSlice({ id: sliceId, trackId: uiTrackId, table: 'slice' }), 'bound_flows');
            }
        };
        // Can happen only for flow events version 1
        const haveCategories = globals$1.globals.connectedFlows.filter(flow => flow.category).length > 0;
        const columns = [
            mithril('th', 'Direction'),
            mithril('th', 'Connected Slice ID'),
            mithril('th', 'Connected Slice Name')
        ];
        if (haveCategories) {
            columns.push(mithril('th', 'Flow Category'));
            columns.push(mithril('th', 'Flow Name'));
        }
        const rows = [mithril('tr', columns)];
        // Fill the table with all the directly connected flow events
        globals$1.globals.connectedFlows.forEach(flow => {
            if (selection.id !== flow.begin.sliceId &&
                selection.id !== flow.end.sliceId) {
                return;
            }
            const outgoing = selection.id === flow.begin.sliceId;
            const otherEnd = (outgoing ? flow.end : flow.begin);
            const args = {
                onclick: () => flowClickHandler(otherEnd.sliceId, otherEnd.trackId),
                onmousemove: () => globals$1.globals.frontendLocalState.setHighlightedSliceId(otherEnd.sliceId),
                onmouseleave: () => globals$1.globals.frontendLocalState.setHighlightedSliceId(-1)
            };
            const data = [
                mithril('td.flow-link', args, outgoing ? 'Outgoing' : 'Incoming'),
                mithril('td.flow-link', args, otherEnd.sliceId.toString()),
                mithril('td.flow-link', args, otherEnd.sliceName)
            ];
            if (haveCategories) {
                data.push(mithril('td.flow-info', flow.category || '-'));
                data.push(mithril('td.flow-info', flow.name || '-'));
            }
            rows.push(mithril('tr', data));
        });
        return mithril('.details-panel', [
            mithril('.details-panel-heading', mithril('h2', `Flow events`)),
            mithril('.flow-events-table', mithril('table.half-width', rows))
        ]);
    }
    renderCanvas(_ctx, _size) { }
}
exports.FlowEventsPanel = FlowEventsPanel;
class FlowEventsAreaSelectedPanel extends panel.Panel {
    view() {
        const selection = globals$1.globals.state.currentSelection;
        if (!selection || selection.kind !== 'AREA') {
            return;
        }
        const columns = [
            mithril('th', 'Flow Category'),
            mithril('th', 'Number of flows'),
            mithril('th', 'Show', mithril('a.warning', mithril('i.material-icons', 'warning'), mithril('.tooltip', 'Showing a large number of flows may impact performance.')))
        ];
        const rows = [mithril('tr', columns)];
        const categoryToFlowsNum = new Map();
        globals$1.globals.selectedFlows.forEach(flow => {
            const categories = getFlowCategories(flow);
            categories.forEach(cat => {
                if (!categoryToFlowsNum.has(cat)) {
                    categoryToFlowsNum.set(cat, 0);
                }
                categoryToFlowsNum.set(cat, categoryToFlowsNum.get(cat) + 1);
            });
        });
        const allWasChecked = globals$1.globals.visibleFlowCategories.get(exports.ALL_CATEGORIES);
        rows.push(mithril('tr.sum', [
            mithril('td.sum-data', 'All'),
            mithril('td.sum-data', globals$1.globals.selectedFlows.length),
            mithril('td.sum-data', mithril('i.material-icons', {
                onclick: () => {
                    if (allWasChecked) {
                        globals$1.globals.visibleFlowCategories.clear();
                    }
                    else {
                        categoryToFlowsNum.forEach((_, cat) => {
                            globals$1.globals.visibleFlowCategories.set(cat, true);
                        });
                    }
                    globals$1.globals.visibleFlowCategories.set(exports.ALL_CATEGORIES, !allWasChecked);
                    globals$1.globals.rafScheduler.scheduleFullRedraw();
                },
            }, allWasChecked ? icons.CHECKBOX : icons.BLANK_CHECKBOX))
        ]));
        categoryToFlowsNum.forEach((num, cat) => {
            const wasChecked = globals$1.globals.visibleFlowCategories.get(cat) ||
                globals$1.globals.visibleFlowCategories.get(exports.ALL_CATEGORIES);
            const data = [
                mithril('td.flow-info', cat),
                mithril('td.flow-info', num),
                mithril('td.flow-info', mithril('i.material-icons', {
                    onclick: () => {
                        if (wasChecked) {
                            globals$1.globals.visibleFlowCategories.set(exports.ALL_CATEGORIES, false);
                        }
                        globals$1.globals.visibleFlowCategories.set(cat, !wasChecked);
                        globals$1.globals.rafScheduler.scheduleFullRedraw();
                    },
                }, wasChecked ? icons.CHECKBOX : icons.BLANK_CHECKBOX))
            ];
            rows.push(mithril('tr', data));
        });
        return mithril('.details-panel', [
            mithril('.details-panel-heading', mithril('h2', `Selected flow events`)),
            mithril('.flow-events-table', mithril('table.half-width', rows)),
        ]);
    }
    renderCanvas(_ctx, _size) { }
}
exports.FlowEventsAreaSelectedPanel = FlowEventsAreaSelectedPanel;

});

var heap_profile_panel = createCommonjsModule(function (module, exports) {
// Copyright (C) 2019 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use size 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.
Object.defineProperty(exports, "__esModule", { value: true });
exports.HeapProfileDetailsPanel = void 0;








const HEADER_HEIGHT = 30;
var ProfileType;
(function (ProfileType) {
    ProfileType["NATIVE_HEAP_PROFILE"] = "native";
    ProfileType["JAVA_HEAP_GRAPH"] = "graph";
})(ProfileType || (ProfileType = {}));
function isProfileType(s) {
    return Object.values(ProfileType).includes(s);
}
function toProfileType(s) {
    if (!isProfileType(s)) {
        throw new Error('Unknown type ${s}');
    }
    return s;
}
function toSelectedCallsite(c) {
    if (c !== undefined && c.name !== undefined) {
        return c.name;
    }
    return '(none)';
}
const RENDER_SELF_AND_TOTAL = {
    selfSize: 'Self',
    totalSize: 'Total',
};
const RENDER_OBJ_COUNT = {
    selfSize: 'Self objects',
    totalSize: 'Subtree objects',
};
class HeapProfileDetailsPanel extends panel.Panel {
    constructor() {
        super(...arguments);
        this.profileType = undefined;
        this.ts = 0;
        this.pid = 0;
        this.flamegraph = new flamegraph.Flamegraph([]);
        this.focusRegex = '';
        this.updateFocusRegexDebounced = rate_limiters.debounce(() => {
            this.updateFocusRegex();
        }, 20);
    }
    view() {
        const heapDumpInfo = globals$1.globals.heapProfileDetails;
        if (heapDumpInfo && heapDumpInfo.type !== undefined &&
            heapDumpInfo.ts !== undefined && heapDumpInfo.tsNs !== undefined &&
            heapDumpInfo.pid !== undefined && heapDumpInfo.upid !== undefined) {
            this.profileType = toProfileType(heapDumpInfo.type);
            this.ts = heapDumpInfo.tsNs;
            this.pid = heapDumpInfo.pid;
            if (heapDumpInfo.flamegraph) {
                this.flamegraph.updateDataIfChanged(this.nodeRendering(), heapDumpInfo.flamegraph);
            }
            const height = heapDumpInfo.flamegraph ?
                this.flamegraph.getHeight() + HEADER_HEIGHT :
                0;
            return mithril('.details-panel', {
                onclick: (e) => {
                    if (this.flamegraph !== undefined) {
                        this.onMouseClick({ y: e.layerY, x: e.layerX });
                    }
                    return false;
                },
                onmousemove: (e) => {
                    if (this.flamegraph !== undefined) {
                        this.onMouseMove({ y: e.layerY, x: e.layerX });
                        globals$1.globals.rafScheduler.scheduleRedraw();
                    }
                },
                onmouseout: () => {
                    if (this.flamegraph !== undefined) {
                        this.onMouseOut();
                    }
                }
            }, mithril('.details-panel-heading.heap-profile', { onclick: (e) => e.stopPropagation() }, [
                mithril('div.options', [
                    mithril('div.title', this.getTitle()),
                    this.getViewingOptionButtons(),
                ]),
                mithril('div.details', [
                    mithril('div.selected', `Selected function: ${toSelectedCallsite(heapDumpInfo.expandedCallsite)}`),
                    mithril('div.time', `Snapshot time: ${time.timeToCode(heapDumpInfo.ts)}`),
                    mithril('input[type=text][placeholder=Focus]', {
                        oninput: (e) => {
                            const target = e.target;
                            this.focusRegex = target.value;
                            this.updateFocusRegexDebounced();
                        },
                        // Required to stop hot-key handling:
                        onkeydown: (e) => e.stopPropagation(),
                    }),
                    this.profileType === ProfileType.NATIVE_HEAP_PROFILE ?
                        mithril('button.download', {
                            onclick: () => {
                                this.downloadPprof();
                            }
                        }, mithril('i.material-icons', 'file_download'), 'Download profile') :
                        null
                ]),
            ]), mithril(`div[style=height:${height}px]`));
        }
        else {
            return mithril('.details-panel', mithril('.details-panel-heading', mithril('h2', `Heap Profile`)));
        }
    }
    getTitle() {
        switch (this.profileType) {
            case ProfileType.NATIVE_HEAP_PROFILE:
                return 'Heap Profile:';
            case ProfileType.JAVA_HEAP_GRAPH:
                return 'Java Heap:';
            default:
                throw new Error('unknown type');
        }
    }
    nodeRendering() {
        if (this.profileType === undefined) {
            return {};
        }
        const viewingOption = globals$1.globals.state.currentHeapProfileFlamegraph.viewingOption;
        switch (this.profileType) {
            case ProfileType.NATIVE_HEAP_PROFILE:
                return RENDER_SELF_AND_TOTAL;
            case ProfileType.JAVA_HEAP_GRAPH:
                if (viewingOption === flamegraph_util.OBJECTS_ALLOCATED_NOT_FREED_KEY) {
                    return RENDER_OBJ_COUNT;
                }
                else {
                    return RENDER_SELF_AND_TOTAL;
                }
            default:
                throw new Error('unknown type');
        }
    }
    updateFocusRegex() {
        globals$1.globals.dispatch(actions.Actions.changeFocusHeapProfileFlamegraph({
            focusRegex: this.focusRegex,
        }));
    }
    getButtonsClass(button) {
        if (globals$1.globals.state.currentHeapProfileFlamegraph === null)
            return '';
        return globals$1.globals.state.currentHeapProfileFlamegraph.viewingOption === button ?
            '.chosen' :
            '';
    }
    getViewingOptionButtons() {
        const viewingOptions = [
            mithril(`button${this.getButtonsClass(flamegraph_util.SPACE_MEMORY_ALLOCATED_NOT_FREED_KEY)}`, {
                onclick: () => {
                    this.changeViewingOption(flamegraph_util.SPACE_MEMORY_ALLOCATED_NOT_FREED_KEY);
                }
            }, 'space'),
            mithril(`button${this.getButtonsClass(flamegraph_util.OBJECTS_ALLOCATED_NOT_FREED_KEY)}`, {
                onclick: () => {
                    this.changeViewingOption(flamegraph_util.OBJECTS_ALLOCATED_NOT_FREED_KEY);
                }
            }, 'objects'),
        ];
        if (this.profileType === ProfileType.NATIVE_HEAP_PROFILE) {
            viewingOptions.push(mithril(`button${this.getButtonsClass(flamegraph_util.ALLOC_SPACE_MEMORY_ALLOCATED_KEY)}`, {
                onclick: () => {
                    this.changeViewingOption(flamegraph_util.ALLOC_SPACE_MEMORY_ALLOCATED_KEY);
                }
            }, 'alloc space'), mithril(`button${this.getButtonsClass(flamegraph_util.OBJECTS_ALLOCATED_KEY)}`, {
                onclick: () => {
                    this.changeViewingOption(flamegraph_util.OBJECTS_ALLOCATED_KEY);
                }
            }, 'alloc objects'));
        }
        return mithril('div', ...viewingOptions);
    }
    changeViewingOption(viewingOption) {
        globals$1.globals.dispatch(actions.Actions.changeViewHeapProfileFlamegraph({ viewingOption }));
    }
    downloadPprof() {
        const engine = Object.values(globals$1.globals.state.engines)[0];
        if (!engine)
            return;
        const src = engine.source;
        globals$1.globals.dispatch(actions.Actions.convertTraceToPprof({ pid: this.pid, ts1: this.ts, src }));
    }
    changeFlamegraphData() {
        const data = globals$1.globals.heapProfileDetails;
        const flamegraphData = data.flamegraph === undefined ? [] : data.flamegraph;
        this.flamegraph.updateDataIfChanged(this.nodeRendering(), flamegraphData, data.expandedCallsite);
    }
    renderCanvas(ctx, size) {
        this.changeFlamegraphData();
        const current = globals$1.globals.state.currentHeapProfileFlamegraph;
        if (current === null)
            return;
        const unit = current.viewingOption === flamegraph_util.SPACE_MEMORY_ALLOCATED_NOT_FREED_KEY ||
            current.viewingOption === flamegraph_util.ALLOC_SPACE_MEMORY_ALLOCATED_KEY ?
            'B' :
            '';
        this.flamegraph.draw(ctx, size.width, size.height, 0, HEADER_HEIGHT, unit);
    }
    onMouseClick({ x, y }) {
        const expandedCallsite = this.flamegraph.onMouseClick({ x, y });
        globals$1.globals.dispatch(actions.Actions.expandHeapProfileFlamegraph({ expandedCallsite }));
        return true;
    }
    onMouseMove({ x, y }) {
        this.flamegraph.onMouseMove({ x, y });
        return true;
    }
    onMouseOut() {
        this.flamegraph.onMouseOut();
    }
}
exports.HeapProfileDetailsPanel = HeapProfileDetailsPanel;

});

var function_profile_panel = createCommonjsModule(function (module, exports) {
// Copyright (C) 2019 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use size 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.
Object.defineProperty(exports, "__esModule", { value: true });
exports.FunctionProfileDetailsPanel = void 0;






const HEADER_HEIGHT = 30;
function toSelectedCallsite(c) {
    if (c !== undefined && c.name !== undefined) {
        return c.name;
    }
    return '(none)';
}
const RENDER_SELF_AND_TOTAL = {
    selfSize: 'Self',
    totalSize: 'Total',
};
class FunctionProfileDetailsPanel extends panel.Panel {
    constructor() {
        super(...arguments);
        this.flamegraph = new flamegraph.Flamegraph([]);
        this.focusRegex = '';
        this.data = {};
        this.updateFocusRegexDebounced = rate_limiters.debounce(() => {
            this.updateFocusRegex();
        }, 20);
    }
    view({ attrs }) {
        //const heapDumpInfo = globals.functionProfileDetails;
        this.data = attrs.data;
        const heapDumpInfo = this.data;
        if (heapDumpInfo) {
            if (heapDumpInfo.flamegraph) {
                this.flamegraph.updateDataIfChanged(this.nodeRendering(), heapDumpInfo.flamegraph);
            }
            const height = heapDumpInfo.flamegraph ?
                this.flamegraph.getHeight() + HEADER_HEIGHT :
                0;
            return mithril('.details-panel', {
                onclick: (e) => {
                    if (this.flamegraph !== undefined) {
                        this.onMouseClick({ y: e.layerY, x: e.layerX });
                        globals$1.globals.rafScheduler.scheduleRedraw();
                    }
                    return false;
                },
                onmousemove: (e) => {
                    if (this.flamegraph !== undefined) {
                        this.onMouseMove({ y: e.layerY, x: e.layerX });
                        globals$1.globals.rafScheduler.scheduleRedraw();
                    }
                },
                onmouseout: () => {
                    if (this.flamegraph !== undefined) {
                        this.onMouseOut();
                    }
                }
            }, mithril('.details-panel-heading.heap-profile', { onclick: (e) => e.stopPropagation() }, [
                mithril('div.details', [
                    mithril('div.selected', `Selected function: ${toSelectedCallsite(heapDumpInfo.expandedCallsite)}`),
                    mithril('input[type=text][placeholder=Focus]', {
                        oninput: (e) => {
                            const target = e.target;
                            this.focusRegex = target.value;
                            this.updateFocusRegexDebounced();
                        },
                        // Required to stop hot-key handling:
                        onkeydown: (e) => e.stopPropagation(),
                    })
                ]),
            ]), mithril(`div[style=height:${height}px]`));
        }
        else {
            return mithril('.details-panel', mithril('.details-panel-heading', mithril('h2', `Function Profile`)));
        }
    }
    nodeRendering() {
        return RENDER_SELF_AND_TOTAL;
    }
    updateFocusRegex() {
        this.changeFlamegraphData();
    }
    changeFlamegraphData() {
        var _a;
        const data = this.data;
        let flamegraphData = data.flamegraph === undefined ? [] : data.flamegraph;
        if (data.expandedCallsite === undefined) {
            flamegraphData = Array.from(this.data.flamegraph || []);
        }
        else {
            flamegraphData = flamegraph_util.expandCallsites(flamegraphData, data.expandedCallsite.id);
        }
        for (let entry of flamegraphData) {
            entry.highlighted = this.focusRegex == '' ? false : (((_a = entry.name) === null || _a === void 0 ? void 0 : _a.toLocaleLowerCase().includes(this.focusRegex.toLocaleLowerCase())) || false);
        }
        this.flamegraph.updateDataIfChanged(this.nodeRendering(), flamegraphData, data.expandedCallsite);
    }
    renderCanvas(ctx, size) {
        const current = globals$1.globals.state.currentFunctionProfileFlamegraph;
        if (current === null)
            return;
        const unit = 's';
        this.flamegraph.draw(ctx, size.width, size.height, 0, HEADER_HEIGHT, unit);
    }
    onMouseClick({ x, y }) {
        const expandedCallsite = this.flamegraph.onMouseClick({ x, y });
        this.data.expandedCallsite = expandedCallsite;
        this.changeFlamegraphData();
        return true;
    }
    onMouseMove({ x, y }) {
        this.flamegraph.onMouseMove({ x, y });
        return true;
    }
    onMouseOut() {
        this.flamegraph.onMouseOut();
    }
}
exports.FunctionProfileDetailsPanel = FunctionProfileDetailsPanel;

});

var logs_panel = createCommonjsModule(function (module, exports) {
// Copyright (C) 2019 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.
Object.defineProperty(exports, "__esModule", { value: true });
exports.LogPanel = void 0;





const time_2 = time;


const ROW_H = 20;
const PRIO_TO_LETTER = ['-', '-', 'V', 'D', 'I', 'W', 'E', 'F'];
class LogPanel extends panel.Panel {
    constructor() {
        super(...arguments);
        this.visibleRowOffset = 0;
        this.visibleRowCount = 0;
    }
    recomputeVisibleRowsAndUpdate() {
        const scrollContainer = logging.assertExists(this.scrollContainer);
        const prevOffset = this.visibleRowOffset;
        const prevCount = this.visibleRowCount;
        this.visibleRowOffset = Math.floor(scrollContainer.scrollTop / ROW_H);
        this.visibleRowCount = Math.ceil(scrollContainer.clientHeight / ROW_H);
        if (this.visibleRowOffset !== prevOffset ||
            this.visibleRowCount !== prevCount) {
            globals$1.globals.dispatch(actions.Actions.updateLogsPagination({
                offset: this.visibleRowOffset,
                count: this.visibleRowCount,
            }));
        }
    }
    oncreate({ dom }) {
        this.scrollContainer = logging.assertExists(dom.parentElement.parentElement.parentElement);
        this.scrollContainer.addEventListener('scroll', this.onScroll.bind(this), { passive: true });
        this.bounds = globals$1.globals.trackDataStore.get(logs.LogBoundsKey);
        this.entries = globals$1.globals.trackDataStore.get(logs.LogEntriesKey);
        this.recomputeVisibleRowsAndUpdate();
    }
    onupdate(_) {
        this.bounds = globals$1.globals.trackDataStore.get(logs.LogBoundsKey);
        this.entries = globals$1.globals.trackDataStore.get(logs.LogEntriesKey);
        this.recomputeVisibleRowsAndUpdate();
    }
    onScroll() {
        if (this.scrollContainer === undefined)
            return;
        this.recomputeVisibleRowsAndUpdate();
        globals$1.globals.rafScheduler.scheduleFullRedraw();
    }
    onRowOver(ts) {
        globals$1.globals.frontendLocalState.setHoveredLogsTimestamp(ts);
    }
    onRowOut() {
        globals$1.globals.frontendLocalState.setHoveredLogsTimestamp(-1);
    }
    totalRows() {
        if (!this.bounds) {
            return { isStale: false, total: 0, offset: 0, count: 0 };
        }
        const { total, startTs, endTs, firstRowTs, lastRowTs } = this.bounds;
        const vis = globals$1.globals.frontendLocalState.visibleWindowTime;
        const leftSpan = new time_2.TimeSpan(startTs, firstRowTs);
        const rightSpan = new time_2.TimeSpan(lastRowTs, endTs);
        const isStaleLeft = !leftSpan.isInBounds(vis.start);
        const isStaleRight = !rightSpan.isInBounds(vis.end);
        const isStale = isStaleLeft || isStaleRight;
        const offset = Math.min(this.visibleRowOffset, total);
        const visCount = Math.min(total, this.visibleRowCount);
        return { isStale, total, count: visCount, offset };
    }
    view(_) {
        const { isStale, total, offset, count } = this.totalRows();
        const rows = [];
        if (this.entries) {
            const offset = this.entries.offset;
            const timestamps = this.entries.timestamps;
            const priorities = this.entries.priorities;
            const tags = this.entries.tags;
            const messages = this.entries.messages;
            for (let i = 0; i < this.entries.timestamps.length; i++) {
                const priorityLetter = PRIO_TO_LETTER[priorities[i]];
                const ts = timestamps[i];
                const prioClass = priorityLetter || '';
                rows.push(mithril(`.row.${prioClass}`, {
                    'class': isStale ? 'stale' : '',
                    style: { top: `${(offset + i) * ROW_H}px` },
                    onmouseover: this.onRowOver.bind(this, ts / 1e9),
                    onmouseout: this.onRowOut.bind(this),
                }, mithril('.cell', time.formatTimestamp(ts / 1e9 - globals$1.globals.state.traceTime.startSec)), mithril('.cell', priorityLetter || '?'), mithril('.cell', tags[i]), mithril('.cell', messages[i]), mithril('br')));
            }
        }
        return mithril('.log-panel', mithril('header', {
            'class': isStale ? 'stale' : '',
        }, `Logs rows [${offset}, ${offset + count}] / ${total}`), mithril('.rows', { style: { height: `${total * ROW_H}px` } }, rows));
    }
    renderCanvas() { }
}
exports.LogPanel = LogPanel;

});

var notes_panel = createCommonjsModule(function (module, exports) {
// Copyright (C) 2019 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use size 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.
Object.defineProperty(exports, "__esModule", { value: true });
exports.NotesEditorPanel = exports.NotesPanel = void 0;








const FLAG_WIDTH = 16;
const AREA_TRIANGLE_WIDTH = 10;
const MOVIE_WIDTH = 16;
const FLAG = `\uE153`;
const MOVIE = '\uE8DA';
function toSummary(s) {
    const newlineIndex = s.indexOf('\n') > 0 ? s.indexOf('\n') : s.length;
    return s.slice(0, Math.min(newlineIndex, s.length, 16));
}
function getStartTimestamp(note) {
    if (note.noteType === 'AREA') {
        return globals$1.globals.state.areas[note.areaId].startSec;
    }
    else {
        return note.timestamp;
    }
}
class NotesPanel extends panel.Panel {
    constructor() {
        super(...arguments);
        this.hoveredX = null;
    }
    oncreate({ dom }) {
        dom.addEventListener('mousemove', (e) => {
            this.hoveredX = e.layerX - css_constants.TRACK_SHELL_WIDTH;
            if (globals$1.globals.state.scrubbingEnabled) {
                const timescale = globals$1.globals.frontendLocalState.timeScale;
                const timestamp = timescale.pxToTime(this.hoveredX);
                globals$1.globals.frontendLocalState.setVidTimestamp(timestamp);
            }
            globals$1.globals.rafScheduler.scheduleRedraw();
        }, { passive: true });
        dom.addEventListener('mouseenter', (e) => {
            this.hoveredX = e.layerX - css_constants.TRACK_SHELL_WIDTH;
            globals$1.globals.rafScheduler.scheduleRedraw();
        });
        dom.addEventListener('mouseout', () => {
            this.hoveredX = null;
            globals$1.globals.frontendLocalState.setHoveredNoteTimestamp(-1);
            globals$1.globals.rafScheduler.scheduleRedraw();
        }, { passive: true });
    }
    view() {
        return mithril('.notes-panel', {
            onclick: (e) => {
                const isMovie = globals$1.globals.state.flagPauseEnabled;
                this.onClick(e.layerX - css_constants.TRACK_SHELL_WIDTH, e.layerY, isMovie);
                e.stopPropagation();
            },
        });
    }
    renderCanvas(ctx, size) {
        const timeScale = globals$1.globals.frontendLocalState.timeScale;
        const range = globals$1.globals.frontendLocalState.visibleWindowTime;
        let aNoteIsHovered = false;
        ctx.fillStyle = '#999';
        ctx.fillRect(css_constants.TRACK_SHELL_WIDTH - 2, 0, 2, size.height);
        for (const xAndTime of gridline_helper.gridlines(size.width, range, timeScale)) {
            ctx.fillRect(xAndTime[0], 0, 1, size.height);
        }
        ctx.textBaseline = 'bottom';
        ctx.font = '10px Helvetica';
        for (const note of Object.values(globals$1.globals.state.notes)) {
            const timestamp = getStartTimestamp(note);
            // TODO(hjd): We should still render area selection marks in viewport is
            // *within* the area (e.g. both lhs and rhs are out of bounds).
            if ((note.noteType !== 'AREA' && !timeScale.timeInBounds(timestamp)) ||
                (note.noteType === 'AREA' &&
                    !timeScale.timeInBounds(globals$1.globals.state.areas[note.areaId].endSec) &&
                    !timeScale.timeInBounds(globals$1.globals.state.areas[note.areaId].startSec))) {
                continue;
            }
            const currentIsHovered = this.hoveredX && this.mouseOverNote(this.hoveredX, note);
            if (currentIsHovered)
                aNoteIsHovered = true;
            const selection = globals$1.globals.state.currentSelection;
            const isSelected = selection !== null &&
                ((selection.kind === 'NOTE' && selection.id === note.id) ||
                    (selection.kind === 'AREA' && selection.noteId === note.id));
            const x = timeScale.timeToPx(timestamp);
            const left = Math.floor(x + css_constants.TRACK_SHELL_WIDTH);
            // Draw flag or marker.
            if (note.noteType === 'AREA') {
                const area = globals$1.globals.state.areas[note.areaId];
                this.drawAreaMarker(ctx, left, Math.floor(timeScale.timeToPx(area.endSec) + css_constants.TRACK_SHELL_WIDTH), note.color, isSelected);
            }
            else {
                this.drawFlag(ctx, left, size.height, note.color, note.noteType, isSelected);
            }
            if (note.text) {
                const summary = toSummary(note.text);
                const measured = ctx.measureText(summary);
                // Add a white semi-transparent background for the text.
                ctx.fillStyle = 'rgba(255, 255, 255, 0.8)';
                ctx.fillRect(left + FLAG_WIDTH + 2, size.height + 2, measured.width + 2, -12);
                ctx.fillStyle = '#3c4b5d';
                ctx.fillText(summary, left + FLAG_WIDTH + 3, size.height + 1);
            }
        }
        // A real note is hovered so we don't need to see the preview line.
        // TODO(hjd): Change cursor to pointer here.
        if (aNoteIsHovered)
            globals$1.globals.frontendLocalState.setHoveredNoteTimestamp(-1);
        // View preview note flag when hovering on notes panel.
        if (!aNoteIsHovered && this.hoveredX !== null) {
            const timestamp = timeScale.pxToTime(this.hoveredX);
            if (timeScale.timeInBounds(timestamp)) {
                globals$1.globals.frontendLocalState.setHoveredNoteTimestamp(timestamp);
                const x = timeScale.timeToPx(timestamp);
                const left = Math.floor(x + css_constants.TRACK_SHELL_WIDTH);
                this.drawFlag(ctx, left, size.height, '#aaa', 'DEFAULT', /* fill */ true);
            }
        }
    }
    drawAreaMarker(ctx, x, xEnd, color, fill) {
        ctx.fillStyle = color;
        ctx.strokeStyle = color;
        const topOffset = 10;
        // Don't draw in the track shell section.
        if (x >= globals$1.globals.frontendLocalState.timeScale.startPx + css_constants.TRACK_SHELL_WIDTH) {
            // Draw left triangle.
            ctx.beginPath();
            ctx.moveTo(x, topOffset);
            ctx.lineTo(x, topOffset + AREA_TRIANGLE_WIDTH);
            ctx.lineTo(x + AREA_TRIANGLE_WIDTH, topOffset);
            ctx.lineTo(x, topOffset);
            if (fill)
                ctx.fill();
            ctx.stroke();
        }
        // Draw right triangle.
        ctx.beginPath();
        ctx.moveTo(xEnd, topOffset);
        ctx.lineTo(xEnd, topOffset + AREA_TRIANGLE_WIDTH);
        ctx.lineTo(xEnd - AREA_TRIANGLE_WIDTH, topOffset);
        ctx.lineTo(xEnd, topOffset);
        if (fill)
            ctx.fill();
        ctx.stroke();
        // Start line after track shell section, join triangles.
        const startDraw = Math.max(x, globals$1.globals.frontendLocalState.timeScale.startPx + css_constants.TRACK_SHELL_WIDTH);
        ctx.beginPath();
        ctx.moveTo(startDraw, topOffset);
        ctx.lineTo(xEnd, topOffset);
        ctx.stroke();
    }
    drawFlag(ctx, x, height, color, noteType, fill) {
        const prevFont = ctx.font;
        const prevBaseline = ctx.textBaseline;
        ctx.textBaseline = 'alphabetic';
        // Adjust height for icon font.
        ctx.font = '24px Material Icons';
        ctx.fillStyle = color;
        ctx.strokeStyle = color;
        // The ligatures have padding included that means the icon is not drawn
        // exactly at the x value. This adjusts for that.
        const iconPadding = 6;
        if (fill) {
            ctx.fillText(noteType === 'MOVIE' ? MOVIE : FLAG, x - iconPadding, height + 2);
        }
        else {
            ctx.strokeText(noteType === 'MOVIE' ? MOVIE : FLAG, x - iconPadding, height + 2.5);
        }
        ctx.font = prevFont;
        ctx.textBaseline = prevBaseline;
    }
    onClick(x, _, isMovie) {
        if (x < 0)
            return;
        const timeScale = globals$1.globals.frontendLocalState.timeScale;
        const timestamp = timeScale.pxToTime(x);
        for (const note of Object.values(globals$1.globals.state.notes)) {
            if (this.hoveredX && this.mouseOverNote(this.hoveredX, note)) {
                if (note.noteType === 'MOVIE') {
                    globals$1.globals.frontendLocalState.setVidTimestamp(note.timestamp);
                }
                if (note.noteType === 'AREA') {
                    globals$1.globals.makeSelection(actions.Actions.reSelectArea({ areaId: note.areaId, noteId: note.id }));
                }
                else {
                    globals$1.globals.makeSelection(actions.Actions.selectNote({ id: note.id }));
                }
                return;
            }
        }
        if (isMovie) {
            globals$1.globals.frontendLocalState.setVidTimestamp(timestamp);
        }
        const color = colorizer.randomColor();
        globals$1.globals.makeSelection(actions.Actions.addNote({ timestamp, color, isMovie }));
    }
    mouseOverNote(x, note) {
        const timeScale = globals$1.globals.frontendLocalState.timeScale;
        const noteX = timeScale.timeToPx(getStartTimestamp(note));
        if (note.noteType === 'AREA') {
            const noteArea = globals$1.globals.state.areas[note.areaId];
            return (noteX <= x && x < noteX + AREA_TRIANGLE_WIDTH) ||
                (timeScale.timeToPx(noteArea.endSec) > x &&
                    x > timeScale.timeToPx(noteArea.endSec) - AREA_TRIANGLE_WIDTH);
        }
        else {
            const width = (note.noteType === 'MOVIE') ? MOVIE_WIDTH : FLAG_WIDTH;
            return noteX <= x && x < noteX + width;
        }
    }
}
exports.NotesPanel = NotesPanel;
class NotesEditorPanel extends panel.Panel {
    view({ attrs }) {
        const note = globals$1.globals.state.notes[attrs.id];
        const startTime = getStartTimestamp(note) - globals$1.globals.state.traceTime.startSec;
        return mithril('.notes-editor-panel', mithril('.notes-editor-panel-heading-bar', mithril('.notes-editor-panel-heading', `Annotation at ${time.timeToString(startTime)}`), mithril('input[type=text]', {
            onkeydown: (e) => {
                e.stopImmediatePropagation();
            },
            value: note.text,
            onchange: (e) => {
                const newText = e.target.value;
                globals$1.globals.dispatch(actions.Actions.changeNoteText({
                    id: attrs.id,
                    newText,
                }));
            },
        }), mithril('span.color-change', `Change color: `, mithril('input[type=color]', {
            value: note.color,
            onchange: (e) => {
                const newColor = e.target.value;
                globals$1.globals.dispatch(actions.Actions.changeNoteColor({
                    id: attrs.id,
                    newColor,
                }));
            },
        })), mithril('button', {
            onclick: () => {
                globals$1.globals.dispatch(actions.Actions.removeNote({ id: attrs.id }));
                globals$1.globals.frontendLocalState.currentTab = undefined;
                globals$1.globals.rafScheduler.scheduleFullRedraw();
            }
        }, 'Remove')));
    }
    renderCanvas(_ctx, _size) { }
}
exports.NotesEditorPanel = NotesEditorPanel;

});

var track_group_panel = createCommonjsModule(function (module, exports) {
// 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.
Object.defineProperty(exports, "__esModule", { value: true });
exports.TrackGroupPanel = void 0;












class TrackGroupPanel extends panel.Panel {
    constructor({ attrs }) {
        super();
        this.shellWidth = 0;
        this.backgroundColor = '#ffffff'; // Updated from CSS later.
        this.trackGroupId = attrs.trackGroupId;
        const trackCreator = track_registry.trackRegistry.get(this.summaryTrackState.kind);
        this.summaryTrack = trackCreator.create(this.summaryTrackState);
    }
    get trackGroupState() {
        return logging.assertExists(globals$1.globals.state.trackGroups[this.trackGroupId]);
    }
    get summaryTrackState() {
        return logging.assertExists(globals$1.globals.state.tracks[this.trackGroupState.tracks[0]]);
    }
    view({ attrs }) {
        const collapsed = this.trackGroupState.collapsed;
        let name = this.trackGroupState.name;
        if (name[0] === '/') {
            name = StripPathFromExecutable(name);
        }
        // The shell should be highlighted if the current search result is inside
        // this track group.
        let highlightClass = '';
        const searchIndex = globals$1.globals.frontendLocalState.searchIndex;
        if (searchIndex !== -1) {
            const trackId = globals$1.globals.currentSearchResults
                .trackIds[globals$1.globals.frontendLocalState.searchIndex];
            const parentTrackId = state.getContainingTrackId(globals$1.globals.state, trackId);
            if (parentTrackId === attrs.trackGroupId) {
                highlightClass = 'flash';
            }
        }
        const selection = globals$1.globals.state.currentSelection;
        const trackGroup = globals$1.globals.state.trackGroups[attrs.trackGroupId];
        let checkBox = icons.BLANK_CHECKBOX;
        if (selection !== null && selection.kind === 'AREA') {
            const selectedArea = globals$1.globals.state.areas[selection.areaId];
            if (selectedArea.tracks.includes(attrs.trackGroupId) &&
                trackGroup.tracks.every(id => selectedArea.tracks.includes(id))) {
                checkBox = icons.CHECKBOX;
            }
            else if (selectedArea.tracks.includes(attrs.trackGroupId) ||
                trackGroup.tracks.some(id => selectedArea.tracks.includes(id))) {
                checkBox = icons.INDETERMINATE_CHECKBOX;
            }
        }
        return mithril(`.track-group-panel[collapsed=${collapsed}]`, { id: 'track_' + this.trackGroupId }, mithril(`.shell`, {
            onclick: (e) => {
                globals$1.globals.dispatch(actions.Actions.toggleTrackGroupCollapsed({
                    trackGroupId: attrs.trackGroupId,
                })),
                    e.stopPropagation();
            },
            class: `${highlightClass}`,
        }, mithril('.fold-button', mithril('i.material-icons', this.trackGroupState.collapsed ? icons.EXPAND_DOWN : icons.EXPAND_UP)), mithril('h1', {
            title: name,
        }, name), selection && selection.kind === 'AREA' ?
            mithril('i.material-icons.track-button', {
                onclick: (e) => {
                    globals$1.globals.dispatch(actions.Actions.toggleTrackSelection({ id: attrs.trackGroupId, isTrackGroup: true }));
                    e.stopPropagation();
                }
            }, checkBox) :
            ''), this.summaryTrack ? mithril(track_panel.TrackContent, { track: this.summaryTrack }) : null);
    }
    oncreate(vnode) {
        this.onupdate(vnode);
    }
    onupdate({ dom }) {
        const shell = logging.assertExists(dom.querySelector('.shell'));
        this.shellWidth = shell.getBoundingClientRect().width;
        // TODO(andrewbb): move this to css_constants
        if (this.trackGroupState.collapsed) {
            this.backgroundColor =
                getComputedStyle(dom).getPropertyValue('--collapsed-background');
        }
        else {
            this.backgroundColor =
                getComputedStyle(dom).getPropertyValue('--expanded-background');
        }
    }
    highlightIfTrackSelected(ctx, size) {
        const localState = globals$1.globals.frontendLocalState;
        const selection = globals$1.globals.state.currentSelection;
        if (!selection || selection.kind !== 'AREA')
            return;
        const selectedArea = globals$1.globals.state.areas[selection.areaId];
        if (selectedArea.tracks.includes(this.trackGroupId)) {
            ctx.fillStyle = 'rgba(131, 152, 230, 0.3)';
            ctx.fillRect(localState.timeScale.timeToPx(selectedArea.startSec) +
                this.shellWidth, 0, localState.timeScale.deltaTimeToPx(selectedArea.endSec - selectedArea.startSec), size.height);
        }
    }
    renderCanvas(ctx, size) {
        const collapsed = this.trackGroupState.collapsed;
        ctx.fillStyle = this.backgroundColor;
        ctx.fillRect(0, 0, size.width, size.height);
        if (!collapsed)
            return;
        this.highlightIfTrackSelected(ctx, size);
        gridline_helper.drawGridLines(ctx, globals$1.globals.frontendLocalState.timeScale, globals$1.globals.frontendLocalState.visibleWindowTime, size.width, size.height);
        ctx.save();
        ctx.translate(this.shellWidth, 0);
        if (this.summaryTrack) {
            this.summaryTrack.render(ctx);
        }
        ctx.restore();
        this.highlightIfTrackSelected(ctx, size);
        const localState = globals$1.globals.frontendLocalState;
        // Draw vertical line when hovering on the notes panel.
        if (localState.hoveredNoteTimestamp !== -1) {
            vertical_line_helper.drawVerticalLineAtTime(ctx, localState.timeScale, localState.hoveredNoteTimestamp, size.height, `#aaa`);
        }
        if (localState.hoveredLogsTimestamp !== -1) {
            vertical_line_helper.drawVerticalLineAtTime(ctx, localState.timeScale, localState.hoveredLogsTimestamp, size.height, `#344596`);
        }
        if (globals$1.globals.state.currentSelection !== null) {
            if (globals$1.globals.state.currentSelection.kind === 'NOTE') {
                const note = globals$1.globals.state.notes[globals$1.globals.state.currentSelection.id];
                if (note.noteType === 'DEFAULT') {
                    vertical_line_helper.drawVerticalLineAtTime(ctx, localState.timeScale, note.timestamp, size.height, note.color);
                }
            }
            if (globals$1.globals.state.currentSelection.kind === 'SLICE' &&
                globals$1.globals.sliceDetails.wakeupTs !== undefined) {
                vertical_line_helper.drawVerticalLineAtTime(ctx, localState.timeScale, globals$1.globals.sliceDetails.wakeupTs, size.height, `black`);
            }
        }
        // All marked areas should have semi-transparent vertical lines
        // marking the start and end.
        for (const note of Object.values(globals$1.globals.state.notes)) {
            if (note.noteType === 'AREA') {
                const transparentNoteColor = 'rgba(' + colorConvert.hex.rgb(note.color.substr(1)).toString() + ', 0.65)';
                vertical_line_helper.drawVerticalLineAtTime(ctx, localState.timeScale, globals$1.globals.state.areas[note.areaId].startSec, size.height, transparentNoteColor, 1);
                vertical_line_helper.drawVerticalLineAtTime(ctx, localState.timeScale, globals$1.globals.state.areas[note.areaId].endSec, size.height, transparentNoteColor, 1);
            }
        }
    }
}
exports.TrackGroupPanel = TrackGroupPanel;
function StripPathFromExecutable(path) {
    return path.split('/').slice(-1)[0];
}

});

var flow_events_renderer = createCommonjsModule(function (module, exports) {
// Copyright (C) 2020 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use size 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.
Object.defineProperty(exports, "__esModule", { value: true });
exports.FlowEventsRenderer = exports.FlowEventsRendererArgs = void 0;






const TRACK_GROUP_CONNECTION_OFFSET = 5;
const TRIANGLE_SIZE = 5;
const CIRCLE_RADIUS = 3;
const BEZIER_OFFSET = 30;
const CONNECTED_FLOW_HUE = 10;
const SELECTED_FLOW_HUE = 230;
const DEFAULT_FLOW_WIDTH = 2;
const FOCUSED_FLOW_WIDTH = 3;
const HIGHLIGHTED_FLOW_INTENSITY = 45;
const FOCUSED_FLOW_INTENSITY = 55;
const DEFAULT_FLOW_INTENSITY = 70;
function hasTrackId(obj) {
    return obj.trackId !== undefined;
}
function hasManyTrackIds(obj) {
    return obj.trackIds !== undefined;
}
function hasId(obj) {
    return obj.id !== undefined;
}
function hasTrackGroupId(obj) {
    return obj.trackGroupId !== undefined;
}
class FlowEventsRendererArgs {
    constructor(canvasWidth, canvasHeight) {
        this.canvasWidth = canvasWidth;
        this.canvasHeight = canvasHeight;
        this.trackIdToTrackPanel = new Map();
        this.groupIdToTrackGroupPanel = new Map();
    }
    registerPanel(panel, yStart, height) {
        if (panel.state instanceof track_panel.TrackPanel && hasId(panel.attrs)) {
            const config = globals$1.globals.state.tracks[panel.attrs.id].config;
            if (hasTrackId(config)) {
                this.trackIdToTrackPanel.set(config.trackId, { panel: panel.state, yStart });
            }
            if (hasManyTrackIds(config)) {
                for (const trackId of config.trackIds) {
                    this.trackIdToTrackPanel.set(trackId, { panel: panel.state, yStart });
                }
            }
        }
        else if (panel.state instanceof track_group_panel.TrackGroupPanel &&
            hasTrackGroupId(panel.attrs)) {
            this.groupIdToTrackGroupPanel.set(panel.attrs.trackGroupId, { panel: panel.state, yStart, height });
        }
    }
}
exports.FlowEventsRendererArgs = FlowEventsRendererArgs;
class FlowEventsRenderer {
    getTrackGroupIdByTrackId(trackId) {
        const uiTrackId = scroll_helper.findUiTrackId(trackId);
        return uiTrackId ? globals$1.globals.state.tracks[uiTrackId].trackGroup : undefined;
    }
    getTrackGroupYCoordinate(args, trackId) {
        const trackGroupId = this.getTrackGroupIdByTrackId(trackId);
        if (!trackGroupId) {
            return undefined;
        }
        const trackGroupInfo = args.groupIdToTrackGroupPanel.get(trackGroupId);
        if (!trackGroupInfo) {
            return undefined;
        }
        return trackGroupInfo.yStart + trackGroupInfo.height -
            TRACK_GROUP_CONNECTION_OFFSET;
    }
    getTrackYCoordinate(args, trackId) {
        var _a;
        return (_a = args.trackIdToTrackPanel.get(trackId)) === null || _a === void 0 ? void 0 : _a.yStart;
    }
    getYConnection(args, trackId, rect) {
        if (!rect) {
            const y = this.getTrackGroupYCoordinate(args, trackId);
            if (y === undefined) {
                return undefined;
            }
            return { y, connection: 'TRACK_GROUP' };
        }
        const y = (this.getTrackYCoordinate(args, trackId) || 0) + rect.top +
            rect.height * 0.5;
        return {
            y: Math.min(Math.max(0, y), args.canvasHeight),
            connection: 'TRACK'
        };
    }
    getXCoordinate(ts) {
        return globals$1.globals.frontendLocalState.timeScale.timeToPx(ts);
    }
    getSliceRect(args, point) {
        var _a;
        const trackPanel = (_a = args.trackIdToTrackPanel.get(point.trackId)) === null || _a === void 0 ? void 0 : _a.panel;
        if (!trackPanel) {
            return undefined;
        }
        return trackPanel.getSliceRect(point.sliceStartTs, point.sliceEndTs, point.depth);
    }
    render(ctx, args) {
        ctx.save();
        ctx.translate(css_constants.TRACK_SHELL_WIDTH, 0);
        ctx.rect(0, 0, args.canvasWidth - css_constants.TRACK_SHELL_WIDTH, args.canvasHeight);
        ctx.clip();
        globals$1.globals.connectedFlows.forEach(flow => {
            this.drawFlow(ctx, args, flow, CONNECTED_FLOW_HUE);
        });
        globals$1.globals.selectedFlows.forEach(flow => {
            const categories = flow_events_panel.getFlowCategories(flow);
            for (const cat of categories) {
                if (globals$1.globals.visibleFlowCategories.get(cat) ||
                    globals$1.globals.visibleFlowCategories.get(flow_events_panel.ALL_CATEGORIES)) {
                    this.drawFlow(ctx, args, flow, SELECTED_FLOW_HUE);
                    break;
                }
            }
        });
        ctx.restore();
    }
    drawFlow(ctx, args, flow, hue) {
        const beginSliceRect = this.getSliceRect(args, flow.begin);
        const endSliceRect = this.getSliceRect(args, flow.end);
        const beginYConnection = this.getYConnection(args, flow.begin.trackId, beginSliceRect);
        const endYConnection = this.getYConnection(args, flow.end.trackId, endSliceRect);
        if (!beginYConnection || !endYConnection) {
            return;
        }
        let beginDir = 'LEFT';
        let endDir = 'RIGHT';
        if (beginYConnection.connection === 'TRACK_GROUP') {
            beginDir = beginYConnection.y > endYConnection.y ? 'DOWN' : 'UP';
        }
        if (endYConnection.connection === 'TRACK_GROUP') {
            endDir = endYConnection.y > beginYConnection.y ? 'DOWN' : 'UP';
        }
        const begin = {
            x: this.getXCoordinate(flow.begin.sliceEndTs),
            y: beginYConnection.y,
            dir: beginDir
        };
        const end = {
            x: this.getXCoordinate(flow.end.sliceStartTs),
            y: endYConnection.y,
            dir: endDir
        };
        const highlighted = flow.end.sliceId === globals$1.globals.frontendLocalState.highlightedSliceId ||
            flow.begin.sliceId === globals$1.globals.frontendLocalState.highlightedSliceId;
        const focused = flow.id === globals$1.globals.frontendLocalState.focusedFlowIdLeft ||
            flow.id === globals$1.globals.frontendLocalState.focusedFlowIdRight;
        let intensity = DEFAULT_FLOW_INTENSITY;
        let width = DEFAULT_FLOW_WIDTH;
        if (focused) {
            intensity = FOCUSED_FLOW_INTENSITY;
            width = FOCUSED_FLOW_WIDTH;
        }
        if (highlighted) {
            intensity = HIGHLIGHTED_FLOW_INTENSITY;
        }
        this.drawFlowArrow(ctx, begin, end, hue, intensity, width);
    }
    getDeltaX(dir, offset) {
        switch (dir) {
            case 'LEFT':
                return -offset;
            case 'RIGHT':
                return offset;
            case 'UP':
                return 0;
            case 'DOWN':
                return 0;
            default:
                return 0;
        }
    }
    getDeltaY(dir, offset) {
        switch (dir) {
            case 'LEFT':
                return 0;
            case 'RIGHT':
                return 0;
            case 'UP':
                return -offset;
            case 'DOWN':
                return offset;
            default:
                return 0;
        }
    }
    drawFlowArrow(ctx, begin, end, hue, intensity, width) {
        const END_OFFSET = (end.dir === 'RIGHT' || end.dir === 'LEFT' ? TRIANGLE_SIZE : 0);
        const color = `hsl(${hue}, 50%, ${intensity}%)`;
        // draw curved line from begin to end (bezier curve)
        ctx.strokeStyle = color;
        ctx.lineWidth = width;
        ctx.beginPath();
        ctx.moveTo(begin.x, begin.y);
        ctx.bezierCurveTo(begin.x - this.getDeltaX(begin.dir, BEZIER_OFFSET), begin.y - this.getDeltaY(begin.dir, BEZIER_OFFSET), end.x - this.getDeltaX(end.dir, BEZIER_OFFSET + END_OFFSET), end.y - this.getDeltaY(end.dir, BEZIER_OFFSET + END_OFFSET), end.x - this.getDeltaX(end.dir, END_OFFSET), end.y - this.getDeltaY(end.dir, END_OFFSET));
        ctx.stroke();
        // TODO (andrewbb): probably we should add a parameter 'MarkerType' to be
        // able to choose what marker we want to draw _before_ the function call.
        // e.g. triangle, circle, square?
        if (begin.dir !== 'RIGHT' && begin.dir !== 'LEFT') {
            // draw a circle if we the line has a vertical connection
            ctx.fillStyle = color;
            ctx.beginPath();
            ctx.arc(begin.x, begin.y, 3, 0, 2 * Math.PI);
            ctx.closePath();
            ctx.fill();
        }
        if (end.dir !== 'RIGHT' && end.dir !== 'LEFT') {
            // draw a circle if we the line has a vertical connection
            ctx.fillStyle = color;
            ctx.beginPath();
            ctx.arc(end.x, end.y, CIRCLE_RADIUS, 0, 2 * Math.PI);
            ctx.closePath();
            ctx.fill();
        }
        else {
            const dx = this.getDeltaX(end.dir, TRIANGLE_SIZE);
            const dy = this.getDeltaY(end.dir, TRIANGLE_SIZE);
            // draw small triangle
            ctx.fillStyle = color;
            ctx.beginPath();
            ctx.moveTo(end.x, end.y);
            ctx.lineTo(end.x - dx - dy, end.y + dx - dy);
            ctx.lineTo(end.x - dx + dy, end.y - dx - dy);
            ctx.closePath();
            ctx.fill();
        }
    }
}
exports.FlowEventsRenderer = FlowEventsRenderer;

});

var panel_container = createCommonjsModule(function (module, exports) {
// 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.
Object.defineProperty(exports, "__esModule", { value: true });
exports.PanelContainer = void 0;







/**
 * If the panel container scrolls, the backing canvas height is
 * SCROLLING_CANVAS_OVERDRAW_FACTOR * parent container height.
 */
const SCROLLING_CANVAS_OVERDRAW_FACTOR = 1.2;
class PanelContainer {
    constructor(vnode) {
        // These values are updated with proper values in oncreate.
        this.parentWidth = 0;
        this.parentHeight = 0;
        this.scrollTop = 0;
        this.panelPositions = [];
        this.totalPanelHeight = 0;
        this.canvasHeight = 0;
        this.panelPerfStats = new WeakMap();
        this.perfStats = {
            totalPanels: 0,
            panelsOnCanvas: 0,
            renderStats: new perf.RunningStatistics(10),
        };
        this.onResize = () => { };
        this.parentOnScroll = () => { };
        this.attrs = vnode.attrs;
        this.canvasRedrawer = () => this.redrawCanvas();
        globals$1.globals.rafScheduler.addRedrawCallback(this.canvasRedrawer);
        perf.perfDisplay.addContainer(this);
        this.flowEventsRenderer = new flow_events_renderer.FlowEventsRenderer();
    }
    get canvasOverdrawFactor() {
        return this.attrs.doesScroll ? SCROLLING_CANVAS_OVERDRAW_FACTOR : 1;
    }
    getPanelsInRegion(startX, endX, startY, endY) {
        const minX = Math.min(startX, endX);
        const maxX = Math.max(startX, endX);
        const minY = Math.min(startY, endY);
        const maxY = Math.max(startY, endY);
        const panels = [];
        for (let i = 0; i < this.panelPositions.length; i++) {
            const pos = this.panelPositions[i];
            const realPosX = pos.x - css_constants.TRACK_SHELL_WIDTH;
            if (realPosX + pos.width >= minX && realPosX <= maxX &&
                pos.y + pos.height >= minY && pos.y <= maxY &&
                this.attrs.panels[i].attrs.selectable) {
                panels.push(this.attrs.panels[i]);
            }
        }
        return panels;
    }
    // This finds the tracks covered by the in-progress area selection. When
    // editing areaY is not set, so this will not be used.
    handleAreaSelection() {
        const area = globals$1.globals.frontendLocalState.selectedArea;
        if (area === undefined ||
            globals$1.globals.frontendLocalState.areaY.start === undefined ||
            globals$1.globals.frontendLocalState.areaY.end === undefined ||
            this.panelPositions.length === 0) {
            return;
        }
        // Only get panels from the current panel container if the selection began
        // in this container.
        const panelContainerTop = this.panelPositions[0].y;
        const panelContainerBottom = this.panelPositions[this.panelPositions.length - 1].y +
            this.panelPositions[this.panelPositions.length - 1].height;
        if (globals$1.globals.frontendLocalState.areaY.start + css_constants.TOPBAR_HEIGHT <
            panelContainerTop ||
            globals$1.globals.frontendLocalState.areaY.start + css_constants.TOPBAR_HEIGHT >
                panelContainerBottom) {
            return;
        }
        // The Y value is given from the top of the pan and zoom region, we want it
        // from the top of the panel container. The parent offset corrects that.
        const panels = this.getPanelsInRegion(globals$1.globals.frontendLocalState.timeScale.timeToPx(area.startSec), globals$1.globals.frontendLocalState.timeScale.timeToPx(area.endSec), globals$1.globals.frontendLocalState.areaY.start + css_constants.TOPBAR_HEIGHT, globals$1.globals.frontendLocalState.areaY.end + css_constants.TOPBAR_HEIGHT);
        // Get the track ids from the panels.
        const tracks = [];
        for (const panel of panels) {
            if (panel.attrs.id !== undefined) {
                tracks.push(panel.attrs.id);
                continue;
            }
            if (panel.attrs.trackGroupId !== undefined) {
                const trackGroup = globals$1.globals.state.trackGroups[panel.attrs.trackGroupId];
                // Only select a track group and all child tracks if it is closed.
                if (trackGroup.collapsed) {
                    tracks.push(panel.attrs.trackGroupId);
                    for (const track of trackGroup.tracks) {
                        tracks.push(track);
                    }
                }
            }
        }
        globals$1.globals.frontendLocalState.selectArea(area.startSec, area.endSec, tracks);
    }
    oncreate(vnodeDom) {
        // Save the canvas context in the state.
        const canvas = vnodeDom.dom.querySelector('.main-canvas');
        const ctx = canvas.getContext('2d');
        if (!ctx) {
            throw Error('Cannot create canvas context');
        }
        this.ctx = ctx;
        this.readParentSizeFromDom(vnodeDom.dom);
        this.readPanelHeightsFromDom(vnodeDom.dom);
        this.updateCanvasDimensions();
        this.repositionCanvas();
        // Save the resize handler in the state so we can remove it later.
        // TODO: Encapsulate resize handling better.
        this.onResize = () => {
            this.readParentSizeFromDom(vnodeDom.dom);
            this.updateCanvasDimensions();
            this.repositionCanvas();
            globals$1.globals.rafScheduler.scheduleFullRedraw();
        };
        // Once ResizeObservers are out, we can stop accessing the window here.
        window.addEventListener('resize', this.onResize);
        // TODO(dproy): Handle change in doesScroll attribute.
        if (this.attrs.doesScroll) {
            this.parentOnScroll = () => {
                this.scrollTop = logging.assertExists(vnodeDom.dom.parentElement).scrollTop;
                this.repositionCanvas();
                globals$1.globals.rafScheduler.scheduleRedraw();
            };
            vnodeDom.dom.parentElement.addEventListener('scroll', this.parentOnScroll, { passive: true });
        }
    }
    onremove({ attrs, dom }) {
        window.removeEventListener('resize', this.onResize);
        globals$1.globals.rafScheduler.removeRedrawCallback(this.canvasRedrawer);
        if (attrs.doesScroll) {
            dom.parentElement.removeEventListener('scroll', this.parentOnScroll);
        }
        perf.perfDisplay.removeContainer(this);
    }
    view({ attrs }) {
        this.attrs = attrs;
        const renderPanel = (panel) => perf.perfDebug() ?
            mithril('.panel', { key: panel.key }, [panel, mithril('.debug-panel-border', { key: 'debug-panel-border' })]) :
            mithril('.panel', { key: panel.key }, panel);
        return [
            mithril('.scroll-limiter', mithril('canvas.main-canvas')),
            mithril('.panels', attrs.panels.map(renderPanel))
        ];
    }
    onupdate(vnodeDom) {
        const totalPanelHeightChanged = this.readPanelHeightsFromDom(vnodeDom.dom);
        const parentSizeChanged = this.readParentSizeFromDom(vnodeDom.dom);
        const canvasSizeShouldChange = parentSizeChanged || !this.attrs.doesScroll && totalPanelHeightChanged;
        if (canvasSizeShouldChange) {
            this.updateCanvasDimensions();
            this.repositionCanvas();
            if (this.attrs.kind === 'TRACKS') {
                globals$1.globals.frontendLocalState.updateLocalLimits(0, this.parentWidth - css_constants.TRACK_SHELL_WIDTH);
            }
            this.redrawCanvas();
        }
    }
    updateCanvasDimensions() {
        this.canvasHeight = Math.floor(this.attrs.doesScroll ? this.parentHeight * this.canvasOverdrawFactor :
            this.totalPanelHeight);
        const ctx = logging.assertExists(this.ctx);
        const canvas = logging.assertExists(ctx.canvas);
        canvas.style.height = `${this.canvasHeight}px`;
        // If're we're non-scrolling canvas and the scroll-limiter should always
        // have the same height. Enforce this by explicitly setting the height.
        if (!this.attrs.doesScroll) {
            const scrollLimiter = canvas.parentElement;
            if (scrollLimiter) {
                scrollLimiter.style.height = `${this.canvasHeight}px`;
            }
        }
        const dpr = window.devicePixelRatio;
        ctx.canvas.width = this.parentWidth * dpr;
        ctx.canvas.height = this.canvasHeight * dpr;
        ctx.scale(dpr, dpr);
    }
    repositionCanvas() {
        const canvas = logging.assertExists(logging.assertExists(this.ctx).canvas);
        const canvasYStart = Math.floor(this.scrollTop - this.getCanvasOverdrawHeightPerSide());
        canvas.style.transform = `translateY(${canvasYStart}px)`;
    }
    /**
     * Reads dimensions of parent node. Returns true if read dimensions are
     * different from what was cached in the state.
     */
    readParentSizeFromDom(dom) {
        const oldWidth = this.parentWidth;
        const oldHeight = this.parentHeight;
        const clientRect = logging.assertExists(dom.parentElement).getBoundingClientRect();
        // On non-MacOS if there is a solid scroll bar it can cover important
        // pixels, reduce the size of the canvas so it doesn't overlap with
        // the scroll bar.
        this.parentWidth =
            clientRect.width - globals$1.globals.frontendLocalState.getScrollbarWidth();
        this.parentHeight = clientRect.height;
        return this.parentHeight !== oldHeight || this.parentWidth !== oldWidth;
    }
    /**
     * Reads dimensions of panels. Returns true if total panel height is different
     * from what was cached in state.
     */
    readPanelHeightsFromDom(dom) {
        const prevHeight = this.totalPanelHeight;
        this.panelPositions = [];
        this.totalPanelHeight = 0;
        const panels = dom.parentElement.querySelectorAll('.panel');
        logging.assertTrue(panels.length === this.attrs.panels.length);
        for (let i = 0; i < panels.length; i++) {
            const rect = panels[i].getBoundingClientRect();
            const id = this.attrs.panels[i].attrs.id ||
                this.attrs.panels[i].attrs.trackGroupId;
            this.panelPositions[i] =
                { id, height: rect.height, width: rect.width, x: rect.x, y: rect.y };
            this.totalPanelHeight += rect.height;
        }
        return this.totalPanelHeight !== prevHeight;
    }
    overlapsCanvas(yStart, yEnd) {
        return yEnd > 0 && yStart < this.canvasHeight;
    }
    redrawCanvas() {
        const redrawStart = perf.debugNow();
        if (!this.ctx)
            return;
        this.ctx.clearRect(0, 0, this.parentWidth, this.canvasHeight);
        const canvasYStart = Math.floor(this.scrollTop - this.getCanvasOverdrawHeightPerSide());
        this.handleAreaSelection();
        let panelYStart = 0;
        const panels = logging.assertExists(this.attrs).panels;
        logging.assertTrue(panels.length === this.panelPositions.length);
        let totalOnCanvas = 0;
        const flowEventsRendererArgs = new flow_events_renderer.FlowEventsRendererArgs(this.parentWidth, this.canvasHeight);
        for (let i = 0; i < panels.length; i++) {
            const panel$1 = panels[i];
            const panelHeight = this.panelPositions[i].height;
            const yStartOnCanvas = panelYStart - canvasYStart;
            if (!panel.isPanelVNode(panel$1)) {
                throw new Error('Vnode passed to panel container is not a panel');
            }
            // TODO(hjd): This cast should be unnecessary given the type guard above.
            const p = panel$1;
            flowEventsRendererArgs.registerPanel(p, yStartOnCanvas, panelHeight);
            if (!this.overlapsCanvas(yStartOnCanvas, yStartOnCanvas + panelHeight)) {
                panelYStart += panelHeight;
                continue;
            }
            totalOnCanvas++;
            this.ctx.save();
            this.ctx.translate(0, yStartOnCanvas);
            const clipRect = new Path2D();
            const size = { width: this.parentWidth, height: panelHeight };
            clipRect.rect(0, 0, size.width, size.height);
            this.ctx.clip(clipRect);
            const beforeRender = perf.debugNow();
            p.state.renderCanvas(this.ctx, size, p);
            this.updatePanelStats(i, p.state, perf.debugNow() - beforeRender, this.ctx, size);
            this.ctx.restore();
            panelYStart += panelHeight;
        }
        this.drawTopLayerOnCanvas();
        this.flowEventsRenderer.render(this.ctx, flowEventsRendererArgs);
        // Collect performance as the last thing we do.
        const redrawDur = perf.debugNow() - redrawStart;
        this.updatePerfStats(redrawDur, panels.length, totalOnCanvas);
    }
    // The panels each draw on the canvas but some details need to be drawn across
    // the whole canvas rather than per panel.
    drawTopLayerOnCanvas() {
        if (!this.ctx)
            return;
        const area = globals$1.globals.frontendLocalState.selectedArea;
        if (area === undefined ||
            globals$1.globals.frontendLocalState.areaY.start === undefined ||
            globals$1.globals.frontendLocalState.areaY.end === undefined) {
            return;
        }
        if (this.panelPositions.length === 0 || area.tracks.length === 0)
            return;
        // Find the minY and maxY of the selected tracks in this panel container.
        const panelContainerTop = this.panelPositions[0].y;
        const panelContainerBottom = this.panelPositions[this.panelPositions.length - 1].y +
            this.panelPositions[this.panelPositions.length - 1].height;
        let selectedTracksMinY = panelContainerBottom;
        let selectedTracksMaxY = panelContainerTop;
        let trackFromCurrentContainerSelected = false;
        for (let i = 0; i < this.panelPositions.length; i++) {
            if (area.tracks.includes(this.panelPositions[i].id)) {
                trackFromCurrentContainerSelected = true;
                selectedTracksMinY =
                    Math.min(selectedTracksMinY, this.panelPositions[i].y);
                selectedTracksMaxY = Math.max(selectedTracksMaxY, this.panelPositions[i].y + this.panelPositions[i].height);
            }
        }
        // No box should be drawn if there are no selected tracks in the current
        // container.
        if (!trackFromCurrentContainerSelected) {
            return;
        }
        const startX = globals$1.globals.frontendLocalState.timeScale.timeToPx(area.startSec);
        const endX = globals$1.globals.frontendLocalState.timeScale.timeToPx(area.endSec);
        // To align with where to draw on the canvas subtract the first panel Y.
        selectedTracksMinY -= panelContainerTop;
        selectedTracksMaxY -= panelContainerTop;
        this.ctx.save();
        this.ctx.strokeStyle = 'rgba(52,69,150)';
        this.ctx.lineWidth = 1;
        const canvasYStart = Math.floor(this.scrollTop - this.getCanvasOverdrawHeightPerSide());
        this.ctx.translate(css_constants.TRACK_SHELL_WIDTH, -canvasYStart);
        this.ctx.strokeRect(startX, selectedTracksMaxY, endX - startX, selectedTracksMinY - selectedTracksMaxY);
        this.ctx.restore();
    }
    updatePanelStats(panelIndex, panel, renderTime, ctx, size) {
        if (!perf.perfDebug())
            return;
        let renderStats = this.panelPerfStats.get(panel);
        if (renderStats === undefined) {
            renderStats = new perf.RunningStatistics();
            this.panelPerfStats.set(panel, renderStats);
        }
        renderStats.addValue(renderTime);
        const statW = 300;
        ctx.fillStyle = 'hsl(97, 100%, 96%)';
        ctx.fillRect(size.width - statW, size.height - 20, statW, 20);
        ctx.fillStyle = 'hsla(122, 77%, 22%)';
        const statStr = `Panel ${panelIndex + 1} | ` + perf.runningStatStr(renderStats);
        ctx.fillText(statStr, size.width - statW, size.height - 10);
    }
    updatePerfStats(renderTime, totalPanels, panelsOnCanvas) {
        if (!perf.perfDebug())
            return;
        this.perfStats.renderStats.addValue(renderTime);
        this.perfStats.totalPanels = totalPanels;
        this.perfStats.panelsOnCanvas = panelsOnCanvas;
    }
    renderPerfStats(index) {
        logging.assertTrue(perf.perfDebug());
        return [mithril('section', mithril('div', `Panel Container ${index + 1}`), mithril('div', `${this.perfStats.totalPanels} panels, ` +
                `${this.perfStats.panelsOnCanvas} on canvas.`), mithril('div', perf.runningStatStr(this.perfStats.renderStats)))];
    }
    getCanvasOverdrawHeightPerSide() {
        const overdrawHeight = (this.canvasOverdrawFactor - 1) * this.parentHeight;
        return overdrawHeight / 2;
    }
}
exports.PanelContainer = PanelContainer;

});

var slice_panel = createCommonjsModule(function (module, exports) {
// Copyright (C) 2019 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use size 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.
Object.defineProperty(exports, "__esModule", { value: true });
exports.SliceDetailsPanel = void 0;








class SliceDetailsPanel extends panel.Panel {
    view() {
        const sliceInfo = globals$1.globals.sliceDetails;
        if (sliceInfo.utid === undefined)
            return;
        const threadInfo = globals$1.globals.threads.get(sliceInfo.utid);
        return mithril('.details-panel', mithril('.details-panel-heading', mithril('h2.split', `Slice Details`), (sliceInfo.wakeupTs && sliceInfo.wakerUtid) ?
            mithril('h2.split', 'Scheduling Latency') :
            ''), this.getDetails(sliceInfo, threadInfo));
    }
    getDetails(sliceInfo, threadInfo) {
        if (!threadInfo || sliceInfo.ts === undefined ||
            sliceInfo.dur === undefined) {
            return null;
        }
        else {
            return mithril('.details-table', mithril('table.half-width', [
                mithril('tr', mithril('th', `Process`), mithril('td', `${threadInfo.procName} [${threadInfo.pid}]`)),
                mithril('tr', mithril('th', `Thread`), mithril('td', `${threadInfo.threadName} [${threadInfo.tid}]`, mithril('i.material-icons.grey', { onclick: () => this.goToThread(), title: 'Go to thread' }, 'call_made'))),
                mithril('tr', mithril('th', `Cmdline`), mithril('td', threadInfo.cmdline)),
                mithril('tr', mithril('th', `Start time`), mithril('td', `${time.timeToCode(sliceInfo.ts)}`)),
                mithril('tr', mithril('th', `Duration`), mithril('td', `${time.timeToCode(sliceInfo.dur)}`)),
                mithril('tr', mithril('th', `Prio`), mithril('td', `${sliceInfo.priority}`)),
                mithril('tr', mithril('th', `End State`), mithril('td', thread_state.translateState(sliceInfo.endState))),
                mithril('tr', mithril('th', `Slice ID`), mithril('td', sliceInfo.id ? sliceInfo.id.toString() : 'Unknown'))
            ]));
        }
    }
    goToThread() {
        const sliceInfo = globals$1.globals.sliceDetails;
        if (sliceInfo.utid === undefined)
            return;
        const threadInfo = globals$1.globals.threads.get(sliceInfo.utid);
        if (sliceInfo.id === undefined || sliceInfo.ts === undefined ||
            sliceInfo.dur === undefined || sliceInfo.cpu === undefined ||
            threadInfo === undefined) {
            return;
        }
        let trackId;
        for (const track of Object.values(globals$1.globals.state.tracks)) {
            if (track.kind === 'ThreadStateTrack' &&
                track.config.utid === threadInfo.utid) {
                trackId = track.id;
            }
        }
        if (trackId && sliceInfo.threadStateId) {
            globals$1.globals.makeSelection(actions.Actions.selectThreadState({
                id: sliceInfo.threadStateId,
                trackId: trackId.toString(),
            }));
            scroll_helper.scrollToTrackAndTs(trackId, time.toNs(sliceInfo.ts + globals$1.globals.state.traceTime.startSec), true);
        }
    }
    renderCanvas(ctx, size) {
        const details = globals$1.globals.sliceDetails;
        // Show expanded details on the scheduling of the currently selected slice.
        if (details.wakeupTs && details.wakerUtid !== undefined) {
            const threadInfo = globals$1.globals.threads.get(details.wakerUtid);
            // Draw diamond and vertical line.
            const startDraw = { x: size.width / 2 + 20, y: 52 };
            ctx.beginPath();
            ctx.moveTo(startDraw.x, startDraw.y + 28);
            ctx.fillStyle = 'black';
            ctx.lineTo(startDraw.x + 6, startDraw.y + 20);
            ctx.lineTo(startDraw.x, startDraw.y + 12);
            ctx.lineTo(startDraw.x - 6, startDraw.y + 20);
            ctx.fill();
            ctx.closePath();
            ctx.fillRect(startDraw.x - 1, startDraw.y, 2, 100);
            // Wakeup explanation text.
            ctx.font = '13px Roboto Condensed';
            ctx.fillStyle = '#3c4b5d';
            if (threadInfo) {
                const displayText = `Wakeup @ ${time.timeToCode(details.wakeupTs - globals$1.globals.state.traceTime.startSec)} on CPU ${details.wakerCpu} by`;
                const processText = `P: ${threadInfo.procName} [${threadInfo.pid}]`;
                const threadText = `T: ${threadInfo.threadName} [${threadInfo.tid}]`;
                ctx.fillText(displayText, startDraw.x + 20, startDraw.y + 20);
                ctx.fillText(processText, startDraw.x + 20, startDraw.y + 37);
                ctx.fillText(threadText, startDraw.x + 20, startDraw.y + 55);
            }
            // Draw latency arrow and explanation text.
            canvas_utils.drawDoubleHeadedArrow(ctx, startDraw.x, startDraw.y + 80, 60, true);
            if (details.ts) {
                const displayLatency = `Scheduling latency: ${time.timeToCode(details.ts -
                    (details.wakeupTs - globals$1.globals.state.traceTime.startSec))}`;
                ctx.fillText(displayLatency, startDraw.x + 70, startDraw.y + 86);
                const explain1 = 'This is the interval from when the task became eligible to run';
                const explain2 = '(e.g. because of notifying a wait queue it was suspended on) to';
                const explain3 = 'when it started running.';
                ctx.font = '10px Roboto Condensed';
                ctx.fillText(explain1, startDraw.x + 70, startDraw.y + 86 + 16);
                ctx.fillText(explain2, startDraw.x + 70, startDraw.y + 86 + 16 + 12);
                ctx.fillText(explain3, startDraw.x + 70, startDraw.y + 86 + 16 + 24);
            }
        }
    }
}
exports.SliceDetailsPanel = SliceDetailsPanel;

});

var thread_state_panel = createCommonjsModule(function (module, exports) {
// Copyright (C) 2019 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use size 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.
Object.defineProperty(exports, "__esModule", { value: true });
exports.ThreadStatePanel = void 0;






class ThreadStatePanel extends panel.Panel {
    view() {
        const threadState = globals$1.globals.threadStateDetails;
        if (threadState === undefined || threadState.utid === undefined ||
            threadState.ts === undefined || threadState.dur === undefined ||
            threadState.state === undefined) {
            return mithril('.details-panel');
        }
        const threadInfo = globals$1.globals.threads.get(threadState.utid);
        if (threadInfo) {
            return mithril('.details-panel', mithril('.details-panel-heading', mithril('h2', 'Thread State')), mithril('.details-table', [mithril('table.half-width', [
                    mithril('tr', mithril('th', `Start time`), mithril('td', `${time.timeToCode(threadState.ts)}`)),
                    mithril('tr', mithril('th', `Duration`), mithril('td', `${time.timeToCode(threadState.dur)} `)),
                    mithril('tr', mithril('th', `State`), mithril('td', this.getStateContent(threadState.state, threadState.cpu, threadState.sliceId, threadState.ts))),
                    mithril('tr', mithril('th', `Process`), mithril('td', `${threadInfo.procName} [${threadInfo.pid}]`)),
                    this.getBlockedFunctionContent(threadState.blockedFunction),
                ])]));
        }
        return mithril('.details-panel');
    }
    renderCanvas(_ctx, _size) { }
    // If it is the running state, we want to show which CPU and a button to
    // go to the sched slice. Otherwise, just show the state.
    getStateContent(state, cpu, sliceId, ts) {
        if (sliceId === undefined || cpu === undefined) {
            return [state];
        }
        return [
            `${state} on CPU ${cpu}`,
            mithril('i.material-icons.grey', {
                onclick: () => {
                    // TODO(hjd): Use trackId from TP.
                    let trackId;
                    for (const track of Object.values(globals$1.globals.state.tracks)) {
                        if (track.kind === 'CpuSliceTrack' &&
                            track.config.cpu === cpu) {
                            trackId = track.id;
                        }
                    }
                    if (trackId) {
                        globals$1.globals.makeSelection(actions.Actions.selectSlice({ id: sliceId, trackId }));
                        scroll_helper.scrollToTrackAndTs(trackId, time.toNs(ts + globals$1.globals.state.traceTime.startSec));
                    }
                },
                title: 'Go to CPU slice'
            }, 'call_made')
        ];
    }
    getBlockedFunctionContent(blockedFunction) {
        if (blockedFunction === undefined) {
            return null;
        }
        return mithril('tr', mithril('th', `Blocked Function`), mithril('td', blockedFunction));
    }
}
exports.ThreadStatePanel = ThreadStatePanel;

});

var details_panel = createCommonjsModule(function (module, exports) {
// Copyright (C) 2019 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.
Object.defineProperty(exports, "__esModule", { value: true });
exports.DetailsPanel = void 0;

















const UP_ICON = 'keyboard_arrow_up';
const DOWN_ICON = 'keyboard_arrow_down';
const DRAG_HANDLE_HEIGHT_PX = 28;
const DEFAULT_DETAILS_HEIGHT_PX = 230 + DRAG_HANDLE_HEIGHT_PX;
function getFullScreenHeight() {
    const panelContainer = document.querySelector('.pan-and-zoom-content');
    if (panelContainer !== null) {
        return panelContainer.clientHeight;
    }
    else {
        return DEFAULT_DETAILS_HEIGHT_PX;
    }
}
function hasLogs() {
    const data = globals$1.globals.trackDataStore.get(logs.LogExistsKey);
    return data && data.exists;
}
class DragHandle {
    constructor() {
        this.dragStartHeight = 0;
        this.height = 0;
        this.previousHeight = this.height;
        this.resize = () => { };
        this.isClosed = this.height <= DRAG_HANDLE_HEIGHT_PX;
        this.isFullscreen = false;
        // We can't get real fullscreen height until the pan_and_zoom_handler exists.
        this.fullscreenHeight = DEFAULT_DETAILS_HEIGHT_PX;
    }
    oncreate({ dom, attrs }) {
        this.resize = attrs.resize;
        this.height = attrs.height;
        this.isClosed = this.height <= DRAG_HANDLE_HEIGHT_PX;
        this.fullscreenHeight = getFullScreenHeight();
        const elem = dom;
        new drag_gesture_handler.DragGestureHandler(elem, this.onDrag.bind(this), this.onDragStart.bind(this), this.onDragEnd.bind(this));
    }
    onupdate({ attrs }) {
        this.resize = attrs.resize;
        this.height = attrs.height;
        this.isClosed = this.height <= DRAG_HANDLE_HEIGHT_PX;
    }
    onDrag(_x, y) {
        const newHeight = Math.floor(this.dragStartHeight + (DRAG_HANDLE_HEIGHT_PX / 2) - y);
        this.isClosed = newHeight <= DRAG_HANDLE_HEIGHT_PX;
        this.isFullscreen = newHeight >= this.fullscreenHeight;
        this.resize(newHeight);
        globals$1.globals.rafScheduler.scheduleFullRedraw();
    }
    onDragStart(_x, _y) {
        this.dragStartHeight = this.height;
    }
    onDragEnd() { }
    view({ attrs }) {
        const icon = this.isClosed ? UP_ICON : DOWN_ICON;
        const title = this.isClosed ? 'Show panel' : 'Hide panel';
        const activeTabExists = globals$1.globals.frontendLocalState.currentTab &&
            attrs.tabs.map(tab => tab.key)
                .includes(globals$1.globals.frontendLocalState.currentTab);
        if (!activeTabExists) {
            globals$1.globals.frontendLocalState.currentTab = undefined;
        }
        const renderTab = (tab) => {
            if (globals$1.globals.frontendLocalState.currentTab === tab.key ||
                globals$1.globals.frontendLocalState.currentTab === undefined &&
                    attrs.tabs.keys().next().value === tab.key) {
                // Update currentTab in case we didn't have one before.
                globals$1.globals.frontendLocalState.currentTab = tab.key;
                return mithril('.tab[active]', tab.name);
            }
            return mithril('.tab', {
                onclick: () => {
                    globals$1.globals.frontendLocalState.currentTab = tab.key;
                    globals$1.globals.rafScheduler.scheduleFullRedraw();
                }
            }, tab.name);
        };
        return mithril('.handle', mithril('.tabs', attrs.tabs.map(renderTab)), mithril('.buttons', mithril('i.material-icons', {
            onclick: () => {
                this.isClosed = false;
                this.isFullscreen = true;
                this.resize(this.fullscreenHeight);
                globals$1.globals.rafScheduler.scheduleFullRedraw();
            },
            title: 'Open fullscreen',
            disabled: this.isFullscreen
        }, 'vertical_align_top'), mithril('i.material-icons', {
            onclick: () => {
                if (this.height === DRAG_HANDLE_HEIGHT_PX) {
                    this.isClosed = false;
                    if (this.previousHeight === 0) {
                        this.previousHeight = DEFAULT_DETAILS_HEIGHT_PX;
                    }
                    this.resize(this.previousHeight);
                }
                else {
                    this.isFullscreen = false;
                    this.isClosed = true;
                    this.previousHeight = this.height;
                    this.resize(DRAG_HANDLE_HEIGHT_PX);
                }
                globals$1.globals.rafScheduler.scheduleFullRedraw();
            },
            title
        }, icon)));
    }
}
class DetailsPanel {
    constructor() {
        this.detailsHeight = DEFAULT_DETAILS_HEIGHT_PX;
        // Used to set details panel to default height on selection.
        this.showDetailsPanel = true;
    }
    view() {
        var _a;
        const detailsPanels = [];
        const curSelection = globals$1.globals.state.currentSelection;
        if (curSelection) {
            switch (curSelection.kind) {
                case 'NOTE':
                    detailsPanels.push({
                        key: 'current_selection',
                        name: 'Current Selection',
                        vnode: mithril(notes_panel.NotesEditorPanel, {
                            key: 'notes',
                            id: curSelection.id,
                        })
                    });
                    break;
                case 'AREA':
                    if (curSelection.noteId !== undefined) {
                        detailsPanels.push({
                            key: 'current_selection',
                            name: 'Current Selection',
                            vnode: mithril(notes_panel.NotesEditorPanel, {
                                key: 'area_notes',
                                id: curSelection.noteId,
                            })
                        });
                    }
                    break;
                case 'SLICE':
                    detailsPanels.push({
                        key: 'current_selection',
                        name: 'Current Selection',
                        vnode: mithril(slice_panel.SliceDetailsPanel, {
                            key: 'slice',
                        })
                    });
                    break;
                case 'COUNTER':
                    detailsPanels.push({
                        key: 'current_selection',
                        name: 'Current Selection',
                        vnode: mithril(counter_panel.CounterDetailsPanel, {
                            key: 'counter',
                        })
                    });
                    break;
                case 'HEAP_PROFILE':
                    detailsPanels.push({
                        key: 'current_selection',
                        name: 'Current Selection',
                        vnode: mithril(heap_profile_panel.HeapProfileDetailsPanel, { key: 'heap_profile' })
                    });
                    break;
                case 'CPU_PROFILE_SAMPLE':
                    detailsPanels.push({
                        key: 'current_selection',
                        name: 'Current Selection',
                        vnode: mithril(cpu_profile_panel.CpuProfileDetailsPanel, {
                            key: 'cpu_profile_sample',
                        })
                    });
                    break;
                case 'CHROME_SLICE':
                    detailsPanels.push({
                        key: 'current_selection',
                        name: 'Current Selection',
                        vnode: mithril(chrome_slice_panel.ChromeSliceDetailsPanel, { key: 'chrome_slice' })
                    });
                    break;
                case 'THREAD_STATE':
                    detailsPanels.push({
                        key: 'current_selection',
                        name: 'Current Selection',
                        vnode: mithril(thread_state_panel.ThreadStatePanel, { key: 'thread_state' })
                    });
                    break;
            }
        }
        if (globals$1.globals.functionProfileDetails.length > 0) {
            for (const detail of globals$1.globals.functionProfileDetails) {
                let name = "";
                if (detail.name === undefined) {
                    name = "unknown";
                }
                else {
                    name = detail.name;
                }
                detailsPanels.push({
                    key: name,
                    name: name,
                    vnode: mithril(function_profile_panel.FunctionProfileDetailsPanel, { key: 'function_profile', data: detail })
                });
            }
            if (!globals$1.globals.frontendLocalState.currentTab) {
                globals$1.globals.frontendLocalState.currentTab = globals$1.globals.functionProfileDetails[0].name;
            }
        }
        if (hasLogs()) {
            detailsPanels.push({
                key: 'android_logs',
                name: 'Android Logs',
                vnode: mithril(logs_panel.LogPanel, { key: 'logs_panel' })
            });
        }
        if (globals$1.globals.queryResults.has('command')) {
            const count = globals$1.globals.queryResults.get('command').rows.length;
            detailsPanels.push({
                key: 'query_result',
                name: `Query Result (${count})`,
                vnode: mithril(query_table.QueryTable, { key: 'query', queryId: 'command' })
            });
        }
        if (globals$1.globals.connectedFlows.length > 0) {
            detailsPanels.push({
                key: 'bound_flows',
                name: 'Flow Events',
                vnode: mithril(flow_events_panel.FlowEventsPanel, { key: 'flow_events' })
            });
        }
        for (const [key, value] of globals$1.globals.aggregateDataStore.entries()) {
            if (value.columns.length > 0 && value.columns[0].data.length > 0) {
                detailsPanels.push({
                    key: value.tabName,
                    name: value.tabName,
                    vnode: mithril(aggregation_panel.AggregationPanel, { kind: key, key, data: value })
                });
            }
        }
        // Add this after all aggregation panels, to make it appear after 'Slices'
        if (globals$1.globals.selectedFlows.length > 0) {
            detailsPanels.push({
                key: 'selected_flows',
                name: 'Flow Events',
                vnode: mithril(flow_events_panel.FlowEventsAreaSelectedPanel)
            });
        }
        this.showDetailsPanel = detailsPanels.length > 0;
        const currentTabDetails = detailsPanels.filter(tab => tab.key === globals$1.globals.frontendLocalState.currentTab)[0];
        const panel = currentTabDetails ?
            currentTabDetails.vnode : (_a = detailsPanels.values().next().value) === null || _a === void 0 ? void 0 : _a.vnode;
        const panels = panel ? [panel] : [];
        return mithril('.details-content', {
            style: {
                height: globals$1.globals.functionProfileDetails.length == 0 ? `${this.detailsHeight}px` : "100%",
                display: this.showDetailsPanel ? null : 'none'
            }
        }, mithril(DragHandle, {
            resize: (height) => {
                this.detailsHeight = Math.max(height, DRAG_HANDLE_HEIGHT_PX);
            },
            height: this.detailsHeight,
            tabs: detailsPanels.map(tab => {
                return { key: tab.key, name: tab.name };
            }),
        }), mithril('.details-panel-container', mithril(panel_container.PanelContainer, { doesScroll: true, panels, kind: 'DETAILS' })));
    }
}
exports.DetailsPanel = DetailsPanel;

});

var drag_strategy = createCommonjsModule(function (module, exports) {
Object.defineProperty(exports, "__esModule", { value: true });
exports.DragStrategy = void 0;
// Copyright (C) 2021 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.


class DragStrategy {
    constructor(timeScale) {
        this.timeScale = timeScale;
    }
    updateGlobals(tStart, tEnd) {
        const vizTime = new time.TimeSpan(tStart, tEnd);
        globals$1.globals.frontendLocalState.updateVisibleTime(vizTime);
        globals$1.globals.rafScheduler.scheduleRedraw();
    }
}
exports.DragStrategy = DragStrategy;

});

var border_drag_strategy = createCommonjsModule(function (module, exports) {
Object.defineProperty(exports, "__esModule", { value: true });
exports.BorderDragStrategy = void 0;

class BorderDragStrategy extends drag_strategy.DragStrategy {
    constructor(timeScale, pixelBounds) {
        super(timeScale);
        this.pixelBounds = pixelBounds;
        this.moveStart = false;
    }
    onDrag(x) {
        let tStart = this.timeScale.pxToTime(this.moveStart ? x : this.pixelBounds[0]);
        let tEnd = this.timeScale.pxToTime(!this.moveStart ? x : this.pixelBounds[1]);
        if (tStart > tEnd) {
            this.moveStart = !this.moveStart;
            [tEnd, tStart] = [tStart, tEnd];
        }
        super.updateGlobals(tStart, tEnd);
        this.pixelBounds =
            [this.timeScale.timeToPx(tStart), this.timeScale.timeToPx(tEnd)];
    }
    onDragStart(x) {
        this.moveStart =
            Math.abs(x - this.pixelBounds[0]) < Math.abs(x - this.pixelBounds[1]);
    }
}
exports.BorderDragStrategy = BorderDragStrategy;

});

var inner_drag_strategy = createCommonjsModule(function (module, exports) {
Object.defineProperty(exports, "__esModule", { value: true });
exports.InnerDragStrategy = void 0;

class InnerDragStrategy extends drag_strategy.DragStrategy {
    constructor(timeScale, pixelBounds) {
        super(timeScale);
        this.pixelBounds = pixelBounds;
        this.dragStartPx = 0;
    }
    onDrag(x) {
        const move = x - this.dragStartPx;
        const tStart = this.timeScale.pxToTime(this.pixelBounds[0] + move);
        const tEnd = this.timeScale.pxToTime(this.pixelBounds[1] + move);
        super.updateGlobals(tStart, tEnd);
    }
    onDragStart(x) {
        this.dragStartPx = x;
    }
}
exports.InnerDragStrategy = InnerDragStrategy;

});

var outer_drag_strategy = createCommonjsModule(function (module, exports) {
Object.defineProperty(exports, "__esModule", { value: true });
exports.OuterDragStrategy = void 0;
// Copyright (C) 2021 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.

class OuterDragStrategy extends drag_strategy.DragStrategy {
    constructor() {
        super(...arguments);
        this.dragStartPx = 0;
    }
    onDrag(x) {
        const dragBeginTime = this.timeScale.pxToTime(this.dragStartPx);
        const dragEndTime = this.timeScale.pxToTime(x);
        const tStart = Math.min(dragBeginTime, dragEndTime);
        const tEnd = Math.max(dragBeginTime, dragEndTime);
        super.updateGlobals(tStart, tEnd);
    }
    onDragStart(x) {
        this.dragStartPx = x;
    }
}
exports.OuterDragStrategy = OuterDragStrategy;

});

var overview_timeline_panel = createCommonjsModule(function (module, exports) {
// 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.
Object.defineProperty(exports, "__esModule", { value: true });
exports.OverviewTimelinePanel = void 0;












class OverviewTimelinePanel extends panel.Panel {
    constructor() {
        super(...arguments);
        this.width = 0;
        this.totTime = new time.TimeSpan(0, 0);
        this.boundOnMouseMove = this.onMouseMove.bind(this);
    }
    // Must explicitly type now; arguments types are no longer auto-inferred.
    // https://github.com/Microsoft/TypeScript/issues/1373
    onupdate({ dom }) {
        this.width = dom.getBoundingClientRect().width;
        this.totTime = new time.TimeSpan(globals$1.globals.state.traceTime.startSec, globals$1.globals.state.traceTime.endSec);
        this.timeScale = new time_scale.TimeScale(this.totTime, [css_constants.TRACK_SHELL_WIDTH, logging.assertExists(this.width)]);
        if (this.gesture === undefined) {
            this.gesture = new drag_gesture_handler.DragGestureHandler(dom, this.onDrag.bind(this), this.onDragStart.bind(this), this.onDragEnd.bind(this));
        }
    }
    oncreate(vnode) {
        this.onupdate(vnode);
        vnode.dom
            .addEventListener('mousemove', this.boundOnMouseMove);
    }
    onremove({ dom }) {
        dom
            .removeEventListener('mousemove', this.boundOnMouseMove);
    }
    view() {
        return mithril('.overview-timeline');
    }
    renderCanvas(ctx, size) {
        if (this.width === undefined)
            return;
        if (this.timeScale === undefined)
            return;
        const headerHeight = 25;
        const tracksHeight = size.height - headerHeight;
        // Draw time labels on the top header.
        ctx.font = '10px Roboto Condensed';
        ctx.fillStyle = '#999';
        for (let i = 0; i < 100; i++) {
            const xPos = (i * (this.width - css_constants.TRACK_SHELL_WIDTH) / 100) + css_constants.TRACK_SHELL_WIDTH;
            const t = this.timeScale.pxToTime(xPos);
            if (xPos <= 0)
                continue;
            if (xPos > this.width)
                break;
            if (i % 10 === 0) {
                ctx.fillRect(xPos - 1, 0, 1, headerHeight - 5);
                ctx.fillText(time.timeToString(t - this.totTime.start), xPos + 5, 18);
            }
            else {
                ctx.fillRect(xPos - 1, 0, 1, 5);
            }
        }
        // Draw mini-tracks with quanitzed density for each process.
        if (globals$1.globals.overviewStore.size > 0) {
            const numTracks = globals$1.globals.overviewStore.size;
            let y = 0;
            const trackHeight = (tracksHeight - 1) / numTracks;
            for (const key of globals$1.globals.overviewStore.keys()) {
                const loads = globals$1.globals.overviewStore.get(key);
                for (let i = 0; i < loads.length; i++) {
                    const xStart = Math.floor(this.timeScale.timeToPx(loads[i].startSec));
                    const xEnd = Math.ceil(this.timeScale.timeToPx(loads[i].endSec));
                    const yOff = Math.floor(headerHeight + y * trackHeight);
                    const lightness = Math.ceil((1 - loads[i].load * 0.7) * 100);
                    ctx.fillStyle = `hsl(${colorizer.hueForCpu(y)}, 50%, ${lightness}%)`;
                    ctx.fillRect(xStart, yOff, xEnd - xStart, Math.ceil(trackHeight));
                }
                y++;
            }
        }
        // Draw bottom border.
        ctx.fillStyle = '#dadada';
        ctx.fillRect(0, size.height - 1, this.width, 1);
        // Draw semi-opaque rects that occlude the non-visible time range.
        const [vizStartPx, vizEndPx] = OverviewTimelinePanel.extractBounds(this.timeScale);
        ctx.fillStyle = 'rgba(200, 200, 200, 0.8)';
        ctx.fillRect(css_constants.TRACK_SHELL_WIDTH - 1, headerHeight, vizStartPx - css_constants.TRACK_SHELL_WIDTH, tracksHeight);
        ctx.fillRect(vizEndPx, headerHeight, this.width - vizEndPx, tracksHeight);
        // Draw brushes.
        ctx.fillStyle = '#999';
        ctx.fillRect(vizStartPx - 1, headerHeight, 1, tracksHeight);
        ctx.fillRect(vizEndPx, headerHeight, 1, tracksHeight);
        const hbarWidth = OverviewTimelinePanel.HANDLE_SIZE_PX;
        const hbarDivisionFactor = 3.5;
        // Draw handlebar
        ctx.fillRect(vizStartPx - Math.floor(hbarWidth / 2) - 1, headerHeight, hbarWidth, tracksHeight / hbarDivisionFactor);
        ctx.fillRect(vizEndPx - Math.floor(hbarWidth / 2), headerHeight, hbarWidth, tracksHeight / hbarDivisionFactor);
    }
    onMouseMove(e) {
        if (this.gesture === undefined || this.gesture.isDragging) {
            return;
        }
        e.target.style.cursor = this.chooseCursor(e.x);
    }
    chooseCursor(x) {
        if (this.timeScale === undefined)
            return 'default';
        const [vizStartPx, vizEndPx] = OverviewTimelinePanel.extractBounds(this.timeScale);
        const startBound = vizStartPx - 1 + css_constants.SIDEBAR_WIDTH;
        const endBound = vizEndPx + css_constants.SIDEBAR_WIDTH;
        if (OverviewTimelinePanel.inBorderRange(x, startBound) ||
            OverviewTimelinePanel.inBorderRange(x, endBound)) {
            return 'ew-resize';
        }
        else if (x < css_constants.SIDEBAR_WIDTH + css_constants.TRACK_SHELL_WIDTH) {
            return 'default';
        }
        else if (x < startBound || endBound < x) {
            return 'crosshair';
        }
        else {
            return 'all-scroll';
        }
    }
    onDrag(x) {
        if (this.dragStrategy === undefined)
            return;
        this.dragStrategy.onDrag(x);
    }
    onDragStart(x) {
        if (this.timeScale === undefined)
            return;
        const pixelBounds = OverviewTimelinePanel.extractBounds(this.timeScale);
        if (OverviewTimelinePanel.inBorderRange(x, pixelBounds[0]) ||
            OverviewTimelinePanel.inBorderRange(x, pixelBounds[1])) {
            this.dragStrategy = new border_drag_strategy.BorderDragStrategy(this.timeScale, pixelBounds);
        }
        else if (x < pixelBounds[0] || pixelBounds[1] < x) {
            this.dragStrategy = new outer_drag_strategy.OuterDragStrategy(this.timeScale);
        }
        else {
            this.dragStrategy = new inner_drag_strategy.InnerDragStrategy(this.timeScale, pixelBounds);
        }
        this.dragStrategy.onDragStart(x);
    }
    onDragEnd() {
        this.dragStrategy = undefined;
    }
    static extractBounds(timeScale) {
        const vizTime = globals$1.globals.frontendLocalState.getVisibleStateBounds();
        return [
            Math.floor(timeScale.timeToPx(vizTime[0])),
            Math.ceil(timeScale.timeToPx(vizTime[1]))
        ];
    }
    static inBorderRange(a, b) {
        return Math.abs(a - b) < this.HANDLE_SIZE_PX / 2;
    }
}
exports.OverviewTimelinePanel = OverviewTimelinePanel;
OverviewTimelinePanel.HANDLE_SIZE_PX = 7;

});

var keyboard_event_handler = createCommonjsModule(function (module, exports) {
// Copyright (C) 2019 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.
Object.defineProperty(exports, "__esModule", { value: true });
exports.handleKey = void 0;





const INSTANT_FOCUS_DURATION_S = 1 / 1e9; // 1 ns.
// Handles all key events than are not handled by the
// pan and zoom handler.
function handleKey(e, down) {
    const key = e.key.toLowerCase();
    const selection = globals$1.globals.state.currentSelection;
    if (down && 'm' === key) {
        if (selection && selection.kind === 'AREA') {
            globals$1.globals.dispatch(actions.Actions.toggleMarkCurrentArea({ persistent: e.shiftKey }));
        }
        else if (selection) {
            lockSliceSpan(e.shiftKey);
        }
    }
    if (down && 'f' === key) {
        findCurrentSelection();
    }
    if (down && 'v' === key) {
        globals$1.globals.dispatch(actions.Actions.toggleVideo({}));
    }
    if (down && 'p' === key) {
        globals$1.globals.dispatch(actions.Actions.toggleFlagPause({}));
    }
    if (down && 't' === key) {
        globals$1.globals.dispatch(actions.Actions.toggleScrubbing({}));
        if (globals$1.globals.frontendLocalState.vidTimestamp < 0) {
            globals$1.globals.frontendLocalState.setVidTimestamp(Number.MAX_SAFE_INTEGER);
        }
        else {
            globals$1.globals.frontendLocalState.setVidTimestamp(Number.MIN_SAFE_INTEGER);
        }
    }
    if (down && 'b' === key && (e.ctrlKey || e.metaKey)) {
        globals$1.globals.frontendLocalState.toggleSidebar();
    }
    if (down && '?' === key) {
        help_modal.toggleHelp();
    }
    if (down && 'enter' === key) {
        e.preventDefault();
        search_handler.executeSearch(e.shiftKey);
    }
    if (down && 'escape' === key) {
        globals$1.globals.frontendLocalState.deselectArea();
        globals$1.globals.makeSelection(actions.Actions.deselect({}));
        globals$1.globals.dispatch(actions.Actions.removeNote({ id: '0' }));
    }
    if (down && ']' === key) {
        if (e.ctrlKey) {
            focusOtherFlow('Forward');
        }
        else {
            moveByFocusedFlow('Forward');
        }
    }
    if (down && '[' === key) {
        if (e.ctrlKey) {
            focusOtherFlow('Backward');
        }
        else {
            moveByFocusedFlow('Backward');
        }
    }
}
exports.handleKey = handleKey;
// Search |boundFlows| for |flowId| and return the id following it.
// Returns the first flow id if nothing was found or |flowId| was the last flow
// in |boundFlows|, and -1 if |boundFlows| is empty
function findAnotherFlowExcept(boundFlows, flowId) {
    let selectedFlowFound = false;
    if (boundFlows.length === 0) {
        return -1;
    }
    for (const flow of boundFlows) {
        if (selectedFlowFound) {
            return flow.id;
        }
        if (flow.id === flowId) {
            selectedFlowFound = true;
        }
    }
    return boundFlows[0].id;
}
// Change focus to the next flow event (matching the direction)
function focusOtherFlow(direction) {
    if (!globals$1.globals.state.currentSelection ||
        globals$1.globals.state.currentSelection.kind !== 'CHROME_SLICE') {
        return;
    }
    const sliceId = globals$1.globals.state.currentSelection.id;
    if (sliceId === -1) {
        return;
    }
    const boundFlows = globals$1.globals.connectedFlows.filter(flow => flow.begin.sliceId === sliceId && direction === 'Forward' ||
        flow.end.sliceId === sliceId && direction === 'Backward');
    if (direction === 'Backward') {
        const nextFlowId = findAnotherFlowExcept(boundFlows, globals$1.globals.frontendLocalState.focusedFlowIdLeft);
        globals$1.globals.frontendLocalState.setHighlightedFlowLeftId(nextFlowId);
    }
    else {
        const nextFlowId = findAnotherFlowExcept(boundFlows, globals$1.globals.frontendLocalState.focusedFlowIdRight);
        globals$1.globals.frontendLocalState.setHighlightedFlowRightId(nextFlowId);
    }
}
// Select the slice connected to the flow in focus
function moveByFocusedFlow(direction) {
    if (!globals$1.globals.state.currentSelection ||
        globals$1.globals.state.currentSelection.kind !== 'CHROME_SLICE') {
        return;
    }
    const sliceId = globals$1.globals.state.currentSelection.id;
    const flowId = (direction === 'Backward' ?
        globals$1.globals.frontendLocalState.focusedFlowIdLeft :
        globals$1.globals.frontendLocalState.focusedFlowIdRight);
    if (sliceId === -1 || flowId === -1) {
        return;
    }
    // Find flow that is in focus and select corresponding slice
    for (const flow of globals$1.globals.connectedFlows) {
        if (flow.id === flowId) {
            const flowPoint = (direction === 'Backward' ? flow.begin : flow.end);
            const uiTrackId = scroll_helper.findUiTrackId(flowPoint.trackId);
            if (uiTrackId) {
                globals$1.globals.makeSelection(actions.Actions.selectChromeSlice({ id: flowPoint.sliceId, trackId: uiTrackId, table: 'slice' }));
            }
        }
    }
}
function findTimeRangeOfSelection() {
    const selection = globals$1.globals.state.currentSelection;
    let startTs = -1;
    let endTs = -1;
    if (selection !== null) {
        if (selection.kind === 'SLICE' || selection.kind === 'CHROME_SLICE') {
            const slice = globals$1.globals.sliceDetails;
            if (slice.ts && slice.dur !== undefined && slice.dur > 0) {
                startTs = slice.ts + globals$1.globals.state.traceTime.startSec;
                endTs = startTs + slice.dur;
            }
            else if (slice.ts) {
                startTs = slice.ts + globals$1.globals.state.traceTime.startSec;
                endTs = startTs + INSTANT_FOCUS_DURATION_S;
            }
        }
        else if (selection.kind === 'THREAD_STATE') {
            const threadState = globals$1.globals.threadStateDetails;
            if (threadState.ts && threadState.dur) {
                startTs = threadState.ts + globals$1.globals.state.traceTime.startSec;
                endTs = startTs + threadState.dur;
            }
        }
        else if (selection.kind === 'COUNTER') {
            startTs = selection.leftTs;
            endTs = selection.rightTs;
        }
    }
    return { startTs, endTs };
}
function lockSliceSpan(persistent = false) {
    const range = findTimeRangeOfSelection();
    if (range.startTs !== -1 && range.endTs !== -1 &&
        globals$1.globals.state.currentSelection !== null) {
        const tracks = globals$1.globals.state.currentSelection.trackId ?
            [globals$1.globals.state.currentSelection.trackId] :
            [];
        const area = { startSec: range.startTs, endSec: range.endTs, tracks };
        globals$1.globals.dispatch(actions.Actions.markArea({ area, persistent }));
    }
}
function findCurrentSelection() {
    const selection = globals$1.globals.state.currentSelection;
    if (selection === null)
        return;
    const range = findTimeRangeOfSelection();
    if (range.startTs !== -1 && range.endTs !== -1) {
        scroll_helper.horizontalScrollAndZoomToRange(range.startTs, range.endTs);
    }
    if (selection.trackId) {
        scroll_helper.verticalScrollToTrack(selection.trackId, true);
    }
}

});

var pan_and_zoom_handler = createCommonjsModule(function (module, exports) {
// 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.
Object.defineProperty(exports, "__esModule", { value: true });
exports.PanAndZoomHandler = void 0;




// When first starting to pan or zoom, move at least this many units.
const INITIAL_PAN_STEP_PX = 50;
const INITIAL_ZOOM_STEP = 0.1;
// The snappiness (spring constant) of pan and zoom animations [0..1].
const SNAP_FACTOR = 0.4;
// How much the velocity of a pan or zoom animation increases per millisecond.
const ACCELERATION_PER_MS = 1 / 50;
// The default duration of a pan or zoom animation. The animation may run longer
// if the user keeps holding the respective button down or shorter if the button
// is released. This value so chosen so that it is longer than the typical key
// repeat timeout to avoid breaks in the animation.
const DEFAULT_ANIMATION_DURATION = 700;
// The minimum number of units to pan or zoom per frame (before the
// ACCELERATION_PER_MS multiplier is applied).
const ZOOM_RATIO_PER_FRAME = 0.008;
const KEYBOARD_PAN_PX_PER_FRAME = 8;
// Scroll wheel animation steps.
const HORIZONTAL_WHEEL_PAN_SPEED = 1;
const WHEEL_ZOOM_SPEED = -0.02;
const EDITING_RANGE_CURSOR = 'ew-resize';
const DRAG_CURSOR = 'default';
const PAN_CURSOR = 'move';
var Pan;
(function (Pan) {
    Pan[Pan["None"] = 0] = "None";
    Pan[Pan["Left"] = -1] = "Left";
    Pan[Pan["Right"] = 1] = "Right";
})(Pan || (Pan = {}));
function keyToPan(e) {
    const key = e.key.toLowerCase();
    if (['a'].includes(key))
        return Pan.Left;
    if (['d', 'e'].includes(key))
        return Pan.Right;
    return Pan.None;
}
var Zoom;
(function (Zoom) {
    Zoom[Zoom["None"] = 0] = "None";
    Zoom[Zoom["In"] = 1] = "In";
    Zoom[Zoom["Out"] = -1] = "Out";
})(Zoom || (Zoom = {}));
function keyToZoom(e) {
    const key = e.key.toLowerCase();
    if (['w', ','].includes(key))
        return Zoom.In;
    if (['s', 'o'].includes(key))
        return Zoom.Out;
    return Zoom.None;
}
/**
 * Enables horizontal pan and zoom with mouse-based drag and WASD navigation.
 */
class PanAndZoomHandler {
    constructor({ element, contentOffsetX, onPanned, onZoomed, editSelection, onSelection, endSelection }) {
        this.mousePositionX = null;
        this.boundOnMouseMove = this.onMouseMove.bind(this);
        this.boundOnWheel = this.onWheel.bind(this);
        this.boundOnKeyDown = this.onKeyDown.bind(this);
        this.boundOnKeyUp = this.onKeyUp.bind(this);
        this.shiftDown = false;
        this.panning = Pan.None;
        this.panOffsetPx = 0;
        this.targetPanOffsetPx = 0;
        this.zooming = Zoom.None;
        this.zoomRatio = 0;
        this.targetZoomRatio = 0;
        this.panAnimation = new animation.Animation(this.onPanAnimationStep.bind(this));
        this.zoomAnimation = new animation.Animation(this.onZoomAnimationStep.bind(this));
        this.element = element;
        this.contentOffsetX = contentOffsetX;
        this.onPanned = onPanned;
        this.onZoomed = onZoomed;
        this.editSelection = editSelection;
        this.onSelection = onSelection;
        this.endSelection = endSelection;
        document.body.addEventListener('keydown', this.boundOnKeyDown);
        document.body.addEventListener('keyup', this.boundOnKeyUp);
        this.element.addEventListener('mousemove', this.boundOnMouseMove);
        this.element.addEventListener('wheel', this.boundOnWheel, { passive: true });
        let prevX = -1;
        let dragStartX = -1;
        let dragStartY = -1;
        let edit = false;
        new drag_gesture_handler.DragGestureHandler(this.element, (x, y) => {
            if (this.shiftDown) {
                this.onPanned(prevX - x);
            }
            else {
                this.onSelection(dragStartX, dragStartY, prevX, x, y, edit);
            }
            prevX = x;
        }, (x, y) => {
            prevX = x;
            dragStartX = x;
            dragStartY = y;
            edit = this.editSelection(x);
            // Set the cursor style based on where the cursor is when the drag
            // starts.
            if (edit) {
                this.element.style.cursor = EDITING_RANGE_CURSOR;
            }
            else if (!this.shiftDown) {
                this.element.style.cursor = DRAG_CURSOR;
            }
        }, () => {
            // Reset the cursor now the drag has ended.
            this.element.style.cursor = this.shiftDown ? PAN_CURSOR : DRAG_CURSOR;
            dragStartX = -1;
            dragStartY = -1;
            this.endSelection(edit);
        });
    }
    shutdown() {
        document.body.removeEventListener('keydown', this.boundOnKeyDown);
        document.body.removeEventListener('keyup', this.boundOnKeyUp);
        this.element.removeEventListener('mousemove', this.boundOnMouseMove);
        this.element.removeEventListener('wheel', this.boundOnWheel);
    }
    onPanAnimationStep(msSinceStartOfAnimation) {
        const step = (this.targetPanOffsetPx - this.panOffsetPx) * SNAP_FACTOR;
        if (this.panning !== Pan.None) {
            const velocity = 1 + msSinceStartOfAnimation * ACCELERATION_PER_MS;
            // Pan at least as fast as the snapping animation to avoid a
            // discontinuity.
            const targetStep = Math.max(KEYBOARD_PAN_PX_PER_FRAME * velocity, step);
            this.targetPanOffsetPx += this.panning * targetStep;
        }
        this.panOffsetPx += step;
        if (Math.abs(step) > 1e-1) {
            this.onPanned(step);
        }
        else {
            this.panAnimation.stop();
        }
    }
    onZoomAnimationStep(msSinceStartOfAnimation) {
        if (this.mousePositionX === null)
            return;
        const step = (this.targetZoomRatio - this.zoomRatio) * SNAP_FACTOR;
        if (this.zooming !== Zoom.None) {
            const velocity = 1 + msSinceStartOfAnimation * ACCELERATION_PER_MS;
            // Zoom at least as fast as the snapping animation to avoid a
            // discontinuity.
            const targetStep = Math.max(ZOOM_RATIO_PER_FRAME * velocity, step);
            this.targetZoomRatio += this.zooming * targetStep;
        }
        this.zoomRatio += step;
        if (Math.abs(step) > 1e-6) {
            this.onZoomed(this.mousePositionX, step);
        }
        else {
            this.zoomAnimation.stop();
        }
    }
    onMouseMove(e) {
        const pageOffset = globals$1.globals.frontendLocalState.sidebarVisible ? this.contentOffsetX : 0;
        // We can't use layerX here because there are many layers in this element.
        this.mousePositionX = e.clientX - pageOffset;
        // Only change the cursor when hovering, the DragGestureHandler handles
        // changing the cursor during drag events. This avoids the problem of
        // the cursor flickering between styles if you drag fast and get too
        // far from the current time range.
        if (e.buttons === 0) {
            if (this.editSelection(this.mousePositionX)) {
                this.element.style.cursor = EDITING_RANGE_CURSOR;
            }
            else {
                this.element.style.cursor = this.shiftDown ? PAN_CURSOR : DRAG_CURSOR;
            }
        }
    }
    onWheel(e) {
        if (Math.abs(e.deltaX) > Math.abs(e.deltaY)) {
            this.onPanned(e.deltaX * HORIZONTAL_WHEEL_PAN_SPEED);
            globals$1.globals.rafScheduler.scheduleRedraw();
        }
        else if (e.ctrlKey && this.mousePositionX) {
            const sign = e.deltaY < 0 ? -1 : 1;
            const deltaY = sign * Math.log2(1 + Math.abs(e.deltaY));
            this.onZoomed(this.mousePositionX, deltaY * WHEEL_ZOOM_SPEED);
            globals$1.globals.rafScheduler.scheduleRedraw();
        }
    }
    onKeyDown(e) {
        this.updateShift(e.shiftKey);
        if (keyToPan(e) !== Pan.None) {
            if (this.panning !== keyToPan(e)) {
                this.panAnimation.stop();
                this.panOffsetPx = 0;
                this.targetPanOffsetPx = keyToPan(e) * INITIAL_PAN_STEP_PX;
            }
            this.panning = keyToPan(e);
            this.panAnimation.start(DEFAULT_ANIMATION_DURATION);
        }
        if (keyToZoom(e) !== Zoom.None) {
            if (this.zooming !== keyToZoom(e)) {
                this.zoomAnimation.stop();
                this.zoomRatio = 0;
                this.targetZoomRatio = keyToZoom(e) * INITIAL_ZOOM_STEP;
            }
            this.zooming = keyToZoom(e);
            this.zoomAnimation.start(DEFAULT_ANIMATION_DURATION);
        }
        // Handle key events that are not pan or zoom.
        keyboard_event_handler.handleKey(e, true);
    }
    onKeyUp(e) {
        this.updateShift(e.shiftKey);
        if (keyToPan(e) === this.panning) {
            this.panning = Pan.None;
        }
        if (keyToZoom(e) === this.zooming) {
            this.zooming = Zoom.None;
        }
        // Handle key events that are not pan or zoom.
        keyboard_event_handler.handleKey(e, false);
    }
    // TODO(hjd): Move this shift handling into the viewer page.
    updateShift(down) {
        if (down === this.shiftDown)
            return;
        this.shiftDown = down;
        if (this.shiftDown) {
            this.element.style.cursor = PAN_CURSOR;
        }
        else if (this.mousePositionX) {
            this.element.style.cursor = DRAG_CURSOR;
        }
    }
}
exports.PanAndZoomHandler = PanAndZoomHandler;

});

var tickmark_panel = createCommonjsModule(function (module, exports) {
// Copyright (C) 2019 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use size 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.
Object.defineProperty(exports, "__esModule", { value: true });
exports.TickmarkPanel = void 0;






// This is used to display the summary of search results.
class TickmarkPanel extends panel.Panel {
    view() {
        return mithril('.tickbar');
    }
    renderCanvas(ctx, size) {
        const { timeScale, visibleWindowTime } = globals$1.globals.frontendLocalState;
        ctx.fillStyle = '#999';
        ctx.fillRect(css_constants.TRACK_SHELL_WIDTH - 2, 0, 2, size.height);
        for (const xAndTime of gridline_helper.gridlines(size.width, visibleWindowTime, timeScale)) {
            ctx.fillRect(xAndTime[0], 0, 1, size.height);
        }
        const data = globals$1.globals.searchSummary;
        for (let i = 0; i < data.tsStarts.length; i++) {
            const tStart = data.tsStarts[i];
            const tEnd = data.tsEnds[i];
            if (tEnd <= visibleWindowTime.start || tStart >= visibleWindowTime.end) {
                continue;
            }
            const rectStart = Math.max(timeScale.timeToPx(tStart), 0) + css_constants.TRACK_SHELL_WIDTH;
            const rectEnd = timeScale.timeToPx(tEnd) + css_constants.TRACK_SHELL_WIDTH;
            ctx.fillStyle = '#ffe263';
            ctx.fillRect(Math.floor(rectStart), 0, Math.ceil(rectEnd - rectStart), size.height);
        }
        const index = globals$1.globals.frontendLocalState.searchIndex;
        const startSec = time.fromNs(globals$1.globals.currentSearchResults.tsStarts[index]);
        const triangleStart = Math.max(timeScale.timeToPx(startSec), 0) + css_constants.TRACK_SHELL_WIDTH;
        ctx.fillStyle = '#000';
        ctx.beginPath();
        ctx.moveTo(triangleStart, size.height);
        ctx.lineTo(triangleStart - 3, 0);
        ctx.lineTo(triangleStart + 3, 0);
        ctx.lineTo(triangleStart, size.height);
        ctx.fill();
        ctx.closePath();
    }
}
exports.TickmarkPanel = TickmarkPanel;

});

var time_axis_panel = createCommonjsModule(function (module, exports) {
// Copyright (C) 2018 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use size 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.
Object.defineProperty(exports, "__esModule", { value: true });
exports.TimeAxisPanel = void 0;






class TimeAxisPanel extends panel.Panel {
    view() {
        return mithril('.time-axis-panel');
    }
    renderCanvas(ctx, size) {
        const timeScale = globals$1.globals.frontendLocalState.timeScale;
        const range = globals$1.globals.frontendLocalState.visibleWindowTime;
        ctx.fillStyle = '#999';
        // Write trace offset time + line.
        ctx.font = '12px Roboto Condensed';
        ctx.textAlign = 'right';
        const offsetTime = time.timeToString(range.start - globals$1.globals.state.traceTime.startSec);
        ctx.fillText(offsetTime, css_constants.TRACK_SHELL_WIDTH - 6, 11);
        ctx.textAlign = 'left';
        const startTime = time.timeToString(globals$1.globals.state.traceTime.startSec);
        ctx.fillText(startTime + ' +', 6, 11);
        // Draw time axis.
        ctx.font = '10px Roboto Condensed';
        for (const [x, time$1] of gridline_helper.gridlines(size.width, range, timeScale)) {
            ctx.fillRect(x, 0, 1, size.height);
            ctx.fillText('+' + time.timeToString(time$1 - range.start), x + 5, 10);
        }
        ctx.fillRect(css_constants.TRACK_SHELL_WIDTH - 2, 0, 2, size.height);
    }
}
exports.TimeAxisPanel = TimeAxisPanel;

});

var time_selection_panel = createCommonjsModule(function (module, exports) {
// Copyright (C) 2019 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use size 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.
Object.defineProperty(exports, "__esModule", { value: true });
exports.TimeSelectionPanel = void 0;


const time_2 = time;




// Draws a vertical line with two horizontal tails at the left and right and
// a label in the middle. It looks a bit like a stretched H:
// |--- Label ---|
// The |target| bounding box determines where to draw the H.
// The |bounds| bounding box gives the visible region, this is used to adjust
// the positioning of the label to ensure it is on screen.
function drawHBar(ctx, target, bounds, label) {
    ctx.fillStyle = '#222';
    const xLeft = Math.floor(target.x);
    const xRight = Math.ceil(target.x + target.width);
    const yMid = Math.floor(target.height / 2 + target.y);
    const xWidth = xRight - xLeft;
    // Don't draw in the track shell.
    ctx.beginPath();
    ctx.rect(bounds.x, bounds.y, bounds.width, bounds.height);
    ctx.clip();
    // Draw horizontal bar of the H.
    ctx.fillRect(xLeft, yMid, xWidth, 1);
    // Draw left vertical bar of the H.
    ctx.fillRect(xLeft, target.y, 1, target.height);
    // Draw right vertical bar of the H.
    ctx.fillRect(xRight, target.y, 1, target.height);
    const labelWidth = ctx.measureText(label).width;
    // Find a good position for the label:
    // By default put the label in the middle of the H:
    let labelXLeft = Math.floor(xWidth / 2 - labelWidth / 2 + xLeft);
    if (labelWidth > target.width || labelXLeft < bounds.x ||
        (labelXLeft + labelWidth) > (bounds.x + bounds.width)) {
        // It won't fit in the middle or would be at least partly out of bounds
        // so put it either to the left or right:
        if (xRight > bounds.x + bounds.width) {
            // If the H extends off the right side of the screen the label
            // goes on the left of the H.
            labelXLeft = xLeft - labelWidth - 3;
        }
        else {
            // Otherwise the label goes on the right of the H.
            labelXLeft = xRight + 3;
        }
    }
    ctx.fillStyle = '#ffffff';
    ctx.fillRect(labelXLeft - 1, 0, labelWidth + 1, target.height);
    ctx.textBaseline = 'middle';
    ctx.fillStyle = '#222';
    ctx.font = '10px Roboto Condensed';
    ctx.fillText(label, labelXLeft, yMid);
}
function drawIBar(ctx, xPos, bounds, label) {
    if (xPos < bounds.x)
        return;
    ctx.fillStyle = '#222';
    ctx.fillRect(xPos, 0, 1, bounds.width);
    const yMid = Math.floor(bounds.height / 2 + bounds.y);
    const labelWidth = ctx.measureText(label).width;
    const padding = 3;
    let xPosLabel;
    if (xPos + padding + labelWidth > bounds.width) {
        xPosLabel = xPos - padding;
        ctx.textAlign = 'right';
    }
    else {
        xPosLabel = xPos + padding;
        ctx.textAlign = 'left';
    }
    ctx.fillStyle = '#ffffff';
    ctx.fillRect(xPosLabel - 1, 0, labelWidth + 2, bounds.height);
    ctx.textBaseline = 'middle';
    ctx.fillStyle = '#222';
    ctx.font = '10px Roboto Condensed';
    ctx.fillText(label, xPosLabel, yMid);
}
class TimeSelectionPanel extends panel.Panel {
    view() {
        return mithril('.time-selection-panel');
    }
    renderCanvas(ctx, size) {
        const range = globals$1.globals.frontendLocalState.visibleWindowTime;
        const timeScale = globals$1.globals.frontendLocalState.timeScale;
        ctx.fillStyle = '#999';
        ctx.fillRect(css_constants.TRACK_SHELL_WIDTH - 2, 0, 2, size.height);
        for (const xAndTime of gridline_helper.gridlines(size.width, range, timeScale)) {
            ctx.fillRect(xAndTime[0], 0, 1, size.height);
        }
        const localArea = globals$1.globals.frontendLocalState.selectedArea;
        const selection = globals$1.globals.state.currentSelection;
        if (localArea !== undefined) {
            const start = Math.min(localArea.startSec, localArea.endSec);
            const end = Math.max(localArea.startSec, localArea.endSec);
            this.renderSpan(ctx, size, new time_2.TimeSpan(start, end));
        }
        else if (selection !== null && selection.kind === 'AREA') {
            const selectedArea = globals$1.globals.state.areas[selection.areaId];
            const start = Math.min(selectedArea.startSec, selectedArea.endSec);
            const end = Math.max(selectedArea.startSec, selectedArea.endSec);
            this.renderSpan(ctx, size, new time_2.TimeSpan(start, end));
        }
        if (globals$1.globals.frontendLocalState.hoveredLogsTimestamp !== -1) {
            this.renderHover(ctx, size, globals$1.globals.frontendLocalState.hoveredLogsTimestamp);
        }
        for (const note of Object.values(globals$1.globals.state.notes)) {
            const noteIsSelected = selection !== null && selection.kind === 'AREA' &&
                selection.noteId === note.id;
            if (note.noteType === 'AREA' && !noteIsSelected) {
                const selectedArea = globals$1.globals.state.areas[note.areaId];
                this.renderSpan(ctx, size, new time_2.TimeSpan(selectedArea.startSec, selectedArea.endSec));
            }
        }
    }
    renderHover(ctx, size, ts) {
        const timeScale = globals$1.globals.frontendLocalState.timeScale;
        const xPos = css_constants.TRACK_SHELL_WIDTH + Math.floor(timeScale.timeToPx(ts));
        const offsetTime = time.timeToString(ts - globals$1.globals.state.traceTime.startSec);
        const timeFromStart = time.timeToString(ts);
        const label = `${offsetTime} (${timeFromStart})`;
        drawIBar(ctx, xPos, this.bounds(size), label);
    }
    renderSpan(ctx, size, span) {
        const timeScale = globals$1.globals.frontendLocalState.timeScale;
        const xLeft = timeScale.timeToPx(span.start);
        const xRight = timeScale.timeToPx(span.end);
        const label = time.timeToString(span.duration);
        drawHBar(ctx, {
            x: css_constants.TRACK_SHELL_WIDTH + xLeft,
            y: 0,
            width: xRight - xLeft,
            height: size.height
        }, this.bounds(size), label);
    }
    bounds(size) {
        return {
            x: css_constants.TRACK_SHELL_WIDTH,
            y: 0,
            width: size.width - css_constants.TRACK_SHELL_WIDTH,
            height: size.height
        };
    }
}
exports.TimeSelectionPanel = TimeSelectionPanel;

});

var video_panel = createCommonjsModule(function (module, exports) {
// Copyright (C) 2019 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.
Object.defineProperty(exports, "__esModule", { value: true });
exports.VideoPanel = void 0;




class VideoPanel {
    view() {
        const vidSections = [];
        const offset = globals$1.globals.state.traceTime.startSec + globals$1.globals.state.videoOffset;
        vidSections.push(mithril('video', {
            class: 'video-panel',
            controls: true,
            width: 320,
            currentTime: globals$1.globals.frontendLocalState.vidTimestamp - offset,
            onpause: (e) => {
                const elem = e.target;
                if (globals$1.globals.state.flagPauseEnabled && !(elem.ended)) {
                    const timestamp = elem.currentTime + offset;
                    const color = colorizer.randomColor();
                    const isMovie = true;
                    globals$1.globals.dispatch(actions.Actions.addNote({ timestamp, color, isMovie }));
                    elem.currentTime = timestamp - offset;
                    globals$1.globals.frontendLocalState.setVidTimestamp(timestamp);
                }
            },
            ontimeupdate: (e) => {
                const elem = e.target;
                if (globals$1.globals.state.scrubbingEnabled) {
                    elem.currentTime = globals$1.globals.frontendLocalState.vidTimestamp - offset;
                }
            },
        }, mithril('source', { src: globals$1.globals.state.video, type: 'video/mp4' })));
        const vidMessages = [];
        const pSetting = `Pause/Flag Synchronization: `;
        const pEnabled = `When you pause the video, a video flag ` +
            `will be drawn at this position. \n Also, adding a video flag by ` +
            `clicking on the notes panel (below the time axis) will move the video ` +
            `to this position.`;
        const pDisabled = `Press 'p' to enable.`;
        const tSetting = `Timeline Scrubbing: `;
        const tEnabled = `When you hover over the notes panel, the video will ` +
            `skip to the hovered timestamp.`;
        const tDisabled = `Press 't' to enable.`;
        function makeMsg(setting, msgType, e, d) {
            return mithril('h1', { class: `video-panel-${msgType}` }, setting ? e : d);
        }
        vidMessages.push(makeMsg(globals$1.globals.state.flagPauseEnabled, 'setting', pSetting.concat('Enabled'), pSetting.concat('Disabled')), makeMsg(globals$1.globals.state.flagPauseEnabled, 'message', pEnabled, pDisabled), makeMsg(globals$1.globals.state.scrubbingEnabled, 'setting', tSetting.concat('Enabled'), tSetting.concat('Disabled')), makeMsg(globals$1.globals.state.scrubbingEnabled, 'message', tEnabled, tDisabled));
        vidSections.push(vidMessages);
        return mithril('.video-panel', vidSections);
    }
}
exports.VideoPanel = VideoPanel;

});

var viewer_page = createCommonjsModule(function (module, exports) {
// 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.
Object.defineProperty(exports, "__esModule", { value: true });
exports.ViewerPage = void 0;



















const SIDEBAR_WIDTH = 256;
// Checks if the mousePos is within 3px of the start or end of the
// current selected time range.
function onTimeRangeBoundary(mousePos) {
    const selection = globals$1.globals.state.currentSelection;
    if (selection !== null && selection.kind === 'AREA') {
        // If frontend selectedArea exists then we are in the process of editing the
        // time range and need to use that value instead.
        const area = globals$1.globals.frontendLocalState.selectedArea ?
            globals$1.globals.frontendLocalState.selectedArea :
            globals$1.globals.state.areas[selection.areaId];
        const start = globals$1.globals.frontendLocalState.timeScale.timeToPx(area.startSec);
        const end = globals$1.globals.frontendLocalState.timeScale.timeToPx(area.endSec);
        const startDrag = mousePos - css_constants.TRACK_SHELL_WIDTH;
        const startDistance = Math.abs(start - startDrag);
        const endDistance = Math.abs(end - startDrag);
        const range = 3 * window.devicePixelRatio;
        // We might be within 3px of both boundaries but we should choose
        // the closest one.
        if (startDistance < range && startDistance <= endDistance)
            return 'START';
        if (endDistance < range && endDistance <= startDistance)
            return 'END';
    }
    return null;
}
/**
 * Top-most level component for the viewer page. Holds tracks, brush timeline,
 * panels, and everything else that's part of the main trace viewer page.
 */
class TraceViewer {
    constructor() {
        this.onResize = () => { };
        // Used to prevent global deselection if a pan/drag select occurred.
        this.keepCurrentSelection = false;
    }
    oncreate(vnode) {
        const frontendLocalState = globals$1.globals.frontendLocalState;
        const updateDimensions = () => {
            const rect = vnode.dom.getBoundingClientRect();
            frontendLocalState.updateLocalLimits(0, rect.width - css_constants.TRACK_SHELL_WIDTH -
                frontendLocalState.getScrollbarWidth());
        };
        updateDimensions();
        // TODO: Do resize handling better.
        this.onResize = () => {
            updateDimensions();
            globals$1.globals.rafScheduler.scheduleFullRedraw();
        };
        // Once ResizeObservers are out, we can stop accessing the window here.
        window.addEventListener('resize', this.onResize);
        const panZoomEl = vnode.dom.querySelector('.pan-and-zoom-content');
        this.zoomContent = new pan_and_zoom_handler.PanAndZoomHandler({
            element: panZoomEl,
            contentOffsetX: SIDEBAR_WIDTH,
            onPanned: (pannedPx) => {
                this.keepCurrentSelection = true;
                const traceTime = globals$1.globals.state.traceTime;
                const vizTime = globals$1.globals.frontendLocalState.visibleWindowTime;
                const origDelta = vizTime.duration;
                const tDelta = frontendLocalState.timeScale.deltaPxToDuration(pannedPx);
                let tStart = vizTime.start + tDelta;
                let tEnd = vizTime.end + tDelta;
                if (tStart < traceTime.startSec) {
                    tStart = traceTime.startSec;
                    tEnd = tStart + origDelta;
                }
                else if (tEnd > traceTime.endSec) {
                    tEnd = traceTime.endSec;
                    tStart = tEnd - origDelta;
                }
                frontendLocalState.updateVisibleTime(new time.TimeSpan(tStart, tEnd));
                // If the user has panned they no longer need the hint.
                localStorage.setItem(topbar.DISMISSED_PANNING_HINT_KEY, 'true');
                globals$1.globals.rafScheduler.scheduleRedraw();
            },
            onZoomed: (zoomedPositionPx, zoomRatio) => {
                // TODO(hjd): Avoid hardcoding TRACK_SHELL_WIDTH.
                // TODO(hjd): Improve support for zooming in overview timeline.
                const span = frontendLocalState.visibleWindowTime;
                const scale = frontendLocalState.timeScale;
                const zoomPx = zoomedPositionPx - css_constants.TRACK_SHELL_WIDTH;
                const newSpan = time_scale.computeZoom(scale, span, 1 - zoomRatio, zoomPx);
                frontendLocalState.updateVisibleTime(newSpan);
                globals$1.globals.rafScheduler.scheduleRedraw();
            },
            editSelection: (currentPx) => {
                return onTimeRangeBoundary(currentPx) !== null;
            },
            onSelection: (dragStartX, dragStartY, prevX, currentX, currentY, editing) => {
                const traceTime = globals$1.globals.state.traceTime;
                const scale = frontendLocalState.timeScale;
                this.keepCurrentSelection = true;
                if (editing) {
                    const selection = globals$1.globals.state.currentSelection;
                    if (selection !== null && selection.kind === 'AREA') {
                        const area = globals$1.globals.frontendLocalState.selectedArea ?
                            globals$1.globals.frontendLocalState.selectedArea :
                            globals$1.globals.state.areas[selection.areaId];
                        let newTime = scale.pxToTime(currentX - css_constants.TRACK_SHELL_WIDTH);
                        // Have to check again for when one boundary crosses over the other.
                        const curBoundary = onTimeRangeBoundary(prevX);
                        if (curBoundary == null)
                            return;
                        const keepTime = curBoundary === 'START' ? area.endSec : area.startSec;
                        // Don't drag selection outside of current screen.
                        if (newTime < keepTime) {
                            newTime = Math.max(newTime, scale.pxToTime(scale.startPx));
                        }
                        else {
                            newTime = Math.min(newTime, scale.pxToTime(scale.endPx));
                        }
                        // When editing the time range we always use the saved tracks,
                        // since these will not change.
                        frontendLocalState.selectArea(Math.max(Math.min(keepTime, newTime), traceTime.startSec), Math.min(Math.max(keepTime, newTime), traceTime.endSec), globals$1.globals.state.areas[selection.areaId].tracks);
                    }
                }
                else {
                    let startPx = Math.min(dragStartX, currentX) - css_constants.TRACK_SHELL_WIDTH;
                    let endPx = Math.max(dragStartX, currentX) - css_constants.TRACK_SHELL_WIDTH;
                    if (startPx < 0 && endPx < 0)
                        return;
                    startPx = Math.max(startPx, scale.startPx);
                    endPx = Math.min(endPx, scale.endPx);
                    frontendLocalState.selectArea(scale.pxToTime(startPx), scale.pxToTime(endPx));
                    frontendLocalState.areaY.start = dragStartY;
                    frontendLocalState.areaY.end = currentY;
                }
                globals$1.globals.rafScheduler.scheduleRedraw();
            },
            endSelection: (edit) => {
                globals$1.globals.frontendLocalState.areaY.start = undefined;
                globals$1.globals.frontendLocalState.areaY.end = undefined;
                const area = globals$1.globals.frontendLocalState.selectedArea;
                // If we are editing we need to pass the current id through to ensure
                // the marked area with that id is also updated.
                if (edit) {
                    const selection = globals$1.globals.state.currentSelection;
                    if (selection !== null && selection.kind === 'AREA' && area) {
                        globals$1.globals.dispatch(actions.Actions.editArea({ area, areaId: selection.areaId }));
                    }
                }
                else if (area) {
                    globals$1.globals.makeSelection(actions.Actions.selectArea({ area }));
                }
                // Now the selection has ended we stored the final selected area in the
                // global state and can remove the in progress selection from the
                // frontendLocalState.
                globals$1.globals.frontendLocalState.deselectArea();
                // Full redraw to color track shell.
                globals$1.globals.rafScheduler.scheduleFullRedraw();
            }
        });
    }
    onremove() {
        window.removeEventListener('resize', this.onResize);
        if (this.zoomContent)
            this.zoomContent.shutdown();
    }
    view() {
        const scrollingPanels = globals$1.globals.state.scrollingTracks.map(id => mithril(track_panel.TrackPanel, { key: id, id, selectable: true }));
        for (const group of Object.values(globals$1.globals.state.trackGroups)) {
            scrollingPanels.push(mithril(track_group_panel.TrackGroupPanel, {
                trackGroupId: group.id,
                key: `trackgroup-${group.id}`,
                selectable: true,
            }));
            if (group.collapsed)
                continue;
            // The first track is the summary track, and is displayed as part of the
            // group panel, we don't want to display it twice so we start from 1.
            for (let i = 1; i < group.tracks.length; ++i) {
                const id = group.tracks[i];
                scrollingPanels.push(mithril(track_panel.TrackPanel, {
                    key: `track-${group.id}-${id}`,
                    id,
                    selectable: true,
                }));
            }
        }
        return mithril('.page', mithril('.split-panel', mithril('.pan-and-zoom-content', {
            onclick: () => {
                // We don't want to deselect when panning/drag selecting.
                if (this.keepCurrentSelection) {
                    this.keepCurrentSelection = false;
                    return;
                }
                globals$1.globals.makeSelection(actions.Actions.deselect({}));
            }
        }, mithril('.pinned-panel-container', mithril(panel_container.PanelContainer, {
            doesScroll: false,
            panels: [
                mithril(overview_timeline_panel.OverviewTimelinePanel, { key: 'overview' }),
                mithril(time_axis_panel.TimeAxisPanel, { key: 'timeaxis' }),
                mithril(time_selection_panel.TimeSelectionPanel, { key: 'timeselection' }),
                mithril(notes_panel.NotesPanel, { key: 'notes' }),
                mithril(tickmark_panel.TickmarkPanel, { key: 'searchTickmarks' }),
                ...globals$1.globals.state.pinnedTracks.map(id => mithril(track_panel.TrackPanel, { key: id, id, selectable: true })),
            ],
            kind: 'OVERVIEW',
        })), mithril('.scrolling-panel-container', mithril(panel_container.PanelContainer, {
            doesScroll: true,
            panels: scrollingPanels,
            kind: 'TRACKS',
        }))), mithril('.video-panel', (globals$1.globals.state.videoEnabled && globals$1.globals.state.video != null) ?
            mithril(video_panel.VideoPanel) :
            null)), mithril(details_panel.DetailsPanel));
    }
}
exports.ViewerPage = pages.createPage({
    view() {
        return mithril(TraceViewer);
    }
});

});

var profile_page = createCommonjsModule(function (module, exports) {
// Copyright (C) 2020 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.
Object.defineProperty(exports, "__esModule", { value: true });
exports.ProfilePage = void 0;





/**
 * Profile page for flamegraphs
 */
class ProfileViewer {
    constructor() {
        this.onResize = () => { };
    }
    oncreate(vnode) {
        const frontendLocalState = globals$1.globals.frontendLocalState;
        const updateDimensions = () => {
            const rect = vnode.dom.getBoundingClientRect();
            frontendLocalState.updateLocalLimits(0, rect.width - css_constants.TRACK_SHELL_WIDTH -
                frontendLocalState.getScrollbarWidth());
        };
        updateDimensions();
        // TODO: Do resize handling better.
        this.onResize = () => {
            updateDimensions();
            globals$1.globals.rafScheduler.scheduleFullRedraw();
        };
        // Once ResizeObservers are out, we can stop accessing the window here.
        window.addEventListener('resize', this.onResize);
    }
    view() {
        return mithril('.page', mithril(details_panel.DetailsPanel));
    }
}
exports.ProfilePage = pages.createPage({
    view() {
        return mithril(ProfileViewer);
    }
});

});

var frontend$1 = createCommonjsModule(function (module, exports) {
// 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.
Object.defineProperty(exports, "__esModule", { value: true });


























const EXTENSION_ID = 'lfmkphfpdbjijhpomgecfikhfohaoine';
function isLocalhostTraceUrl(url) {
    return ['127.0.0.1', 'localhost'].includes((new URL(url)).hostname);
}
/**
 * The API the main thread exposes to the controller.
 */
class FrontendApi {
    constructor(router) {
        this.router = router;
    }
    patchState(patches) {
        const oldState = globals$1.globals.state;
        globals$1.globals.state = immer_1.applyPatches(globals$1.globals.state, patches);
        // If the visible time in the global state has been updated more recently
        // than the visible time handled by the frontend @ 60fps, update it. This
        // typically happens when restoring the state from a permalink.
        globals$1.globals.frontendLocalState.mergeState(globals$1.globals.state.frontendLocalState);
        // Only redraw if something other than the frontendLocalState changed.
        for (const key in globals$1.globals.state) {
            if (key !== 'frontendLocalState' && key !== 'visibleTracks' &&
                oldState[key] !== globals$1.globals.state[key]) {
                this.redraw();
                return;
            }
        }
    }
    // TODO: we can't have a publish method for each batch of data that we don't
    // want to keep in the global state. Figure out a more generic and type-safe
    // mechanism to achieve this.
    publishOverviewData(data) {
        for (const [key, value] of Object.entries(data)) {
            if (!globals$1.globals.overviewStore.has(key)) {
                globals$1.globals.overviewStore.set(key, []);
            }
            if (value instanceof Array) {
                globals$1.globals.overviewStore.get(key).push(...value);
            }
            else {
                globals$1.globals.overviewStore.get(key).push(value);
            }
        }
        globals$1.globals.rafScheduler.scheduleRedraw();
    }
    publishTrackData(args) {
        globals$1.globals.setTrackData(args.id, args.data);
        if ([logs.LogExistsKey, logs.LogBoundsKey, logs.LogEntriesKey].includes(args.id)) {
            const data = globals$1.globals.trackDataStore.get(logs.LogExistsKey);
            if (data && data.exists)
                globals$1.globals.rafScheduler.scheduleFullRedraw();
        }
        else {
            globals$1.globals.rafScheduler.scheduleRedraw();
        }
    }
    publishQueryResult(args) {
        globals$1.globals.queryResults.set(args.id, args.data);
        this.redraw();
    }
    publishThreads(data) {
        globals$1.globals.threads.clear();
        data.forEach(thread => {
            globals$1.globals.threads.set(thread.utid, thread);
        });
        this.redraw();
    }
    publishSliceDetails(click) {
        globals$1.globals.sliceDetails = click;
        this.redraw();
    }
    publishThreadStateDetails(click) {
        globals$1.globals.threadStateDetails = click;
        this.redraw();
    }
    publishConnectedFlows(connectedFlows) {
        globals$1.globals.connectedFlows = connectedFlows;
        // Call resetFlowFocus() each time connectedFlows is updated to correctly
        // navigate using hotkeys.
        this.resetFlowFocus();
        this.redraw();
    }
    // If a chrome slice is selected and we have any flows in connectedFlows
    // we will find the flows on the right and left of that slice to set a default
    // focus. In all other cases the focusedFlowId(Left|Right) will be set to -1.
    resetFlowFocus() {
        var _a;
        globals$1.globals.frontendLocalState.focusedFlowIdLeft = -1;
        globals$1.globals.frontendLocalState.focusedFlowIdRight = -1;
        if (((_a = globals$1.globals.state.currentSelection) === null || _a === void 0 ? void 0 : _a.kind) === 'CHROME_SLICE') {
            const sliceId = globals$1.globals.state.currentSelection.id;
            for (const flow of globals$1.globals.connectedFlows) {
                if (flow.begin.sliceId === sliceId) {
                    globals$1.globals.frontendLocalState.focusedFlowIdRight = flow.id;
                }
                if (flow.end.sliceId === sliceId) {
                    globals$1.globals.frontendLocalState.focusedFlowIdLeft = flow.id;
                }
            }
        }
    }
    publishSelectedFlows(selectedFlows) {
        globals$1.globals.selectedFlows = selectedFlows;
        this.redraw();
    }
    publishCounterDetails(click) {
        globals$1.globals.counterDetails = click;
        this.redraw();
    }
    publishHeapProfileDetails(click) {
        globals$1.globals.heapProfileDetails = click;
        this.redraw();
    }
    publishCpuProfileDetails(details) {
        globals$1.globals.cpuProfileDetails = details;
        this.redraw();
    }
    publishHasFtrace(hasFtrace) {
        globals$1.globals.hasFtrace = hasFtrace;
        this.redraw();
    }
    publishConversionJobStatusUpdate(job) {
        globals$1.globals.setConversionJobStatus(job.jobName, job.jobStatus);
        this.redraw();
    }
    publishFileDownload(args) {
        const url = URL.createObjectURL(args.file);
        const a = document.createElement('a');
        a.href = url;
        a.download = args.name !== undefined ? args.name : args.file.name;
        document.body.appendChild(a);
        a.click();
        document.body.removeChild(a);
        URL.revokeObjectURL(url);
    }
    publishLoading(numQueuedQueries) {
        globals$1.globals.numQueuedQueries = numQueuedQueries;
        // TODO(hjd): Clean up loadingAnimation given that this now causes a full
        // redraw anyways. Also this should probably just go via the global state.
        globals$1.globals.rafScheduler.scheduleFullRedraw();
    }
    // For opening JSON/HTML traces with the legacy catapult viewer.
    publishLegacyTrace(args) {
        const arr = new Uint8Array(args.data, 0, args.size);
        const str = (new TextDecoder('utf-8')).decode(arr);
        legacy_trace_viewer.openBufferWithLegacyTraceViewer('trace.json', str, 0);
    }
    publishBufferUsage(args) {
        globals$1.globals.setBufferUsage(args.percentage);
        this.redraw();
    }
    publishSearch(args) {
        globals$1.globals.searchSummary = args;
        this.redraw();
    }
    publishSearchResult(args) {
        globals$1.globals.currentSearchResults = args;
        this.redraw();
    }
    publishRecordingLog(args) {
        globals$1.globals.setRecordingLog(args.logs);
        this.redraw();
    }
    publishTraceErrors(numErrors) {
        globals$1.globals.setTraceErrors(numErrors);
        this.redraw();
    }
    publishMetricError(error) {
        globals$1.globals.setMetricError(error);
        globals$1.globals.logging.logError(error, false);
        this.redraw();
    }
    publishMetricResult(metricResult) {
        globals$1.globals.setMetricResult(metricResult);
        this.redraw();
    }
    publishAggregateData(args) {
        globals$1.globals.setAggregateData(args.kind, args.data);
        this.redraw();
    }
    redraw() {
        if (globals$1.globals.state.route &&
            globals$1.globals.state.route !== this.router.getRouteFromHash()) {
            this.router.setRouteOnHash(globals$1.globals.state.route);
        }
        globals$1.globals.rafScheduler.scheduleFullRedraw();
    }
}
function setExtensionAvailability(available) {
    globals$1.globals.dispatch(actions.Actions.setExtensionAvailable({
        available,
    }));
}
function setupContentSecurityPolicy() {
    // Note: self and sha-xxx must be quoted, urls data: and blob: must not.
    const policy = {
        'default-src': [
            `'self'`,
            // Google Tag Manager bootstrap.
            `'sha256-LirUKeorCU4uRNtNzr8tlB11uy8rzrdmqHCX38JSwHY='`,
        ],
        'script-src': [
            `'self'`,
            'https://*.google.com',
            'https://*.googleusercontent.com',
            'https://www.googletagmanager.com',
            'https://www.google-analytics.com',
        ],
        'object-src': ['none'],
        'connect-src': [
            `'self'`,
            'http://127.0.0.1:9001',
            'https://www.google-analytics.com',
            'https://*.googleapis.com',
            'blob:',
            'data:',
        ],
        'img-src': [
            `'self'`,
            'data:',
            'blob:',
            'https://www.google-analytics.com',
            'https://www.googletagmanager.com',
        ],
        'navigate-to': ['https://*.perfetto.dev', 'self'],
    };
    const meta = document.createElement('meta');
    meta.httpEquiv = 'Content-Security-Policy';
    let policyStr = '';
    for (const [key, list] of Object.entries(policy)) {
        policyStr += `${key} ${list.join(' ')}; `;
    }
    meta.content = policyStr;
    document.head.appendChild(meta);
}
function main() {
    setupContentSecurityPolicy();
    // Load the css. The load is asynchronous and the CSS is not ready by the time
    // appenChild returns.
    const cssLoadPromise = deferred.defer();
    const css = document.createElement('link');
    css.rel = 'stylesheet';
    css.href = globals$1.globals.root + 'perfetto.css';
    css.onload = () => cssLoadPromise.resolve();
    css.onerror = (err) => cssLoadPromise.reject(err);
    const favicon = document.head.querySelector('#favicon');
    if (favicon)
        favicon.href = globals$1.globals.root + 'assets/favicon.png';
    // Load the script to detect if this is a Googler (see comments on globals.ts)
    // and initialize GA after that (or after a timeout if something goes wrong).
    const script = document.createElement('script');
    script.src =
        'https://storage.cloud.google.com/perfetto-ui-internal/is_internal_user.js';
    script.async = true;
    script.onerror = () => globals$1.globals.logging.initialize();
    script.onload = () => globals$1.globals.logging.initialize();
    setTimeout(() => globals$1.globals.logging.initialize(), 5000);
    document.head.append(script, css);
    // Add Error handlers for JS error and for uncaught exceptions in promises.
    logging.setErrorHandler((err) => error_dialog.maybeShowErrorDialog(err));
    window.addEventListener('error', e => logging.reportError(e));
    window.addEventListener('unhandledrejection', e => logging.reportError(e));
    const controller = new Worker(globals$1.globals.root + 'controller_bundle.js');
    const frontendChannel = new MessageChannel();
    const controllerChannel = new MessageChannel();
    const extensionLocalChannel = new MessageChannel();
    const errorReportingChannel = new MessageChannel();
    errorReportingChannel.port2.onmessage = (e) => error_dialog.maybeShowErrorDialog(`${e.data}`);
    controller.postMessage({
        frontendPort: frontendChannel.port1,
        controllerPort: controllerChannel.port1,
        extensionPort: extensionLocalChannel.port1,
        errorReportingPort: errorReportingChannel.port1,
    }, [
        frontendChannel.port1,
        controllerChannel.port1,
        extensionLocalChannel.port1,
        errorReportingChannel.port1,
    ]);
    const dispatch = controllerChannel.port2.postMessage.bind(controllerChannel.port2);
    globals$1.globals.initialize(dispatch, controller);
    globals$1.globals.serviceWorkerController.install();
    const router = new router$1.Router('/', {
        '/': home_page.HomePage,
        '/viewer': viewer_page.ViewerPage,
        '/record': record_page.RecordPage,
        '/query': analyze_page.AnalyzePage,
        '/metrics': metrics_page.MetricsPage,
        '/info': trace_info_page.TraceInfoPage,
        '/profile': profile_page.ProfilePage,
    }, dispatch, globals$1.globals.logging);
    remote.forwardRemoteCalls(frontendChannel.port2, new FrontendApi(router));
    // We proxy messages between the extension and the controller because the
    // controller's worker can't access chrome.runtime.
    const extensionPort = window.chrome && chrome.runtime ?
        chrome.runtime.connect(EXTENSION_ID) :
        undefined;
    setExtensionAvailability(extensionPort !== undefined);
    if (extensionPort) {
        extensionPort.onDisconnect.addListener(_ => {
            setExtensionAvailability(false);
            // tslint:disable-next-line: no-unused-expression
            void chrome.runtime.lastError; // Needed to not receive an error log.
        });
        // This forwards the messages from the extension to the controller.
        extensionPort.onMessage.addListener((message, _port) => {
            extensionLocalChannel.port2.postMessage(message);
        });
    }
    // This forwards the messages from the controller to the extension
    extensionLocalChannel.port2.onmessage = ({ data }) => {
        if (extensionPort)
            extensionPort.postMessage(data);
    };
    // Put these variables in the global scope for better debugging.
    window.m = mithril;
    window.globals = globals$1.globals;
    window.Actions = actions.Actions;
    // Prevent pinch zoom.
    document.body.addEventListener('wheel', (e) => {
        if (e.ctrlKey)
            e.preventDefault();
    }, { passive: false });
    cssLoadPromise.then(() => onCssLoaded(router));
}
function onCssLoaded(router) {
    css_constants.initCssConstants();
    // Clear all the contents of the initial page (e.g. the <pre> error message)
    // And replace it with the root <main> element which will be used by mithril.
    document.body.innerHTML = '<main></main>';
    const main = logging.assertExists(document.body.querySelector('main'));
    globals$1.globals.rafScheduler.domRedraw = () => mithril.render(main, mithril(router.resolve(globals$1.globals.state.route)));
    router.navigateToCurrentHash();
    // /?s=xxxx for permalinks.
    const stateHash = router$1.Router.param('s');
    const urlHash = router$1.Router.param('url');
    const androidBugTool = router$1.Router.param('openFromAndroidBugTool');
    if (typeof stateHash === 'string' && stateHash) {
        globals$1.globals.dispatch(actions.Actions.loadPermalink({
            hash: stateHash,
        }));
    }
    else if (typeof urlHash === 'string' && urlHash) {
        if (isLocalhostTraceUrl(urlHash)) {
            const fileName = urlHash.split('/').pop() || 'local_trace.pftrace';
            const request = fetch(urlHash)
                .then(response => response.blob())
                .then(blob => {
                globals$1.globals.dispatch(actions.Actions.openTraceFromFile({
                    file: new File([blob], fileName),
                }));
            })
                .catch(e => alert(`Could not load local trace ${e}`));
            task_tracker.taskTracker.trackPromise(request, 'Downloading local trace');
        }
        else {
            globals$1.globals.dispatch(actions.Actions.openTraceFromUrl({
                url: urlHash,
            }));
        }
    }
    else if (androidBugTool) {
        // TODO(hjd): Unify updateStatus and TaskTracker
        globals$1.globals.dispatch(actions.Actions.updateStatus({
            msg: 'Loading trace from ABT extension',
            timestamp: Date.now() / 1000
        }));
        const loadInfo = android_bug_tool.loadAndroidBugToolInfo();
        task_tracker.taskTracker.trackPromise(loadInfo, 'Loading trace from ABT extension');
        loadInfo
            .then(info => {
            globals$1.globals.dispatch(actions.Actions.openTraceFromFile({
                file: info.file,
            }));
        })
            .catch(e => {
            console.error(e);
        });
    }
    else {
        // This is for VizTracer use only!
        fetch("http://127.0.0.1:9001/vizviewer_info")
            .then(data => {
            return data.json();
        })
            .then(res => {
            if (res.is_flamegraph) {
                fetch("http://127.0.0.1:9001/flamegraph")
                    .then(data => {
                    return data.json();
                })
                    .then(res => {
                    globals$1.globals.functionProfileDetails = res;
                    globals$1.globals.dispatch(actions.Actions.navigate({ route: "/profile" }));
                });
            }
            else {
                // Try to load the function map
                fetch("http://127.0.0.1:9001/file_info")
                    .then(data => {
                    return data.json();
                })
                    .then(res => {
                    globals$1.globals.sourceFileStorage = res;
                    globals$1.globals.state.currentSelection = {
                        kind: 'FUNCTION_PROFILE',
                        id: 1234567
                    };
                    // To make it auto-load the trace, we try to load localtrace
                    globals$1.globals.dispatch(actions.Actions.openTraceFromUrl({
                        url: 'http://127.0.0.1:9001/localtrace',
                    }));
                })
                    .catch(error => {
                    console.log(error);
                });
            }
        });
    }
    // Add support for opening traces from postMessage().
    window.addEventListener('message', post_message_handler.postMessageHandler, { passive: true });
    // Will update the chip on the sidebar footer that notifies that the RPC is
    // connected. Has no effect on the controller (which will repeat this check
    // before creating a new engine).
    rpc_http_dialog.CheckHttpRpcConnection();
    live_reload.initLiveReloadIfLocalhost();
    record_page.updateAvailableAdbDevices();
    try {
        navigator.usb.addEventListener('connect', () => record_page.updateAvailableAdbDevices());
        navigator.usb.addEventListener('disconnect', () => record_page.updateAvailableAdbDevices());
    }
    catch (e) {
        console.error('WebUSB API not supported');
    }
    file_drop_handler.installFileDropHandler();
}
main();

});

return frontend$1;

}());
//# sourceMappingURL=frontend_bundle.js.map
