161fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian/*
261fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian * Copyright (C) 2016 The Android Open Source Project
361fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian *
461fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian * Licensed under the Apache License, Version 2.0 (the "License");
561fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian * you may not use this file except in compliance with the License.
661fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian * You may obtain a copy of the License at
761fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian *
861fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian *      http://www.apache.org/licenses/LICENSE-2.0
961fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian *
1061fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian * Unless required by applicable law or agreed to in writing, software
1161fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian * distributed under the License is distributed on an "AS IS" BASIS,
1261fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1361fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian * See the License for the specific language governing permissions and
1461fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian * limitations under the License.
1561fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian */
1661fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian
1761fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian#include "Profiler.h"
1861fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian
1961fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian#include <stdlib.h>
2061fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian#include <string.h>
2161fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian#include <unistd.h>
2261fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian
2361fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian#include <algorithm>
2461fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian#include <iostream>
2561fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian
2661fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian#if defined(__linux__)
2761fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian
2861fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian#include <sys/syscall.h>
2961fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian
3061fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian#ifdef __ARM_ARCH
3161fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian    enum ARMv8PmuPerfTypes{
3261fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian        // Common micro-architecture events
3361fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian        ARMV8_PMUV3_PERFCTR_L1_ICACHE_REFILL    = 0x01,
3461fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian        ARMV8_PMUV3_PERFCTR_L1_ICACHE_ACCESS    = 0x14,
3561fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian        ARMV8_PMUV3_PERFCTR_L2_CACHE_ACCESS     = 0x16,
3661fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian        ARMV8_PMUV3_PERFCTR_L2_CACHE_REFILL     = 0x17,
3761fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian        ARMV8_PMUV3_PERFCTR_L2_CACHE_WB         = 0x18,
3861fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian    };
3961fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian#endif
4061fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian
4161fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopianstatic int perf_event_open(struct perf_event_attr* hw_event, pid_t pid,
4261fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian        int cpu, int group_fd, unsigned long flags) {
4361fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian    return syscall(__NR_perf_event_open, hw_event, pid, cpu, group_fd, flags);
4461fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian}
4561fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian
4661fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian#endif // __linux__
4761fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian
4861fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopiannamespace utils {
4961fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian
5061fd2ab615ab17f6de593e8a8cf475465967ac9cMathias AgopianProfiler& Profiler::get() noexcept {
5161fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian    static Profiler sProfiler;
5261fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian    return sProfiler;
5361fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian}
5461fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian
5561fd2ab615ab17f6de593e8a8cf475465967ac9cMathias AgopianProfiler::Profiler() noexcept {
5661fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian    std::uninitialized_fill(mCountersFd.begin(), mCountersFd.end(), -1);
5761fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian    Profiler::resetEvents(EV_CPU_CYCLES | EV_L1D_RATES | EV_BPU_RATES);
5861fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian}
5961fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian
6061fd2ab615ab17f6de593e8a8cf475465967ac9cMathias AgopianProfiler::~Profiler() noexcept {
6161fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian    for (int fd : mCountersFd) {
6261fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian        if (fd >= 0) {
6361fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian            close(fd);
6461fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian        }
6561fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian    }
6661fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian}
6761fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian
6861fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopianuint32_t Profiler::resetEvents(uint32_t eventMask) noexcept {
6961fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian    // close all counters
7061fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian    for (int& fd : mCountersFd) {
7161fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian        if (fd >= 0) {
7261fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian            close(fd);
7361fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian            fd = -1;
7461fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian        }
7561fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian    }
7661fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian    mEnabledEvents = 0;
7761fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian
7861fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian#if defined(__linux__)
7961fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian
8061fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian    struct perf_event_attr pe;
8161fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian    memset(&pe, 0, sizeof(struct perf_event_attr));
8261fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian    pe.type = PERF_TYPE_HARDWARE;
8361fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian    pe.size = sizeof(struct perf_event_attr);
8461fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian    pe.config = PERF_COUNT_HW_INSTRUCTIONS;
8561fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian    pe.disabled = 1;
8661fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian    pe.exclude_kernel = 1;
8761fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian    pe.exclude_hv = 1;
8861fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian    pe.read_format = PERF_FORMAT_GROUP |
8961fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian                     PERF_FORMAT_ID |
9061fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian                     PERF_FORMAT_TOTAL_TIME_ENABLED |
9161fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian                     PERF_FORMAT_TOTAL_TIME_RUNNING;
9261fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian
9361fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian    uint8_t count = 0;
9461fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian    int fd = perf_event_open(&pe, 0, -1, -1, 0);
9561fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian    if (fd >= 0) {
9661fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian        const int groupFd = fd;
9761fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian        mIds[INSTRUCTIONS] = count++;
9861fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian        mCountersFd[INSTRUCTIONS] = fd;
9961fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian
10061fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian        pe.read_format = PERF_FORMAT_GROUP | PERF_FORMAT_ID;
10161fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian
10261fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian        if (eventMask & EV_CPU_CYCLES) {
10361fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian            pe.type = PERF_TYPE_HARDWARE;
10461fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian            pe.config = PERF_COUNT_HW_CPU_CYCLES;
10561fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian            mCountersFd[CPU_CYCLES] = perf_event_open(&pe, 0, -1, groupFd, 0);
10661fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian            if (mCountersFd[CPU_CYCLES] > 0) {
10761fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian                mIds[CPU_CYCLES] = count++;
10861fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian                mEnabledEvents |= EV_CPU_CYCLES;
10961fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian            }
11061fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian        }
11161fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian
11261fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian        if (eventMask & EV_L1D_REFS) {
11361fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian            pe.type = PERF_TYPE_HARDWARE;
11461fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian            pe.config = PERF_COUNT_HW_CACHE_REFERENCES;
11561fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian            mCountersFd[DCACHE_REFS] = perf_event_open(&pe, 0, -1, groupFd, 0);
11661fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian            if (mCountersFd[DCACHE_REFS] > 0) {
11761fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian                mIds[DCACHE_REFS] = count++;
11861fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian                mEnabledEvents |= EV_L1D_REFS;
11961fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian            }
12061fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian        }
12161fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian
12261fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian        if (eventMask & EV_L1D_MISSES) {
12361fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian            pe.type = PERF_TYPE_HARDWARE;
12461fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian            pe.config = PERF_COUNT_HW_CACHE_MISSES;
12561fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian            mCountersFd[DCACHE_MISSES] = perf_event_open(&pe, 0, -1, groupFd, 0);
12661fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian            if (mCountersFd[DCACHE_MISSES] > 0) {
12761fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian                mIds[DCACHE_MISSES] = count++;
12861fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian                mEnabledEvents |= EV_L1D_MISSES;
12961fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian            }
13061fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian        }
13161fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian
13261fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian        if (eventMask & EV_BPU_REFS) {
13361fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian            pe.type = PERF_TYPE_HARDWARE;
13461fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian            pe.config = PERF_COUNT_HW_BRANCH_INSTRUCTIONS;
13561fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian            mCountersFd[BRANCHES] = perf_event_open(&pe, 0, -1, groupFd, 0);
13661fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian            if (mCountersFd[BRANCHES] > 0) {
13761fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian                mIds[BRANCHES] = count++;
13861fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian                mEnabledEvents |= EV_BPU_REFS;
13961fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian            }
14061fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian        }
14161fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian
14261fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian        if (eventMask & EV_BPU_MISSES) {
14361fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian            pe.type = PERF_TYPE_HARDWARE;
14461fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian            pe.config = PERF_COUNT_HW_BRANCH_MISSES;
14561fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian            mCountersFd[BRANCH_MISSES] = perf_event_open(&pe, 0, -1, groupFd, 0);
14661fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian            if (mCountersFd[BRANCH_MISSES] > 0) {
14761fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian                mIds[BRANCH_MISSES] = count++;
14861fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian                mEnabledEvents |= EV_BPU_MISSES;
14961fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian            }
15061fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian        }
15161fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian
15261fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian#ifdef __ARM_ARCH
15361fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian        if (eventMask & EV_L1I_REFS) {
15461fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian            pe.type = PERF_TYPE_RAW;
15561fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian            pe.config = ARMV8_PMUV3_PERFCTR_L1_ICACHE_ACCESS;
15661fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian            mCountersFd[ICACHE_REFS] = perf_event_open(&pe, 0, -1, groupFd, 0);
15761fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian            if (mCountersFd[ICACHE_REFS] > 0) {
15861fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian                mIds[ICACHE_REFS] = count++;
15961fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian                mEnabledEvents |= EV_L1I_REFS;
16061fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian            }
16161fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian        }
16261fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian
16361fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian        if (eventMask & EV_L1I_MISSES) {
16461fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian            pe.type = PERF_TYPE_RAW;
16561fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian            pe.config = ARMV8_PMUV3_PERFCTR_L1_ICACHE_REFILL;
16661fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian            mCountersFd[ICACHE_MISSES] = perf_event_open(&pe, 0, -1, groupFd, 0);
16761fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian            if (mCountersFd[ICACHE_MISSES] > 0) {
16861fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian                mIds[ICACHE_MISSES] = count++;
16961fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian                mEnabledEvents |= EV_L1I_MISSES;
17061fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian            }
17161fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian        }
17261fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian#else
17361fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian        if (eventMask & EV_L1I_REFS) {
17461fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian            pe.type = PERF_TYPE_HW_CACHE;
17561fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian            pe.config = PERF_COUNT_HW_CACHE_L1I |
17661fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian                (PERF_COUNT_HW_CACHE_OP_READ<<8) | (PERF_COUNT_HW_CACHE_RESULT_ACCESS<<16);
17761fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian            mCountersFd[ICACHE_REFS] = perf_event_open(&pe, 0, -1, groupFd, 0);
17861fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian            if (mCountersFd[ICACHE_REFS] > 0) {
17961fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian                mIds[ICACHE_REFS] = count++;
18061fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian                mEnabledEvents |= EV_L1I_REFS;
18161fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian            }
18261fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian        }
18361fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian
18461fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian        if (eventMask & EV_L1I_MISSES) {
18561fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian            pe.type = PERF_TYPE_HW_CACHE;
18661fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian            pe.config = PERF_COUNT_HW_CACHE_L1I |
18761fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian                (PERF_COUNT_HW_CACHE_OP_READ<<8) | (PERF_COUNT_HW_CACHE_RESULT_MISS<<16);
18861fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian            mCountersFd[ICACHE_MISSES] = perf_event_open(&pe, 0, -1, groupFd, 0);
18961fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian            if (mCountersFd[ICACHE_MISSES] > 0) {
19061fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian                mIds[ICACHE_MISSES] = count++;
19161fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian                mEnabledEvents |= EV_L1I_MISSES;
19261fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian            }
19361fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian        }
19461fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian#endif
19561fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian    }
19661fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian#endif // __linux__
19761fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian    return mEnabledEvents;
19861fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian}
19961fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian
20061fd2ab615ab17f6de593e8a8cf475465967ac9cMathias Agopian} // namespace utils
201